From 3b2e37538230062673c6dc79f9f73cc324aa62d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Tue, 22 Sep 2020 17:40:26 +0200 Subject: [PATCH 001/278] WIP --- include/Nazara/Graphics/BasicMaterial.hpp | 72 ++ include/Nazara/Graphics/BasicMaterial.inl | 91 ++ include/Nazara/Graphics/CullingList.hpp | 215 ++++ include/Nazara/Graphics/CullingList.inl | 498 +++++++++ include/Nazara/Graphics/Enums.hpp | 18 + include/Nazara/Graphics/Graphics.hpp | 20 +- include/Nazara/Graphics/Graphics.inl | 16 + include/Nazara/Graphics/Material.hpp | 150 +++ include/Nazara/Graphics/Material.inl | 981 ++++++++++++++++++ include/Nazara/Graphics/MaterialPipeline.hpp | 87 ++ include/Nazara/Graphics/MaterialPipeline.inl | 138 +++ include/Nazara/Graphics/MaterialSettings.hpp | 92 ++ include/Nazara/Graphics/MaterialSettings.inl | 147 +++ .../Nazara/Graphics/PhongLightingMaterial.hpp | 110 ++ .../Nazara/Graphics/PhongLightingMaterial.inl | 156 +++ .../Graphics/PredefinedShaderStructs.hpp | 68 ++ .../Graphics/PredefinedShaderStructs.inl | 9 + include/Nazara/Graphics/RenderQueue.hpp | 101 ++ include/Nazara/Graphics/RenderQueue.inl | 136 +++ include/Nazara/Renderer/RenderPipeline.hpp | 1 - src/Nazara/Graphics/BasicMaterial.cpp | 203 ++++ src/Nazara/Graphics/BasicRenderQueue.cpp | 956 +++++++++++++++++ src/Nazara/Graphics/Graphics.cpp | 25 +- src/Nazara/Graphics/Material.cpp | 487 +++++++++ src/Nazara/Graphics/MaterialPipeline.cpp | 235 +++++ src/Nazara/Graphics/PhongLightingMaterial.cpp | 331 ++++++ .../Graphics/PredefinedShaderStructs.cpp | 167 +++ 27 files changed, 5502 insertions(+), 8 deletions(-) create mode 100644 include/Nazara/Graphics/BasicMaterial.hpp create mode 100644 include/Nazara/Graphics/BasicMaterial.inl create mode 100644 include/Nazara/Graphics/CullingList.hpp create mode 100644 include/Nazara/Graphics/CullingList.inl create mode 100644 include/Nazara/Graphics/Graphics.inl create mode 100644 include/Nazara/Graphics/Material.hpp create mode 100644 include/Nazara/Graphics/Material.inl create mode 100644 include/Nazara/Graphics/MaterialPipeline.hpp create mode 100644 include/Nazara/Graphics/MaterialPipeline.inl create mode 100644 include/Nazara/Graphics/MaterialSettings.hpp create mode 100644 include/Nazara/Graphics/MaterialSettings.inl create mode 100644 include/Nazara/Graphics/PhongLightingMaterial.hpp create mode 100644 include/Nazara/Graphics/PhongLightingMaterial.inl create mode 100644 include/Nazara/Graphics/PredefinedShaderStructs.hpp create mode 100644 include/Nazara/Graphics/PredefinedShaderStructs.inl create mode 100644 include/Nazara/Graphics/RenderQueue.hpp create mode 100644 include/Nazara/Graphics/RenderQueue.inl create mode 100644 src/Nazara/Graphics/BasicMaterial.cpp create mode 100644 src/Nazara/Graphics/BasicRenderQueue.cpp create mode 100644 src/Nazara/Graphics/Material.cpp create mode 100644 src/Nazara/Graphics/MaterialPipeline.cpp create mode 100644 src/Nazara/Graphics/PhongLightingMaterial.cpp create mode 100644 src/Nazara/Graphics/PredefinedShaderStructs.cpp diff --git a/include/Nazara/Graphics/BasicMaterial.hpp b/include/Nazara/Graphics/BasicMaterial.hpp new file mode 100644 index 000000000..a623d973a --- /dev/null +++ b/include/Nazara/Graphics/BasicMaterial.hpp @@ -0,0 +1,72 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_BASIC_MATERIAL_HPP +#define NAZARA_BASIC_MATERIAL_HPP + +#include +#include + +namespace Nz +{ + class NAZARA_GRAPHICS_API BasicMaterial + { + friend class MaterialPipeline; + + public: + BasicMaterial(Material* material); + + inline const TextureRef& GetAlphaMap() const; + float GetAlphaThreshold() const; + Color GetDiffuseColor() const; + inline const TextureRef& GetDiffuseMap() const; + + inline bool HasAlphaMap() const; + inline bool HasAlphaThreshold() const; + inline bool HasDiffuseColor() const; + inline bool HasDiffuseMap() const; + + inline bool SetAlphaMap(const String& textureName); + inline void SetAlphaMap(TextureRef alphaMap); + void SetAlphaThreshold(float alphaThreshold); + void SetDiffuseColor(const Color& diffuse); + inline bool SetDiffuseMap(const String& textureName); + inline void SetDiffuseMap(TextureRef diffuseMap); + + static const std::shared_ptr& GetSettings(); + + private: + struct UniformOffsets + { + std::size_t alphaThreshold; + std::size_t diffuseColor; + }; + + struct TextureIndexes + { + std::size_t alpha; + std::size_t diffuse; + }; + + static bool Initialize(); + static void Uninitialize(); + + MaterialRef m_material; + std::size_t m_uniformBlockIndex; + TextureIndexes m_textureIndexes; + UniformOffsets m_uniformOffsets; + + static std::shared_ptr s_materialSettings; + static std::size_t s_uniformBlockIndex; + static RenderPipelineLayoutRef s_renderPipelineLayout; + static TextureIndexes s_textureIndexes; + static UniformOffsets s_uniformOffsets; + }; +} + +#include + +#endif // NAZARA_BASIC_MATERIAL_HPP diff --git a/include/Nazara/Graphics/BasicMaterial.inl b/include/Nazara/Graphics/BasicMaterial.inl new file mode 100644 index 000000000..79e92e8a2 --- /dev/null +++ b/include/Nazara/Graphics/BasicMaterial.inl @@ -0,0 +1,91 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include + +namespace Nz +{ + inline const TextureRef& BasicMaterial::GetAlphaMap() const + { + NazaraAssert(HasAlphaMap(), "Material has no alpha map slot"); + return m_material->GetTexture(m_textureIndexes.alpha); + } + + inline const TextureRef& BasicMaterial::GetDiffuseMap() const + { + NazaraAssert(HasDiffuseMap(), "Material has no alpha map slot"); + return m_material->GetTexture(m_textureIndexes.diffuse); + } + + inline bool BasicMaterial::HasAlphaMap() const + { + return m_textureIndexes.alpha != MaterialSettings::InvalidIndex; + } + + inline bool BasicMaterial::HasAlphaThreshold() const + { + return m_uniformOffsets.alphaThreshold != MaterialSettings::InvalidIndex; + } + + inline bool BasicMaterial::HasDiffuseColor() const + { + return m_uniformOffsets.diffuseColor != MaterialSettings::InvalidIndex; + } + + inline bool BasicMaterial::HasDiffuseMap() const + { + return m_textureIndexes.diffuse != MaterialSettings::InvalidIndex; + } + + inline bool BasicMaterial::SetAlphaMap(const String& textureName) + { + TextureRef texture = TextureLibrary::Query(textureName); + if (!texture) + { + texture = TextureManager::Get(textureName); + if (!texture) + { + NazaraError("Failed to get alpha map \"" + textureName + "\""); + return false; + } + } + + SetAlphaMap(std::move(texture)); + return true; + } + + inline void BasicMaterial::SetAlphaMap(TextureRef alphaMap) + { + NazaraAssert(HasAlphaMap(), "Material has no alpha map slot"); + m_material->SetTexture(m_textureIndexes.alpha, std::move(alphaMap)); + } + + inline bool BasicMaterial::SetDiffuseMap(const String& textureName) + { + TextureRef texture = TextureLibrary::Query(textureName); + if (!texture) + { + texture = TextureManager::Get(textureName); + if (!texture) + { + NazaraError("Failed to get diffuse map \"" + textureName + "\""); + return false; + } + } + + SetDiffuseMap(std::move(texture)); + return true; + } + + inline void BasicMaterial::SetDiffuseMap(TextureRef diffuseMap) + { + NazaraAssert(HasDiffuseMap(), "Material has no diffuse map slot"); + m_material->SetTexture(m_textureIndexes.diffuse, std::move(diffuseMap)); + } +} + +#include diff --git a/include/Nazara/Graphics/CullingList.hpp b/include/Nazara/Graphics/CullingList.hpp new file mode 100644 index 000000000..7eff97852 --- /dev/null +++ b/include/Nazara/Graphics/CullingList.hpp @@ -0,0 +1,215 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_CULLINGLIST_HPP +#define NAZARA_CULLINGLIST_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + template + class CullingList + { + public: + template class Entry; + class BoxEntry; + class NoTestEntry; + class SphereEntry; + class VolumeEntry; + + template friend class Entry; + friend BoxEntry; + friend NoTestEntry; + friend SphereEntry; + friend VolumeEntry; + + using ResultContainer = std::vector; + + CullingList() = default; + CullingList(const CullingList& renderable) = delete; + CullingList(CullingList&& renderable) = delete; + ~CullingList(); + + std::size_t Cull(const Frustumf& frustum, bool* forceInvalidation = nullptr); + + std::size_t FillWithAllEntries(bool* forceInvalidation = nullptr); + + const ResultContainer& GetFullyVisibleResults() const; + const ResultContainer& GetPartiallyVisibleResults() const; + + BoxEntry RegisterBoxTest(const T* renderable); + NoTestEntry RegisterNoTest(const T* renderable); + SphereEntry RegisterSphereTest(const T* renderable); + VolumeEntry RegisterVolumeTest(const T* renderable); + + CullingList& operator=(const CullingList& renderable) = delete; + CullingList& operator=(CullingList&& renderable) = delete; + + NazaraSignal(OnCullingListRelease, CullingList* /*cullingList*/); + + private: + inline void NotifyBoxUpdate(std::size_t index, const Boxf& boundingVolume); + inline void NotifyForceInvalidation(CullTest type, std::size_t index); + inline void NotifyMovement(CullTest type, std::size_t index, void* oldPtr, void* newPtr); + inline void NotifyRelease(CullTest type, std::size_t index); + inline void NotifySphereUpdate(std::size_t index, const Spheref& sphere); + inline void NotifyVolumeUpdate(std::size_t index, const BoundingVolumef& boundingVolume); + + struct BoxVisibilityEntry + { + Boxf box; + BoxEntry* entry; + const T* renderable; + bool forceInvalidation; + }; + + struct NoTestVisibilityEntry + { + NoTestEntry* entry; + const T* renderable; + bool forceInvalidation; + }; + + struct SphereVisibilityEntry + { + Spheref sphere; + SphereEntry* entry; + const T* renderable; + bool forceInvalidation; + }; + + struct VolumeVisibilityEntry + { + BoundingVolumef volume; + VolumeEntry* entry; + const T* renderable; + bool forceInvalidation; + }; + + std::vector m_boxTestList; + std::vector m_noTestList; + std::vector m_sphereTestList; + std::vector m_volumeTestList; + ResultContainer m_fullyVisibleResults; + ResultContainer m_partiallyVisibleResults; + }; + + template + template + class CullingList::Entry + { + public: + Entry(); + Entry(const Entry&) = delete; + Entry(Entry&& entry); + ~Entry(); + + void ForceInvalidation(); + + CullingList* GetParent() const; + + void UpdateIndex(std::size_t index); + + Entry& operator=(const Entry&) = delete; + Entry& operator=(Entry&& entry); + + protected: + Entry(CullingList* parent, std::size_t index); + + std::size_t m_index; + CullingList* m_parent; + }; + + template + class CullingList::BoxEntry : public CullingList::template Entry + { + friend CullingList; + + using ParentType = Entry; + + public: + BoxEntry(); + BoxEntry(BoxEntry&&) = default; + ~BoxEntry() = default; + + void UpdateBox(const Boxf& box); + + BoxEntry& operator=(BoxEntry&&) = default; + + private: + BoxEntry(CullingList* parent, std::size_t index); + }; + + template + class CullingList::NoTestEntry : public CullingList::template Entry + { + friend CullingList; + + using ParentType = Entry; + + public: + NoTestEntry(); + NoTestEntry(NoTestEntry&&) = default; + ~NoTestEntry() = default; + + NoTestEntry& operator=(NoTestEntry&&) = default; + + private: + NoTestEntry(CullingList* parent, std::size_t index); + }; + + template + class CullingList::SphereEntry : public CullingList::template Entry + { + friend CullingList; + + using ParentType = Entry; + + public: + SphereEntry(); + SphereEntry(SphereEntry&&) = default; + ~SphereEntry() = default; + + void UpdateSphere(const Spheref& sphere); + + SphereEntry& operator=(SphereEntry&&) = default; + + private: + SphereEntry(CullingList* parent, std::size_t index); + }; + + template + class CullingList::VolumeEntry : public CullingList::template Entry + { + friend CullingList; + + using ParentType = Entry; + + public: + VolumeEntry(); + VolumeEntry(VolumeEntry&&) = default; + ~VolumeEntry() = default; + + void UpdateVolume(const BoundingVolumef& sphere); + + VolumeEntry& operator=(VolumeEntry&&) = default; + + private: + VolumeEntry(CullingList* parent, std::size_t index); + }; +} + +#include + +#endif // NAZARA_CULLINGLIST_HPP diff --git a/include/Nazara/Graphics/CullingList.inl b/include/Nazara/Graphics/CullingList.inl new file mode 100644 index 000000000..aa94bc995 --- /dev/null +++ b/include/Nazara/Graphics/CullingList.inl @@ -0,0 +1,498 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + template + CullingList::~CullingList() + { + OnCullingListRelease(this); + } + + template + std::size_t CullingList::Cull(const Frustumf& frustum, bool* forceInvalidation) + { + m_fullyVisibleResults.clear(); + m_partiallyVisibleResults.clear(); + + bool forcedInvalidation = false; + + std::size_t fullyVisibleHash = 5U; + std::size_t partiallyVisibleHash = 5U; + + auto CombineHash = [](std::size_t currentHash, std::size_t newHash) + { + return currentHash * 23 + newHash; + }; + + for (BoxVisibilityEntry& entry : m_boxTestList) + { + switch (frustum.Intersect(entry.box)) + { + case IntersectionSide_Inside: + m_fullyVisibleResults.push_back(entry.renderable); + fullyVisibleHash = CombineHash(fullyVisibleHash, std::hash()(entry.renderable)); + + forcedInvalidation = forcedInvalidation | entry.forceInvalidation; + entry.forceInvalidation = false; + break; + + case IntersectionSide_Intersecting: + m_partiallyVisibleResults.push_back(entry.renderable); + partiallyVisibleHash = CombineHash(partiallyVisibleHash, std::hash()(entry.renderable)); + + forcedInvalidation = forcedInvalidation | entry.forceInvalidation; + entry.forceInvalidation = false; + break; + + case IntersectionSide_Outside: + break; + } + } + + for (NoTestVisibilityEntry& entry : m_noTestList) + { + m_fullyVisibleResults.push_back(entry.renderable); + CombineHash(fullyVisibleHash, std::hash()(entry.renderable)); + + if (entry.forceInvalidation) + { + forcedInvalidation = true; + entry.forceInvalidation = false; + } + } + + for (SphereVisibilityEntry& entry : m_sphereTestList) + { + switch (frustum.Intersect(entry.sphere)) + { + case IntersectionSide_Inside: + m_fullyVisibleResults.push_back(entry.renderable); + fullyVisibleHash = CombineHash(fullyVisibleHash, std::hash()(entry.renderable)); + + forcedInvalidation = forcedInvalidation | entry.forceInvalidation; + entry.forceInvalidation = false; + break; + + case IntersectionSide_Intersecting: + m_partiallyVisibleResults.push_back(entry.renderable); + partiallyVisibleHash = CombineHash(partiallyVisibleHash, std::hash()(entry.renderable)); + + forcedInvalidation = forcedInvalidation | entry.forceInvalidation; + entry.forceInvalidation = false; + break; + + case IntersectionSide_Outside: + break; + } + } + + for (VolumeVisibilityEntry& entry : m_volumeTestList) + { + switch (frustum.Intersect(entry.volume)) + { + case IntersectionSide_Inside: + m_fullyVisibleResults.push_back(entry.renderable); + fullyVisibleHash = CombineHash(fullyVisibleHash, std::hash()(entry.renderable)); + + forcedInvalidation = forcedInvalidation | entry.forceInvalidation; + entry.forceInvalidation = false; + break; + + case IntersectionSide_Intersecting: + m_partiallyVisibleResults.push_back(entry.renderable); + partiallyVisibleHash = CombineHash(partiallyVisibleHash, std::hash()(entry.renderable)); + + forcedInvalidation = forcedInvalidation | entry.forceInvalidation; + entry.forceInvalidation = false; + break; + + case IntersectionSide_Outside: + break; + } + } + + if (forceInvalidation) + *forceInvalidation = forcedInvalidation; + + return 5 + partiallyVisibleHash * 17 + fullyVisibleHash; + } + + template + std::size_t CullingList::FillWithAllEntries(bool* forceInvalidation) + { + m_fullyVisibleResults.clear(); + m_partiallyVisibleResults.clear(); + + bool forcedInvalidation = false; + + std::size_t visibleHash = 5U; + + auto FillWithList = [&](auto& testList) + { + for (auto& entry : testList) + { + m_fullyVisibleResults.push_back(entry.renderable); + visibleHash = visibleHash * 23 + std::hash()(entry.renderable); + + forcedInvalidation = forcedInvalidation | entry.forceInvalidation; + entry.forceInvalidation = false; + } + }; + + FillWithList(m_boxTestList); + FillWithList(m_noTestList); + FillWithList(m_sphereTestList); + FillWithList(m_volumeTestList); + + if (forceInvalidation) + *forceInvalidation = forcedInvalidation; + + return visibleHash; + } + + template + auto CullingList::GetFullyVisibleResults() const -> const ResultContainer& + { + return m_fullyVisibleResults; + } + + template + auto CullingList::GetPartiallyVisibleResults() const -> const ResultContainer& + { + return m_partiallyVisibleResults; + } + + template + auto CullingList::RegisterBoxTest(const T* renderable) -> BoxEntry + { + BoxEntry newEntry(this, m_boxTestList.size()); + m_boxTestList.emplace_back(BoxVisibilityEntry{ Nz::Boxf(), &newEntry, renderable, false }); //< Address of entry will be updated when moving + + return newEntry; + } + + template + auto CullingList::RegisterNoTest(const T* renderable) -> NoTestEntry + { + NoTestEntry newEntry(this, m_volumeTestList.size()); + m_noTestList.emplace_back(NoTestVisibilityEntry{&newEntry, renderable, false}); //< Address of entry will be updated when moving + + return newEntry; + } + + template + auto CullingList::RegisterSphereTest(const T* renderable) -> SphereEntry + { + SphereEntry newEntry(this, m_sphereTestList.size()); + m_sphereTestList.emplace_back(SphereVisibilityEntry{Nz::Spheref(), &newEntry, renderable, false}); //< Address of entry will be updated when moving + + return newEntry; + } + + template + auto CullingList::RegisterVolumeTest(const T* renderable) -> VolumeEntry + { + VolumeEntry newEntry(this, m_volumeTestList.size()); + m_volumeTestList.emplace_back(VolumeVisibilityEntry{Nz::BoundingVolumef(), &newEntry, renderable, false}); //< Address of entry will be updated when moving + + return newEntry; + } + + template + inline void CullingList::NotifyBoxUpdate(std::size_t index, const Boxf& box) + { + m_boxTestList[index].box = box; + } + + template + void CullingList::NotifyForceInvalidation(CullTest type, std::size_t index) + { + switch (type) + { + case CullTest::Box: + { + m_boxTestList[index].forceInvalidation = true; + break; + } + + case CullTest::NoTest: + { + m_noTestList[index].forceInvalidation = true; + break; + } + + case CullTest::Sphere: + { + m_sphereTestList[index].forceInvalidation = true; + break; + } + + case CullTest::Volume: + { + m_volumeTestList[index].forceInvalidation = true; + break; + } + + default: + NazaraInternalError("Unhandled culltype"); + break; + } + } + + template + void CullingList::NotifyMovement(CullTest type, std::size_t index, void* oldPtr, void* newPtr) + { + NazaraUnused(oldPtr); + + switch (type) + { + case CullTest::Box: + { + BoxVisibilityEntry& entry = m_boxTestList[index]; + NazaraAssert(entry.entry == oldPtr, "Invalid box entry"); + + entry.entry = static_cast(newPtr); + break; + } + + case CullTest::NoTest: + { + NoTestVisibilityEntry& entry = m_noTestList[index]; + NazaraAssert(entry.entry == oldPtr, "Invalid entry"); + + entry.entry = static_cast(newPtr); + break; + } + + case CullTest::Sphere: + { + SphereVisibilityEntry& entry = m_sphereTestList[index]; + NazaraAssert(entry.entry == oldPtr, "Invalid sphere entry"); + + entry.entry = static_cast(newPtr); + break; + } + + case CullTest::Volume: + { + VolumeVisibilityEntry& entry = m_volumeTestList[index]; + NazaraAssert(entry.entry == oldPtr, "Invalid volume entry"); + + entry.entry = static_cast(newPtr); + break; + } + + default: + NazaraInternalError("Unhandled culltype"); + break; + } + } + + template + void CullingList::NotifyRelease(CullTest type, std::size_t index) + { + switch (type) + { + case CullTest::Box: + { + m_boxTestList[index] = std::move(m_boxTestList.back()); + m_boxTestList[index].entry->UpdateIndex(index); + m_boxTestList.pop_back(); + break; + } + + case CullTest::NoTest: + { + m_noTestList[index] = std::move(m_noTestList.back()); + m_noTestList[index].entry->UpdateIndex(index); + m_noTestList.pop_back(); + break; + } + + case CullTest::Sphere: + { + m_sphereTestList[index] = std::move(m_sphereTestList.back()); + m_sphereTestList[index].entry->UpdateIndex(index); + m_sphereTestList.pop_back(); + break; + } + + case CullTest::Volume: + { + m_volumeTestList[index] = std::move(m_volumeTestList.back()); + m_volumeTestList[index].entry->UpdateIndex(index); + m_volumeTestList.pop_back(); + break; + } + + default: + NazaraInternalError("Unhandled culltype"); + break; + } + } + + template + void CullingList::NotifySphereUpdate(std::size_t index, const Spheref& sphere) + { + m_sphereTestList[index].sphere = sphere; + } + + template + void CullingList::NotifyVolumeUpdate(std::size_t index, const BoundingVolumef& boundingVolume) + { + m_volumeTestList[index].volume = boundingVolume; + } + + ////////////////////////////////////////////////////////////////////////// + + template + template + CullingList::Entry::Entry() : + m_parent(nullptr) + { + } + + template + template + CullingList::Entry::Entry(CullingList* parent, std::size_t index) : + m_index(index), + m_parent(parent) + { + } + + template + template + CullingList::Entry::Entry(Entry&& entry) : + m_index(entry.m_index), + m_parent(entry.m_parent) + { + if (m_parent) + m_parent->NotifyMovement(Type, m_index, &entry, this); + + entry.m_parent = nullptr; + } + + template + template + CullingList::Entry::~Entry() + { + if (m_parent) + m_parent->NotifyRelease(Type, m_index); + } + + template + template + void CullingList::Entry::ForceInvalidation() + { + m_parent->NotifyForceInvalidation(Type, m_index); + } + + template + template + CullingList* CullingList::Entry::GetParent() const + { + return m_parent; + } + + template + template + void CullingList::Entry::UpdateIndex(std::size_t index) + { + m_index = index; + } + + template + template + typename CullingList::template Entry& CullingList::Entry::operator=(Entry&& entry) + { + m_index = entry.m_index; + m_parent = entry.m_parent; + if (m_parent) + m_parent->NotifyMovement(Type, m_index, &entry, this); + + entry.m_parent = nullptr; + + return *this; + } + + ////////////////////////////////////////////////////////////////////////// + + template + CullingList::BoxEntry::BoxEntry() : + ParentType() + { + } + + template + CullingList::BoxEntry::BoxEntry(CullingList* parent, std::size_t index) : + ParentType(parent, index) + { + } + + template + void CullingList::BoxEntry::UpdateBox(const Boxf& box) + { + this->m_parent->NotifyBoxUpdate(this->m_index, box); + } + + ////////////////////////////////////////////////////////////////////////// + + template + CullingList::NoTestEntry::NoTestEntry() : + ParentType() + { + } + + template + CullingList::NoTestEntry::NoTestEntry(CullingList* parent, std::size_t index) : + ParentType(parent, index) + { + } + + ////////////////////////////////////////////////////////////////////////// + + template + CullingList::SphereEntry::SphereEntry() : + ParentType() + { + } + + template + CullingList::SphereEntry::SphereEntry(CullingList* parent, std::size_t index) : + ParentType(parent, index) + { + } + + template + void CullingList::SphereEntry::UpdateSphere(const Spheref& sphere) + { + this->m_parent->NotifySphereUpdate(this->m_index, sphere); + } + + ////////////////////////////////////////////////////////////////////////// + + template + CullingList::VolumeEntry::VolumeEntry() : + ParentType() + { + } + + template + CullingList::VolumeEntry::VolumeEntry(CullingList* parent, std::size_t index) : + ParentType(parent, index) + { + } + + template + void CullingList::VolumeEntry::UpdateVolume(const BoundingVolumef& volume) + { + this->m_parent->NotifyVolumeUpdate(this->m_index, volume); + } +} + +#include diff --git a/include/Nazara/Graphics/Enums.hpp b/include/Nazara/Graphics/Enums.hpp index f847d5fe4..ca7288e87 100644 --- a/include/Nazara/Graphics/Enums.hpp +++ b/include/Nazara/Graphics/Enums.hpp @@ -9,6 +9,24 @@ namespace Nz { + enum class CullTest + { + Box, + NoTest, + Sphere, + Volume + }; + + enum PredefinedShaderBinding + { + PredefinedShaderBinding_TexOverlay, + PredefinedShaderBinding_UboInstanceData, + PredefinedShaderBinding_UboLighData, + PredefinedShaderBinding_UboViewerData, + + PredefinedShaderBinding_Max = PredefinedShaderBinding_UboViewerData + }; + } #endif // NAZARA_ENUMS_GRAPHICS_HPP diff --git a/include/Nazara/Graphics/Graphics.hpp b/include/Nazara/Graphics/Graphics.hpp index 71f7f533a..7cf692bc4 100644 --- a/include/Nazara/Graphics/Graphics.hpp +++ b/include/Nazara/Graphics/Graphics.hpp @@ -10,9 +10,12 @@ #include #include #include +#include namespace Nz { + class RenderDevice; + class NAZARA_GRAPHICS_API Graphics : public ModuleBase { friend ModuleBase; @@ -20,14 +23,25 @@ namespace Nz public: using Dependencies = TypeList; - struct Config {}; + struct Config; - Graphics(Config /*config*/); - ~Graphics(); + Graphics(Config config); + ~Graphics() = default; + + inline RenderDevice& GetRenderDevice(); + + struct Config + { + bool useDedicatedRenderDevice = true; + }; private: + std::shared_ptr m_renderDevice; + static Graphics* s_instance; }; } +#include + #endif diff --git a/include/Nazara/Graphics/Graphics.inl b/include/Nazara/Graphics/Graphics.inl new file mode 100644 index 000000000..ba9766953 --- /dev/null +++ b/include/Nazara/Graphics/Graphics.inl @@ -0,0 +1,16 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + inline RenderDevice& Graphics::GetRenderDevice() + { + return *m_renderDevice; + } +} + +#include diff --git a/include/Nazara/Graphics/Material.hpp b/include/Nazara/Graphics/Material.hpp new file mode 100644 index 000000000..31e732125 --- /dev/null +++ b/include/Nazara/Graphics/Material.hpp @@ -0,0 +1,150 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_BASE_MATERIAL_HPP +#define NAZARA_BASE_MATERIAL_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + struct NAZARA_GRAPHICS_API MaterialParams : ResourceParameters + { + bool loadAlphaMap = true; + bool loadDiffuseMap = true; + bool loadEmissiveMap = true; + bool loadHeightMap = true; + bool loadNormalMap = true; + bool loadSpecularMap = true; + std::string shaderName = "Basic"; + + bool IsValid() const; + }; + + class NAZARA_GRAPHICS_API Material : public RefCounted, public Resource + { + public: + Material(std::shared_ptr settings); + inline Material(const Material& material); + inline ~Material(); + + void Apply(const MaterialPipeline::Instance& instance) const; + + void BuildFromParameters(const ParameterList& matData, const MaterialParams& matParams = MaterialParams()); + + inline void Configure(const MaterialPipeline* pipeline); + inline void Configure(const MaterialPipelineInfo& pipelineInfo); + inline bool Configure(const String& pipelineName); + + inline void EnableAlphaTest(bool alphaTest); + inline void EnableBlending(bool blending); + inline void EnableColorWrite(bool colorWrite); + inline void EnableDepthBuffer(bool depthBuffer); + inline void EnableDepthSorting(bool depthSorting); + inline void EnableDepthWrite(bool depthWrite); + inline void EnableFaceCulling(bool faceCulling); + inline void EnableReflectionMapping(bool reflection); + inline void EnableScissorTest(bool scissorTest); + inline void EnableShadowCasting(bool castShadows); + inline void EnableShadowReceive(bool receiveShadows); + inline void EnableStencilTest(bool stencilTest); + inline void EnableVertexColor(bool vertexColor); + + inline void EnsurePipelineUpdate() const; + + inline RendererComparison GetDepthFunc() const; + inline BlendFunc GetDstBlend() const; + inline FaceSide GetFaceCulling() const; + inline FaceFilling GetFaceFilling() const; + inline float GetLineWidth() const; + inline const MaterialPipeline* GetPipeline() const; + inline const MaterialPipelineInfo& GetPipelineInfo() const; + inline float GetPointSize() const; + inline const std::shared_ptr& GetSettings() const; + inline const std::shared_ptr& GetShader() const; + inline BlendFunc GetSrcBlend() const; + inline UniformBuffer* GetSharedUniformBuffer(std::size_t bufferIndex) const; + inline const std::shared_ptr& GetTexture(std::size_t textureIndex) const; + inline const std::shared_ptr& GetTextureSampler(std::size_t textureIndex) const; + inline UniformBufferRef& GetUniformBuffer(std::size_t bufferIndex); + inline const UniformBufferRef& GetUniformBuffer(std::size_t bufferIndex) const; + + inline bool HasDepthMaterial() const; + inline bool HasTexture(std::size_t textureIndex) const; + inline bool HasVertexColor() const; + + inline bool IsAlphaTestEnabled() const; + inline bool IsBlendingEnabled() const; + inline bool IsColorWriteEnabled() const; + inline bool IsDepthBufferEnabled() const; + inline bool IsDepthSortingEnabled() const; + inline bool IsDepthWriteEnabled() const; + inline bool IsFaceCullingEnabled() const; + inline bool IsReflectionMappingEnabled() const; + inline bool IsScissorTestEnabled() const; + inline bool IsStencilTestEnabled() const; + inline bool IsShadowCastingEnabled() const; + inline bool IsShadowReceiveEnabled() const; + + void SaveToParameters(ParameterList* matData); + + inline void SetDepthFunc(RendererComparison depthFunc); + inline void SetDstBlend(BlendFunc func); + inline void SetFaceCulling(FaceSide faceSide); + inline void SetFaceFilling(FaceFilling filling); + inline void SetLineWidth(float lineWidth); + inline void SetPointSize(float pointSize); + inline void SetShader(std::shared_ptr shader); + inline void SetUniformBuffer(std::size_t bufferIndex, UniformBuffer* uniformBuffer); + inline void SetSrcBlend(BlendFunc func); + inline void SetTexture(std::size_t textureIndex, Texture* texture); + inline void SetTextureSampler(std::size_t textureIndex, const TextureSampler& sampler); + + inline Material& operator=(const Material& material); + + // Signals: + NazaraSignal(OnMaterialRelease, const Material* /*material*/); + + private: + inline void InvalidatePipeline(); + inline void UpdatePipeline() const; + + struct MaterialTexture + { + std::shared_ptr sampler; + std::shared_ptr texture; + }; + + std::shared_ptr m_settings; + std::vector m_textures; + std::vector m_uniformBuffers; + mutable const MaterialPipeline* m_pipeline; + MaterialPipelineInfo m_pipelineInfo; + mutable bool m_pipelineUpdated; + bool m_shadowCastingEnabled; + }; +} + +#include + +#endif // NAZARA_BASE_MATERIAL_HPP diff --git a/include/Nazara/Graphics/Material.inl b/include/Nazara/Graphics/Material.inl new file mode 100644 index 000000000..d60bde1c1 --- /dev/null +++ b/include/Nazara/Graphics/Material.inl @@ -0,0 +1,981 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include + +namespace Nz +{ + /*! + * \brief Constructs a Material object by assignation + * + * \param material Material to copy into this + */ + inline Material::Material(const Material& material) : + RefCounted(), + Resource(material) + { + operator=(material); + } + + /*! + * \brief Destructs the object and calls OnMaterialRelease + * + * \see OnMaterialRelease + */ + inline Material::~Material() + { + OnMaterialRelease(this); + } + + /*! + * \brief Reset material pipeline state + * + * Sets the material pipeline + * + * \remark pipeline must be valid + * + * \see Configure + */ + inline void Material::Configure(const MaterialPipeline* pipeline) + { + NazaraAssert(pipeline, "Invalid material pipeline"); + + m_pipeline = pipeline; + m_pipelineInfo = m_pipeline->GetInfo(); + m_pipelineUpdated = true; + } + + /*! + * \brief Reset material pipeline state + * + * Sets the material pipeline using pipeline info + * + * \remark pipeline must be valid + * + * \see Configure + */ + inline void Material::Configure(const MaterialPipelineInfo& pipelineInfo) + { + m_pipelineInfo = pipelineInfo; + + InvalidatePipeline(); + } + + /*! + * \brief Reset material pipeline state + * + * Sets the material pipeline using a name to lookup in the MaterialPipelineLibrary + * + * \return True if the material pipeline was found in the library + * + * \see Configure + */ + inline bool Material::Configure(const String& pipelineName) + { + MaterialPipelineRef pipeline = MaterialPipelineLibrary::Query(pipelineName); + if (!pipeline) + { + NazaraError("Failed to get pipeline \"" + pipelineName + "\""); + return false; + } + + Configure(std::move(pipeline)); + return true; + } + + /*! + * \brief Enable/Disable alpha test for this material + * + * When enabled, all objects using this material will be rendered using alpha testing, + * rejecting pixels if their alpha component is under a defined threshold. + * This allows some kind of transparency with a much cheaper cost as it doesn't prevent any optimization (as deferred rendering or batching). + * + * \param alphaTest Defines if this material will use alpha testing + * + * \remark Invalidates the pipeline + * + * \see IsAlphaTestEnabled + * \see SetAlphaThreshold + */ + inline void Material::EnableAlphaTest(bool alphaTest) + { + m_pipelineInfo.alphaTest = alphaTest; + + InvalidatePipeline(); + } + + /*! + * \brief Enable/Disable blending for this material + * + * When enabled, all objects using this material will be rendered using blending, obeying the dstBlend and srcBlend parameters + * This is useful with translucent objects, but will reduces performance as it prevents some optimizations (as deferred rendering) + * + * \param blending Defines if this material will use blending + * + * \remark Invalidates the pipeline + * + * \see IsBlendingEnabled + * \see SetDstBlend + * \see SetSrcBlend + */ + inline void Material::EnableBlending(bool blending) + { + m_pipelineInfo.blending = blending; + + InvalidatePipeline(); + } + + /*! + * \brief Enable/Disable color writing for this material + * + * \param colorWrite Defines if this material will use color writing + * + * \remark Invalidates the pipeline + * + * \see IsColorWritingEnabled + */ + inline void Material::EnableColorWrite(bool colorWrite) + { + m_pipelineInfo.colorWrite = colorWrite; + + InvalidatePipeline(); + } + + /*! + * \brief Enable/Disable depth buffer for this material + * + * When enabled, all objects using this material will be rendered using a depth buffer, if the RenderTarget has one. + * This will enable Depth Test, preventing further fragments to render on top of closer ones. + * + * This parameter is required for depth writing. + * + * In order to enable depth writing without enabling depth test, set the depth comparison function to RendererComparison_Never + * + * \param depthBuffer Defines if this material will use depth buffer + * + * \remark Invalidates the pipeline + * + * \see EnableDepthWrite + * \see IsDepthBufferEnabled + * \see SetDepthFunc + */ + inline void Material::EnableDepthBuffer(bool depthBuffer) + { + m_pipelineInfo.depthBuffer = depthBuffer; + + InvalidatePipeline(); + } + + /*! + * \brief Enable/Disable depth sorting for this material + * + * When enabled, all objects using this material will be rendered far from near + * This is useful with translucent objects, but will reduces performance as it breaks batching + * + * \param depthSorting Defines if this material will use depth sorting + * + * \remark Depth sorting may not be perfect (may be object-sorting instead of triangle-sorting) + * \remark Invalidates the pipeline + * + * \see IsDepthSortingEnabled + */ + inline void Material::EnableDepthSorting(bool depthSorting) + { + m_pipelineInfo.depthSorting = depthSorting; + + InvalidatePipeline(); + } + + /*! + * \brief Enable/Disable depth writing for this material + * + * When enabled, and if depth buffer is enabled and present, all fragments generated with this material will write + * to the depth buffer if they pass depth test. + * + * This is usually disabled with translucent objects, as depth test is wanted to prevent them from rendering on top of opaque objects but + * not depth writing (which could make other translucent fragments to fail depth test) + * + * \param depthBuffer Defines if this material will use depth write + * + * \remark Invalidates the pipeline + * + * \see EnableDepthBuffer + * \see IsDepthWriteEnabled + */ + inline void Material::EnableDepthWrite(bool depthWrite) + { + m_pipelineInfo.depthWrite = depthWrite; + + InvalidatePipeline(); + } + + /*! + * \brief Enable/Disable face culling for this material + * + * When enabled, the material prevents front and/or back faces from rendering. + * This is commonly used as an optimization to prevent processing of hidden faces by the rendering device. + * + * Use SetFaceCulling to control which side will be eliminated. + * + * \param faceCulling Defines if this material will use face culling + * + * \remark Invalidates the pipeline + * + * \see IsFaceCullingEnabled + * \see SetFaceCulling + */ + inline void Material::EnableFaceCulling(bool faceCulling) + { + m_pipelineInfo.faceCulling = faceCulling; + + InvalidatePipeline(); + } + + /*! + * \brief Enable/Disable reflection mapping for this material + * + * When enabled, the material will render reflections from the object environment according to the reflection mode. + * Whether or not this is expensive depends of the reflection mode and size. + * + * Please note this is only a hint for the render technique, and reflections can be forcefully enabled or disabled depending on the material shader. + * + * Use SetReflectionMode and SetReflectionSize to control reflection quality. + * + * \param reflection Defines if this material should use reflection mapping + * + * \remark May invalidates the pipeline + * + * \see IsReflectionMappingEnabled + * \see SetReflectionMode + * \see SetReflectionSize + */ + inline void Material::EnableReflectionMapping(bool reflection) + { + m_pipelineInfo.reflectionMapping = reflection; + + InvalidatePipeline(); + } + + /*! + * \brief Enable/Disable scissor test for this material + * + * When enabled, the material prevents fragments out of the scissor box to be rendered. + * This can be useful with GUI, where widgets must not be rendered outside of their parent rendering area. + * + * \param scissorTest Defines if this material will use scissor test + * + * \remark Invalidates the pipeline + * + * \see IsScissorTestEnabled + */ + inline void Material::EnableScissorTest(bool scissorTest) + { + m_pipelineInfo.scissorTest = scissorTest; + + InvalidatePipeline(); + } + + /*! + * \brief Enable/Disable shadow casting for this material + * + * When enabled, all objects using this material will be allowed to cast shadows upon any objects using a material with shadow receiving enabled. + * The depth material replaces this one when rendering shadows. + * + * \param castShadows Defines if this material will be allowed to cast shadows + * + * \remark Does not invalidate the pipeline + * + * \see EnableShadowReceive + * \see IsShadowCastingEnabled + * \see SetDepthMaterial + */ + inline void Material::EnableShadowCasting(bool castShadows) + { + // Has no influence on pipeline + m_shadowCastingEnabled = castShadows; + } + + /*! + * \brief Enable/Disable shadow receiving for this material + * + * When enabled, all objects using this material will be allowed to be casted shadows upon themselves + * Disabling this can be helpful to prevent some rendering artifacts (especially with translucent objects) + * + * \param receiveShadows Defines if this material will be able to receive shadows + * + * \remark Invalidates the pipeline + * + * \see IsShadowReceiveEnabled + */ + inline void Material::EnableShadowReceive(bool receiveShadows) + { + m_pipelineInfo.shadowReceive = receiveShadows; + + InvalidatePipeline(); + } + + /*! + * \brief Enable/Disable stencil test for this material + * + * When enabled, all fragments must pass the stencil test to be rendered. + * + * \param scissorTest Defines if this material will use stencil test + * + * \remark Invalidates the pipeline + * + * \see IsStencilTestEnabled + */ + inline void Material::EnableStencilTest(bool stencilTest) + { + m_pipelineInfo.stencilTest = stencilTest; + + InvalidatePipeline(); + } + + /*! + * \brief Enable/Disable vertex coloring on this material + * + * This is a temporary option, until the new material pipeline system is ready, allowing to enable vertex coloring. + * This option only works with meshes using vertex colors. + * + * \param vertexColor Defines if this material will use vertex color or not + * + * \remark Invalidates the pipeline + * + * \see HasVertexColor + */ + inline void Material::EnableVertexColor(bool vertexColor) + { + m_pipelineInfo.hasVertexColor = vertexColor; + + InvalidatePipeline(); + } + + /*! + * \brief Ensures the pipeline gets updated + * + * When the pipeline gets invalidated, it's not updated until required (per example by calling GetPipeline). + * Using this function forces the pipeline update, making GetPipeline thread-safe as long as the pipeline does not get invalidated. + * + * \see GetPipeline + */ + inline void Material::EnsurePipelineUpdate() const + { + if (!m_pipelineUpdated) + UpdatePipeline(); + } + + /*! + * \brief Gets the function to compare depth + * + * \return Function comparing the depth of two materials + * + * \see EnableDepthTest + * \see SetAmbientColor + */ + inline RendererComparison Material::GetDepthFunc() const + { + return m_pipelineInfo.depthCompare; + } + + /*! + * \brief Gets the depth material + * + * \return Constant reference to the depth material + * + * \see EnableShadowCasting + */ + inline const MaterialRef& Material::GetDepthMaterial() const + { + return m_depthMaterial; + } + + /*! + * \brief Gets the dst in blend + * + * \return Function for dst blending + * + * \see SetDstBlend + */ + inline BlendFunc Material::GetDstBlend() const + { + return m_pipelineInfo.dstBlend; + } + + /*! + * \brief Gets the face culling + * + * \return Current face culling side + * + * \see SetFaceCulling + */ + inline FaceSide Material::GetFaceCulling() const + { + return m_pipelineInfo.cullingSide; + } + + /*! + * \brief Gets the face filling + * \return Current face filling + */ + inline FaceFilling Material::GetFaceFilling() const + { + return m_pipelineInfo.faceFilling; + } + + /*! + * \brief Gets the line width of this material + * \return Line width + */ + inline float Material::GetLineWidth() const + { + return m_pipelineInfo.lineWidth; + } + + /*! + * \brief Gets the render states + * \return Constant reference to the render states + */ + inline const MaterialPipeline* Material::GetPipeline() const + { + EnsurePipelineUpdate(); + + return m_pipeline; + } + + /*! + * \brief Gets the pipeline informations + * \return Constant reference to the pipeline info + */ + inline const MaterialPipelineInfo& Material::GetPipelineInfo() const + { + return m_pipelineInfo; + } + + /*! + * \brief Gets the point size of this material + * \return Point size + */ + inline float Material::GetPointSize() const + { + return m_pipelineInfo.pointSize; + } + + /*! + * \brief Gets the reflection mode of the material + * + * \return Current reflection mode + * + * \see SetReflectionMode + */ + inline ReflectionMode Material::GetReflectionMode() const + { + return m_reflectionMode; + } + + inline const std::shared_ptr& Material::GetSettings() const + { + return m_settings; + } + + /*! + * \brief Gets the über-shader used by this material + * \return Constant pointer to the über-shader used + */ + inline const UberShader* Material::GetShader() const + { + return m_pipelineInfo.uberShader; + } + + /*! + * \brief Gets the src in blend + * \return Function for src blending + */ + inline BlendFunc Material::GetSrcBlend() const + { + return m_pipelineInfo.srcBlend; + } + + inline const TextureRef& Material::GetTexture(std::size_t textureIndex) const + { + NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index"); + return m_textures[textureIndex].texture; + } + + inline TextureSampler& Material::GetTextureSampler(std::size_t textureIndex) + { + NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index"); + return m_textures[textureIndex].sampler; + } + + inline const TextureSampler& Material::GetTextureSampler(std::size_t textureIndex) const + { + NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index"); + return m_textures[textureIndex].sampler; + } + + inline UniformBufferRef& Material::GetUniformBuffer(std::size_t bufferIndex) + { + NazaraAssert(bufferIndex < m_uniformBuffers.size(), "Invalid uniform buffer index"); + return m_uniformBuffers[bufferIndex]; + } + + inline const UniformBufferRef& Material::GetUniformBuffer(std::size_t bufferIndex) const + { + NazaraAssert(bufferIndex < m_uniformBuffers.size(), "Invalid uniform buffer index"); + return m_uniformBuffers[bufferIndex]; + } + + inline bool Material::HasDepthMaterial() const + { + return m_depthMaterial.IsValid(); + } + + inline bool Material::HasTexture(std::size_t textureIndex) const + { + Texture* texture = GetTexture(textureIndex); + return texture && texture->IsValid(); + } + + /*! + * \brief Checks whether this material uses vertex coloring + * \return true If it is the case + */ + inline bool Material::HasVertexColor() const + { + return m_pipelineInfo.hasVertexColor; + } + + /*! + * \brief Checks whether this material has alpha test enabled + * \return true If it is the case + */ + inline bool Material::IsAlphaTestEnabled() const + { + return m_pipelineInfo.alphaTest; + } + + /*! + * \brief Checks whether this material has blending enabled + * \return true If it is the case + */ + inline bool Material::IsBlendingEnabled() const + { + return m_pipelineInfo.blending; + } + + /*! + * \brief Checks whether this material has color write enabled + * \return true If it is the case + */ + inline bool Material::IsColorWriteEnabled() const + { + return m_pipelineInfo.colorWrite; + } + + /*! + * \brief Checks whether this material has depth buffer enabled + * \return true If it is the case + */ + inline bool Material::IsDepthBufferEnabled() const + { + return m_pipelineInfo.depthBuffer; + } + + /*! + * \brief Checks whether this material has depth sorting enabled + * \return true If it is the case + */ + inline bool Material::IsDepthSortingEnabled() const + { + return m_pipelineInfo.depthSorting; + } + + /*! + * \brief Checks whether this material has depth writing enabled + * \return true If it is the case + */ + inline bool Material::IsDepthWriteEnabled() const + { + return m_pipelineInfo.depthWrite; + } + + /*! + * \brief Checks whether this material has face culling enabled + * \return true If it is the case + */ + inline bool Material::IsFaceCullingEnabled() const + { + return m_pipelineInfo.faceCulling; + } + + /*! + * \brief Checks whether this material has reflection mapping enabled + * \return true If it is the case + * + * \see EnableReflectionMapping + */ + inline bool Material::IsReflectionMappingEnabled() const + { + return m_pipelineInfo.reflectionMapping; + } + + /*! + * \brief Checks whether this material has scissor test enabled + * \return true If it is the case + */ + inline bool Material::IsScissorTestEnabled() const + { + return m_pipelineInfo.scissorTest; + } + + /*! + * \brief Checks whether this material has stencil test enabled + * \return true If it is the case + */ + inline bool Material::IsStencilTestEnabled() const + { + return m_pipelineInfo.stencilTest; + } + + /*! + * \brief Checks whether this material cast shadow + * \return true If it is the case + */ + inline bool Material::IsShadowCastingEnabled() const + { + return m_shadowCastingEnabled; + } + + /*! + * \brief Checks whether this material receive shadow + * \return true If it is the case + */ + inline bool Material::IsShadowReceiveEnabled() const + { + return m_pipelineInfo.shadowReceive; + } + + /*! + * \brief Sets the depth functor + * + * \param depthFunc + * + * \remark Invalidates the pipeline + */ + inline void Material::SetDepthFunc(RendererComparison depthFunc) + { + m_pipelineInfo.depthFunc = depthFunc; + + InvalidatePipeline(); + } + + /*! + * \brief Sets the depth material + * \return true If successful + * + * \param depthMaterial Material for depth + */ + inline void Material::SetDepthMaterial(MaterialRef depthMaterial) + { + m_depthMaterial = std::move(depthMaterial); + } + + /*! + * \brief Sets the dst in blend + * + * \param func Function for dst blending + * + * \remark Invalidates the pipeline + */ + inline void Material::SetDstBlend(BlendFunc func) + { + m_pipelineInfo.dstBlend = func; + + InvalidatePipeline(); + } + + /*! + * \brief Sets the face culling + * + * \param faceSide Face to cull + * + * \remark Invalidates the pipeline + */ + inline void Material::SetFaceCulling(FaceSide faceSide) + { + m_pipelineInfo.cullingSide = faceSide; + + InvalidatePipeline(); + } + + /*! + * \brief Sets the face filling + * + * \param filling Face to fill + * + * \remark Invalidates the pipeline + */ + inline void Material::SetFaceFilling(FaceFilling filling) + { + m_pipelineInfo.faceFilling = filling; + + InvalidatePipeline(); + } + + /*! + * \brief Sets the line width for this material + * + * This parameter is used when rendering lines, to define the width (in pixels) the line will take on the framebuffer + * + * \param lineWidth Width of the line + * + * \remark Invalidates the pipeline + * + * \see GetLineWidth + */ + inline void Material::SetLineWidth(float lineWidth) + { + m_pipelineInfo.lineWidth = lineWidth; + + InvalidatePipeline(); + } + + /*! + * \brief Sets the point size for this material + * + * This parameter is used when rendering points, to define the size (in pixels) the point will take on the framebuffer + * + * \param pointSize Size of the point + * + * \remark Invalidates the pipeline + * + * \see GetPointSize + */ + inline void Material::SetPointSize(float pointSize) + { + m_pipelineInfo.pointSize = pointSize; + + InvalidatePipeline(); + } + + /*! + * \brief Changes reflection mode of the material + * + * When reflections are enabled, the material will render reflections from the object environment according to the reflection mode. + * This function does change the reflection mode used by the material. + * + * Skyboxes reflections are the cheapest but are static and thus can't reflect other objects. + * Probes reflections are cheap, depending on probes reflection mode, but require regular probe finding from objects using it. + * Real-time reflections are expensive but provide the most accurate reflection map (and can reflect other objects around). + * + * \param reflectionMode The new reflection mode this material should use + * + * \remark May invalidates the pipeline + * + * \see EnableReflectionMapping + * \see IsReflectionMappingEnabled + * \see SetReflectionSize + */ + inline void Material::SetReflectionMode(ReflectionMode reflectionMode) + { + if (m_reflectionMode != reflectionMode) + { + OnMaterialReflectionModeChange(this, reflectionMode); + + m_reflectionMode = reflectionMode; + } + } + + /*! + * \brief Sets the shader with a constant reference to a ubershader + * + * \param uberShader Uber shader to apply + * + * \remark Invalidates the pipeline + * + * \see GetShader + */ + inline void Material::SetShader(UberShaderConstRef uberShader) + { + m_pipelineInfo.uberShader = std::move(uberShader); + + InvalidatePipeline(); + } + + /*! + * \brief Sets the shader by name + * \return true If successful + * + * \param uberShaderName Named shader + */ + inline bool Material::SetShader(const String& uberShaderName) + { + UberShaderConstRef uberShader = UberShaderLibrary::Get(uberShaderName); + if (!uberShader) + return false; + + SetShader(std::move(uberShader)); + return true; + } + + inline void Material::SetUniformBuffer(std::size_t bufferIndex, UniformBuffer* uniformBuffer) + { + NazaraAssert(bufferIndex < m_uniformBuffers.size(), "Invalid shared uniform buffer index"); + m_uniformBuffers[bufferIndex] = uniformBuffer; + } + + inline void Material::SetTexture(std::size_t textureIndex, Texture* texture) + { + NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index"); + m_textures[textureIndex].texture = texture; + + if (texture) + m_pipelineInfo.textures |= UInt64(1) << UInt64(textureIndex); + else + m_pipelineInfo.textures &= ~(UInt64(1) << UInt64(textureIndex)); + + InvalidatePipeline(); + } + + inline void Material::SetTextureSampler(std::size_t textureIndex, const TextureSampler& sampler) + { + NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index"); + m_textures[textureIndex].sampler = sampler; + } + + /*! + * \brief Sets the src in blend + * + * \param func Function for src blending + * + * \remark Invalidates the pipeline + * + * \see GetSrcBlend + */ + inline void Material::SetSrcBlend(BlendFunc func) + { + m_pipelineInfo.srcBlend = func; + + InvalidatePipeline(); + } + + /*! + * \brief Sets the current material with the content of the other one + * \return A reference to this + * + * \param material The other Material + */ + inline Material& Material::operator=(const Material& material) + { + Resource::operator=(material); + + m_settings = material.m_settings; + m_textures = material.m_textures; + m_depthMaterial = material.m_depthMaterial; + m_pipeline = material.m_pipeline; + m_pipelineInfo = material.m_pipelineInfo; + m_pipelineUpdated = material.m_pipelineUpdated; + m_shadowCastingEnabled = material.m_shadowCastingEnabled; + m_reflectionSize = material.m_reflectionSize; + + m_pipelineInfo.settings = m_settings; + + for (std::size_t i = 0; i < m_uniformBuffers.size(); ++i) + { + const UniformBuffer* sourceBuffer = material.GetUniformBuffer(i); + UniformBuffer* targetBuffer = m_uniformBuffers[i] = UniformBuffer::New(sourceBuffer->GetEndOffset() - sourceBuffer->GetStartOffset(), DataStorage_Hardware, BufferUsage_Dynamic); + if (!targetBuffer->CopyContent(sourceBuffer)) + NazaraError("Failed to copy uniform buffer content"); + } + + SetReflectionMode(material.GetReflectionMode()); + return *this; + } + + /*! + * \brief Gets the default material + * + * \return Reference to the default material + * + * \remark This material should NOT be modified as it would affect all objects using it + */ + inline MaterialRef Material::GetDefault() + { + return s_defaultMaterial; + } + + inline int Material::GetTextureUnit(TextureMap textureMap) + { + return s_textureUnits[textureMap]; + } + + /*! + * \brief Loads the material from file + * \return true if loading is successful + * + * \param filePath Path to the file + * \param params Parameters for the material + */ + inline MaterialRef Material::LoadFromFile(const String& filePath, const MaterialParams& params) + { + return MaterialLoader::LoadFromFile(filePath, params); + } + + /*! + * \brief Loads the material from memory + * \return true if loading is successful + * + * \param data Raw memory + * \param size Size of the memory + * \param params Parameters for the material + */ + inline MaterialRef Material::LoadFromMemory(const void* data, std::size_t size, const MaterialParams& params) + { + return MaterialLoader::LoadFromMemory(data, size, params); + } + + /*! + * \brief Loads the material from stream + * \return true if loading is successful + * + * \param stream Stream to the material + * \param params Parameters for the material + */ + inline MaterialRef Material::LoadFromStream(Stream& stream, const MaterialParams& params) + { + return MaterialLoader::LoadFromStream(stream, params); + } + + inline void Material::InvalidatePipeline() + { + m_pipelineUpdated = false; + } + + inline void Material::UpdatePipeline() const + { + m_pipeline = MaterialPipeline::GetPipeline(m_pipelineInfo); + m_pipelineUpdated = true; + } + + /*! + * \brief Creates a new material from the arguments + * \return A reference to the newly created material + * + * \param args Arguments for the material + */ + template + MaterialRef Material::New(Args&&... args) + { + std::unique_ptr object(new Material(std::forward(args)...)); + object->SetPersistent(false); + + return object.release(); + } +} + +#include diff --git a/include/Nazara/Graphics/MaterialPipeline.hpp b/include/Nazara/Graphics/MaterialPipeline.hpp new file mode 100644 index 000000000..6147e50b9 --- /dev/null +++ b/include/Nazara/Graphics/MaterialPipeline.hpp @@ -0,0 +1,87 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_MATERIALPIPELINE_HPP +#define NAZARA_MATERIALPIPELINE_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + class Shader; + + struct MaterialPipelineInfo : RenderStates + { + bool alphaTest = false; + bool depthSorting = false; + bool hasVertexColor = false; + bool reflectionMapping = false; + bool shadowReceive = true; + Nz::UInt64 textures = 0; + + std::shared_ptr pipelineLayout; + std::shared_ptr settings; + std::shared_ptr shader; + }; + + inline bool operator==(const MaterialPipelineInfo& lhs, const MaterialPipelineInfo& rhs); + inline bool operator!=(const MaterialPipelineInfo& lhs, const MaterialPipelineInfo& rhs); + + + class NAZARA_GRAPHICS_API MaterialPipeline + { + public: + struct Instance; + + MaterialPipeline(const MaterialPipeline&) = delete; + MaterialPipeline(MaterialPipeline&&) = delete; + ~MaterialPipeline() = default; + + inline const Instance& Apply(UInt32 flags = ShaderFlags_None) const; + + MaterialPipeline& operator=(const MaterialPipeline&) = delete; + MaterialPipeline& operator=(MaterialPipeline&&) = delete; + + inline const MaterialPipelineInfo& GetInfo() const; + inline const Instance& GetInstance(UInt32 flags = ShaderFlags_None) const; + + static MaterialPipelineRef GetPipeline(const MaterialPipelineInfo& pipelineInfo); + + struct Instance + { + RenderPipeline renderPipeline; + //Shader::LayoutBindings bindings; + //UberShaderInstance* uberInstance = nullptr; + }; + + private: + inline MaterialPipeline(const MaterialPipelineInfo& pipelineInfo); + + void GenerateRenderPipeline(UInt32 flags) const; + + static bool Initialize(); + template static MaterialPipelineRef New(Args&&... args); + static void Uninitialize(); + + MaterialPipelineInfo m_pipelineInfo; + mutable std::array m_instances; + + using PipelineCache = std::unordered_map; + static PipelineCache s_pipelineCache; + + static MaterialPipelineLibrary::LibraryMap s_library; + }; +} + +#include + +#endif // NAZARA_MATERIALPIPELINE_HPP diff --git a/include/Nazara/Graphics/MaterialPipeline.inl b/include/Nazara/Graphics/MaterialPipeline.inl new file mode 100644 index 000000000..f771f8a52 --- /dev/null +++ b/include/Nazara/Graphics/MaterialPipeline.inl @@ -0,0 +1,138 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include + +namespace Nz +{ + inline MaterialPipeline::MaterialPipeline(const MaterialPipelineInfo& pipelineInfo) : + m_pipelineInfo(pipelineInfo) + { + } + + /*! + * \brief Enable pipeline states for rendering + * + * \param flags Shader flags + */ + inline const MaterialPipeline::Instance& MaterialPipeline::Apply(UInt32 flags) const + { + const Instance& instance = GetInstance(flags); + instance.uberInstance->Activate(); + + Renderer::SetRenderStates(m_pipelineInfo); + + return instance; + } + + /*! + * \brief Retrieve a MaterialPipelineInfo object describing this pipeline + * + * \return Pipeline informations + */ + const MaterialPipelineInfo& MaterialPipeline::GetInfo() const + { + return m_pipelineInfo; + } + + /*! + * \brief Retrieve (and generate if required) a pipeline instance using shader flags without applying it + * + * \param flags Shader flags + * + * \return Pipeline instance + */ + inline const MaterialPipeline::Instance& MaterialPipeline::GetInstance(UInt32 flags) const + { + const Instance& instance = m_instances[flags]; + if (!instance.uberInstance) + GenerateRenderPipeline(flags); + + return instance; + } + + bool operator==(const MaterialPipelineInfo& lhs, const MaterialPipelineInfo& rhs) + { + if (!operator==(static_cast(lhs), static_cast(rhs))) + return false; + + #define NazaraPipelineMember(field) if (lhs.field != rhs.field) return false + #define NazaraPipelineBoolMember NazaraPipelineMember + + NazaraPipelineBoolMember(depthSorting); + NazaraPipelineBoolMember(hasVertexColor); + NazaraPipelineBoolMember(reflectionMapping); + NazaraPipelineBoolMember(shadowReceive); + + NazaraPipelineMember(pipelineLayout); + NazaraPipelineMember(settings); + NazaraPipelineMember(shader); + + #undef NazaraPipelineMember + #undef NazaraPipelineBoolMember + + return true; + } + + bool operator!=(const MaterialPipelineInfo& lhs, const MaterialPipelineInfo& rhs) + { + return !operator==(lhs, rhs); + } + + /*! + * \brief Creates a new MaterialPipeline from the arguments + * \return A reference to the newly created material pipeline + * + * \param args Arguments for the material pipeline + */ + template + MaterialPipelineRef MaterialPipeline::New(Args&&... args) + { + std::unique_ptr object(new MaterialPipeline(std::forward(args)...)); + object->SetPersistent(false); + return object.release(); + } +} + +namespace std +{ + template<> + struct hash + { + size_t operator()(const Nz::MaterialPipelineInfo& pipelineInfo) const + { + hash parentHash; + + std::size_t seed = parentHash(pipelineInfo); + + Nz::UInt16 parameterHash = 0; + Nz::UInt16 parameterIndex = 0; + + #define NazaraPipelineMember(member) Nz::HashCombine(seed, pipelineInfo.member) + #define NazaraPipelineBoolMember(member) parameterHash |= ((pipelineInfo.member) ? 1U : 0U) << (parameterIndex++) + + NazaraPipelineBoolMember(alphaTest); + NazaraPipelineBoolMember(depthSorting); + NazaraPipelineBoolMember(hasVertexColor); + NazaraPipelineBoolMember(reflectionMapping); + NazaraPipelineBoolMember(shadowReceive); + + NazaraPipelineMember(pipelineLayout.get()); //< Hash pointer + NazaraPipelineMember(settings.get()); //< Hash pointer + NazaraPipelineMember(shader.get()); + + #undef NazaraPipelineMember + #undef NazaraPipelineBoolMember + + Nz::HashCombine(seed, parameterHash); + + return seed; + } + }; +} + +#include diff --git a/include/Nazara/Graphics/MaterialSettings.hpp b/include/Nazara/Graphics/MaterialSettings.hpp new file mode 100644 index 000000000..069224bc4 --- /dev/null +++ b/include/Nazara/Graphics/MaterialSettings.hpp @@ -0,0 +1,92 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_MATERIALSETTINGS_HPP +#define NAZARA_MATERIALSETTINGS_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + class MaterialSettings + { + public: + using PredefinedBinding = std::array; + + struct SharedUniformBlock; + struct Texture; + struct UniformBlock; + + inline MaterialSettings(); + inline MaterialSettings(std::vector textures, std::vector uniformBlocks, std::vector sharedUniformBlocks, const PredefinedBinding& predefinedBinding); + MaterialSettings(const MaterialSettings&) = default; + MaterialSettings(MaterialSettings&&) = delete; + ~MaterialSettings() = default; + + inline std::size_t GetPredefinedBindingIndex(PredefinedShaderBinding binding) const; + inline const std::shared_ptr& GetRenderPipelineLayout() const; + inline const std::vector& GetSharedUniformBlocks() const; + inline std::size_t GetSharedUniformBlockVariableOffset(std::size_t uniformBlockIndex, const std::string_view& name) const; + inline std::size_t GetSharedUniformBlockIndex(const std::string_view& name) const; + inline const std::vector& GetTextures() const; + inline std::size_t GetTextureIndex(const std::string_view& name) const; + inline const std::vector& GetUniformBlocks() const; + inline std::size_t GetUniformBlockIndex(const std::string_view& name) const; + inline std::size_t GetUniformBlockVariableOffset(std::size_t uniformBlockIndex, const std::string_view& name) const; + + MaterialSettings& operator=(const MaterialSettings&) = delete; + MaterialSettings& operator=(MaterialSettings&&) = delete; + + static constexpr std::size_t InvalidIndex = std::numeric_limits::max(); + + struct UniformVariable + { + std::string name; + std::size_t offset; + }; + + struct SharedUniformBlock + { + std::string name; + std::string bindingPoint; + std::vector uniforms; + }; + + struct Texture + { + std::string bindingPoint; + std::string name; + ImageType type; + }; + + struct UniformBlock + { + std::size_t blockSize; + std::string name; + std::string bindingPoint; + std::vector uniforms; + std::vector defaultValues; + }; + + private: + std::shared_ptr m_pipelineLayout; + std::vector m_sharedUniformBlocks; + std::vector m_textures; + std::vector m_uniformBlocks; + PredefinedBinding m_predefinedBinding; + }; +} + +#include + +#endif // NAZARA_MATERIALPIPELINESETTINGS_HPP diff --git a/include/Nazara/Graphics/MaterialSettings.inl b/include/Nazara/Graphics/MaterialSettings.inl new file mode 100644 index 000000000..ca410d0fc --- /dev/null +++ b/include/Nazara/Graphics/MaterialSettings.inl @@ -0,0 +1,147 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include + +namespace Nz +{ + inline MaterialSettings::MaterialSettings() : + MaterialSettings({}, {}, {}, { InvalidIndex }) + { + } + + inline MaterialSettings::MaterialSettings(std::vector textures, std::vector uniformBlocks, std::vector sharedUniformBlocks, const PredefinedBinding& predefinedBindings) : + m_sharedUniformBlocks(std::move(sharedUniformBlocks)), + m_textures(std::move(textures)), + m_uniformBlocks(std::move(uniformBlocks)), + m_predefinedBinding(predefinedBindings) + { + RenderPipelineLayoutInfo info; + + unsigned int bindingIndex = 0; + + for (const Texture& textureInfo : m_textures) + { + info.bindings.push_back({ + textureInfo.bindingPoint, + ShaderBindingType::Texture, + ShaderStageType_All, + bindingIndex++ + }); + } + + for (const UniformBlock& ubo : m_uniformBlocks) + { + info.bindings.push_back({ + ubo.bindingPoint, + ShaderBindingType::UniformBuffer, + ShaderStageType_All, + bindingIndex++ + }); + } + + for (const SharedUniformBlock& ubo : m_sharedUniformBlocks) + { + info.bindings.push_back({ + ubo.bindingPoint, + ShaderBindingType::UniformBuffer, + ShaderStageType_All, + bindingIndex++ + }); + } + + m_pipelineLayout = Graphics::Instance()->GetRenderDevice().InstantiateRenderPipelineLayout(std::move(info)); + } + + inline std::size_t MaterialSettings::GetPredefinedBindingIndex(PredefinedShaderBinding binding) const + { + return m_predefinedBinding[static_cast(binding)]; + } + + inline const std::shared_ptr& MaterialSettings::GetRenderPipelineLayout() const + { + return m_pipelineLayout; + } + + inline auto MaterialSettings::GetSharedUniformBlocks() const -> const std::vector& + { + return m_sharedUniformBlocks; + } + + inline std::size_t MaterialSettings::GetSharedUniformBlockIndex(const std::string_view& name) const + { + for (std::size_t i = 0; i < m_sharedUniformBlocks.size(); ++i) + { + if (m_sharedUniformBlocks[i].name == name) + return i; + } + + return InvalidIndex; + } + + inline auto MaterialSettings::GetTextures() const -> const std::vector& + { + return m_textures; + } + + inline std::size_t MaterialSettings::GetSharedUniformBlockVariableOffset(std::size_t uniformBlockIndex, const std::string_view& name) const + { + assert(uniformBlockIndex < m_sharedUniformBlocks.size()); + + const std::vector& variables = m_sharedUniformBlocks[uniformBlockIndex].uniforms; + for (std::size_t i = 0; i < variables.size(); ++i) + { + if (variables[i].name == name) + return i; + } + + return InvalidIndex; + } + + inline std::size_t MaterialSettings::GetTextureIndex(const std::string_view& name) const + { + for (std::size_t i = 0; i < m_textures.size(); ++i) + { + if (m_textures[i].name == name) + return i; + } + + return InvalidIndex; + } + + inline auto MaterialSettings::GetUniformBlocks() const -> const std::vector& + { + return m_uniformBlocks; + } + + inline std::size_t MaterialSettings::GetUniformBlockIndex(const std::string_view& name) const + { + for (std::size_t i = 0; i < m_uniformBlocks.size(); ++i) + { + if (m_uniformBlocks[i].name == name) + return i; + } + + return InvalidIndex; + } + + inline std::size_t MaterialSettings::GetUniformBlockVariableOffset(std::size_t uniformBlockIndex, const std::string_view& name) const + { + assert(uniformBlockIndex < m_uniformBlocks.size()); + + const std::vector& variables = m_uniformBlocks[uniformBlockIndex].uniforms; + for (std::size_t i = 0; i < variables.size(); ++i) + { + if (variables[i].name == name) + return i; + } + + return InvalidIndex; + } +} + +#include diff --git a/include/Nazara/Graphics/PhongLightingMaterial.hpp b/include/Nazara/Graphics/PhongLightingMaterial.hpp new file mode 100644 index 000000000..277cdc873 --- /dev/null +++ b/include/Nazara/Graphics/PhongLightingMaterial.hpp @@ -0,0 +1,110 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_PHONG_LIGHTING_MATERIAL_HPP +#define NAZARA_PHONG_LIGHTING_MATERIAL_HPP + +#include +#include + +namespace Nz +{ + class NAZARA_GRAPHICS_API PhongLightingMaterial + { + friend class MaterialPipeline; + + public: + PhongLightingMaterial(Material* material); + + inline const TextureRef& GetAlphaMap() const; + float GetAlphaThreshold() const; + Color GetAmbientColor() const; + Color GetDiffuseColor() const; + inline const TextureRef& GetDiffuseMap() const; + inline TextureSampler& GetDiffuseSampler(); + inline const TextureSampler& GetDiffuseSampler() const; + inline const TextureRef& GetEmissiveMap() const; + inline const TextureRef& GetHeightMap() const; + inline const TextureRef& GetNormalMap() const; + float GetShininess() const; + Color GetSpecularColor() const; + inline const TextureRef& GetSpecularMap() const; + inline TextureSampler& GetSpecularSampler(); + inline const TextureSampler& GetSpecularSampler() const; + + inline bool HasAlphaMap() const; + inline bool HasAlphaThreshold() const; + inline bool HasAmbientColor() const; + inline bool HasDiffuseColor() const; + inline bool HasDiffuseMap() const; + inline bool HasEmissiveMap() const; + inline bool HasHeightMap() const; + inline bool HasNormalMap() const; + inline bool HasShininess() const; + inline bool HasSpecularColor() const; + inline bool HasSpecularMap() const; + + inline bool SetAlphaMap(const String& textureName); + inline void SetAlphaMap(TextureRef alphaMap); + void SetAlphaThreshold(float alphaThreshold); + void SetAmbientColor(const Color& ambient); + void SetDiffuseColor(const Color& diffuse); + inline bool SetDiffuseMap(const String& textureName); + inline void SetDiffuseMap(TextureRef diffuseMap); + inline void SetDiffuseSampler(const TextureSampler& sampler); + inline bool SetEmissiveMap(const String& textureName); + inline void SetEmissiveMap(TextureRef textureName); + inline bool SetHeightMap(const String& textureName); + inline void SetHeightMap(TextureRef textureName); + inline bool SetNormalMap(const String& textureName); + inline void SetNormalMap(TextureRef textureName); + void SetShininess(float shininess); + void SetSpecularColor(const Color& specular); + inline bool SetSpecularMap(const String& textureName); + inline void SetSpecularMap(TextureRef specularMap); + inline void SetSpecularSampler(const TextureSampler& sampler); + + static const std::shared_ptr& GetSettings(); + + private: + struct PhongUniformOffsets + { + std::size_t alphaThreshold; + std::size_t shininess; + std::size_t ambientColor; + std::size_t diffuseColor; + std::size_t specularColor; + }; + + struct TextureIndexes + { + std::size_t alpha; + std::size_t diffuse; + std::size_t emissive; + std::size_t height; + std::size_t normal; + std::size_t specular; + }; + + static bool Initialize(); + static void Uninitialize(); + + MaterialRef m_material; + std::size_t m_phongUniformIndex; + TextureIndexes m_textureIndexes; + PhongUniformOffsets m_phongUniformOffsets; + + static std::shared_ptr s_materialSettings; + static std::size_t s_phongUniformBlockIndex; + static RenderPipelineLayoutRef s_renderPipelineLayout; + static TextureIndexes s_textureIndexes; + static PhongUniformOffsets s_phongUniformOffsets; + }; +} + +#include + +#endif // NAZARA_PHONG_LIGHTING_MATERIAL_HPP diff --git a/include/Nazara/Graphics/PhongLightingMaterial.inl b/include/Nazara/Graphics/PhongLightingMaterial.inl new file mode 100644 index 000000000..1fc14ed20 --- /dev/null +++ b/include/Nazara/Graphics/PhongLightingMaterial.inl @@ -0,0 +1,156 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include + +namespace Nz +{ + inline const TextureRef& PhongLightingMaterial::GetAlphaMap() const + { + NazaraAssert(HasAlphaMap(), "Material has no alpha map slot"); + return m_material->GetTexture(m_textureIndexes.alpha); + } + + inline const TextureRef& PhongLightingMaterial::GetDiffuseMap() const + { + NazaraAssert(HasDiffuseMap(), "Material has no alpha map slot"); + return m_material->GetTexture(m_textureIndexes.diffuse); + } + + inline const TextureRef& PhongLightingMaterial::GetEmissiveMap() const + { + NazaraAssert(HasEmissiveMap(), "Material has no alpha map slot"); + return m_material->GetTexture(m_textureIndexes.emissive); + } + + inline const TextureRef& PhongLightingMaterial::GetHeightMap() const + { + NazaraAssert(HasHeightMap(), "Material has no alpha map slot"); + return m_material->GetTexture(m_textureIndexes.height); + } + + inline const TextureRef& PhongLightingMaterial::GetNormalMap() const + { + NazaraAssert(HasNormalMap(), "Material has no alpha map slot"); + return m_material->GetTexture(m_textureIndexes.normal); + } + + inline const TextureRef& PhongLightingMaterial::GetSpecularMap() const + { + NazaraAssert(HasSpecularMap(), "Material has no alpha map slot"); + return m_material->GetTexture(m_textureIndexes.specular); + } + + inline bool PhongLightingMaterial::HasAlphaMap() const + { + return m_textureIndexes.alpha != MaterialSettings::InvalidIndex; + } + + inline bool PhongLightingMaterial::HasAlphaThreshold() const + { + return m_phongUniformOffsets.alphaThreshold != MaterialSettings::InvalidIndex; + } + + inline bool PhongLightingMaterial::HasAmbientColor() const + { + return m_phongUniformOffsets.ambientColor != MaterialSettings::InvalidIndex; + } + + inline bool PhongLightingMaterial::HasDiffuseColor() const + { + return m_phongUniformOffsets.diffuseColor != MaterialSettings::InvalidIndex; + } + + inline bool PhongLightingMaterial::HasDiffuseMap() const + { + return m_textureIndexes.diffuse != MaterialSettings::InvalidIndex; + } + + inline bool PhongLightingMaterial::HasEmissiveMap() const + { + return m_textureIndexes.emissive != MaterialSettings::InvalidIndex; + } + + inline bool PhongLightingMaterial::HasHeightMap() const + { + return m_textureIndexes.height != MaterialSettings::InvalidIndex; + } + + inline bool PhongLightingMaterial::HasNormalMap() const + { + return m_textureIndexes.normal != MaterialSettings::InvalidIndex; + } + + inline bool PhongLightingMaterial::HasShininess() const + { + return m_phongUniformOffsets.shininess != MaterialSettings::InvalidIndex; + } + + inline bool PhongLightingMaterial::HasSpecularColor() const + { + return m_phongUniformOffsets.specularColor != MaterialSettings::InvalidIndex; + } + + inline bool PhongLightingMaterial::HasSpecularMap() const + { + return m_textureIndexes.specular != MaterialSettings::InvalidIndex; + } + + inline void PhongLightingMaterial::SetAlphaMap(TextureRef alphaMap) + { + NazaraAssert(HasAlphaMap(), "Material has no alpha map slot"); + m_material->SetTexture(m_textureIndexes.alpha, std::move(alphaMap)); + } + + inline bool PhongLightingMaterial::SetDiffuseMap(const String& textureName) + { + TextureRef texture = TextureLibrary::Query(textureName); + if (!texture) + { + texture = TextureManager::Get(textureName); + if (!texture) + { + NazaraError("Failed to get diffuse map \"" + textureName + "\""); + return false; + } + } + + SetDiffuseMap(std::move(texture)); + return true; + } + + inline void PhongLightingMaterial::SetDiffuseMap(TextureRef diffuseMap) + { + NazaraAssert(HasDiffuseMap(), "Material has no diffuse map slot"); + m_material->SetTexture(m_textureIndexes.diffuse, std::move(diffuseMap)); + } + + inline bool PhongLightingMaterial::SetNormalMap(const String& textureName) + { + TextureRef texture = TextureLibrary::Query(textureName); + if (!texture) + { + texture = TextureManager::Get(textureName); + if (!texture) + { + NazaraError("Failed to get normal map \"" + textureName + "\""); + return false; + } + } + + SetNormalMap(std::move(texture)); + return true; + } + + inline void PhongLightingMaterial::SetNormalMap(TextureRef normalMap) + { + NazaraAssert(HasNormalMap(), "Material has no normal map slot"); + m_material->SetTexture(m_textureIndexes.normal, std::move(normalMap)); + } +} + +#include diff --git a/include/Nazara/Graphics/PredefinedShaderStructs.hpp b/include/Nazara/Graphics/PredefinedShaderStructs.hpp new file mode 100644 index 000000000..d196b5e0a --- /dev/null +++ b/include/Nazara/Graphics/PredefinedShaderStructs.hpp @@ -0,0 +1,68 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_PREDEFINEDSHADERSTRUCTS_HPP +#define NAZARA_PREDEFINEDSHADERSTRUCTS_HPP + +#include +#include +#include + +namespace Nz +{ + struct NAZARA_GRAPHICS_API PredefinedLightData + { + struct InnerStruct + { + std::size_t type; + std::size_t color; + std::size_t factor; + std::size_t parameter1; + std::size_t parameter2; + std::size_t parameter3; + std::size_t shadowMappingFlag; + std::size_t totalSize; + }; + + InnerStruct innerOffsets; + std::array lightArray; + std::size_t lightArraySize; + + static PredefinedLightData GetOffset(); + static MaterialSettings::SharedUniformBlock GetUniformBlock(); + }; + + struct NAZARA_GRAPHICS_API PredefinedInstanceData + { + std::size_t invWorldMatrixOffset; + std::size_t totalSize; + std::size_t worldMatrixOffset; + + static PredefinedInstanceData GetOffset(); + static MaterialSettings::SharedUniformBlock GetUniformBlock(); + }; + + struct NAZARA_GRAPHICS_API PredefinedViewerData + { + std::size_t eyePositionOffset; + std::size_t invProjMatrixOffset; + std::size_t invTargetSizeOffset; + std::size_t invViewMatrixOffset; + std::size_t invViewProjMatrixOffset; + std::size_t projMatrixOffset; + std::size_t targetSizeOffset; + std::size_t totalSize; + std::size_t viewMatrixOffset; + std::size_t viewProjMatrixOffset; + + static PredefinedViewerData GetOffset(); + static MaterialSettings::SharedUniformBlock GetUniformBlock(); + }; +} + +#include + +#endif // NAZARA_PREDEFINEDSHADERSTRUCTS_HPP diff --git a/include/Nazara/Graphics/PredefinedShaderStructs.inl b/include/Nazara/Graphics/PredefinedShaderStructs.inl new file mode 100644 index 000000000..e3daa8694 --- /dev/null +++ b/include/Nazara/Graphics/PredefinedShaderStructs.inl @@ -0,0 +1,9 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include + +namespace Nz +{ +} diff --git a/include/Nazara/Graphics/RenderQueue.hpp b/include/Nazara/Graphics/RenderQueue.hpp new file mode 100644 index 000000000..0d1f1fb81 --- /dev/null +++ b/include/Nazara/Graphics/RenderQueue.hpp @@ -0,0 +1,101 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_RENDERQUEUE_HPP +#define NAZARA_RENDERQUEUE_HPP + +#include +#include +#include + +namespace Nz +{ + class RenderQueueInternal + { + public: + using Index = Nz::UInt64; + + RenderQueueInternal() = default; + RenderQueueInternal(const RenderQueueInternal&) = default; + RenderQueueInternal(RenderQueueInternal&&) = default; + ~RenderQueueInternal() = default; + + RenderQueueInternal& operator=(const RenderQueueInternal&) = default; + RenderQueueInternal& operator=(RenderQueueInternal&&) = default; + + protected: + using RenderDataPair = std::pair; + + void Sort(); + + std::vector m_orderedRenderQueue; + }; + + template + class RenderQueue : public RenderQueueInternal + { + public: + class const_iterator; + friend const_iterator; + using size_type = std::size_t; + + RenderQueue() = default; + RenderQueue(const RenderQueue&) = default; + RenderQueue(RenderQueue&&) noexcept = default; + ~RenderQueue() = default; + + void Clear(); + + void Insert(RenderData&& data); + + template void Sort(IndexFunc&& func); + + // STL API + inline const_iterator begin() const; + inline bool empty() const; + inline const_iterator end() const; + inline size_type size() const; + + RenderQueue& operator=(const RenderQueue&) = default; + RenderQueue& operator=(RenderQueue&&) noexcept = default; + + private: + const RenderData& GetData(std::size_t i) const; + + std::vector m_data; + }; + + template + class RenderQueue::const_iterator : public std::iterator + { + friend RenderQueue; + + public: + const_iterator(const const_iterator& it); + + const RenderData& operator*() const; + + const_iterator& operator=(const const_iterator& it); + const_iterator& operator++(); + const_iterator operator++(int); + + bool operator==(const const_iterator& rhs) const; + bool operator!=(const const_iterator& rhs) const; + + void swap(const_iterator& rhs); + + private: + const_iterator(const RenderQueue* queue, std::size_t nextId); + + std::size_t m_nextDataId; + const RenderQueue* m_queue; + }; + +} + +#include + +#endif // NAZARA_RENDERQUEUE_HPP diff --git a/include/Nazara/Graphics/RenderQueue.inl b/include/Nazara/Graphics/RenderQueue.inl new file mode 100644 index 000000000..47ec03c98 --- /dev/null +++ b/include/Nazara/Graphics/RenderQueue.inl @@ -0,0 +1,136 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + template + void RenderQueue::Clear() + { + m_orderedRenderQueue.clear(); + m_data.clear(); + } + + template + void RenderQueue::Insert(RenderData&& data) + { + m_data.emplace_back(std::move(data)); + } + + template + template + void RenderQueue::Sort(IndexFunc&& func) + { + m_orderedRenderQueue.clear(); + m_orderedRenderQueue.reserve(m_data.size()); + + std::size_t dataIndex = 0; + for (const RenderData& renderData : m_data) + m_orderedRenderQueue.emplace_back(func(renderData), dataIndex++); + + RenderQueueInternal::Sort(); + } + + template + typename RenderQueue::const_iterator RenderQueue::begin() const + { + return const_iterator(this, 0); + } + + template + bool RenderQueue::empty() const + { + return m_orderedRenderQueue.empty(); + } + + template + typename RenderQueue::const_iterator RenderQueue::end() const + { + return const_iterator(this, m_orderedRenderQueue.size()); + } + + template + typename RenderQueue::size_type RenderQueue::size() const + { + return m_orderedRenderQueue.size(); + } + + template + const RenderData& RenderQueue::GetData(std::size_t i) const + { + NazaraAssert(i < m_orderedRenderQueue.size(), "Cannot dereference post-end iterator"); + + return m_data[m_orderedRenderQueue[i].second]; + } + + + template + RenderQueue::const_iterator::const_iterator(const RenderQueue* queue, std::size_t nextId) : + m_nextDataId(nextId), + m_queue(queue) + { + } + + template + RenderQueue::const_iterator::const_iterator(const const_iterator& it) : + m_nextDataId(it.m_nextDataId), + m_queue(it.m_queue) + { + } + + template + const RenderData& RenderQueue::const_iterator::operator*() const + { + return m_queue->GetData(m_nextDataId); + } + + template + typename RenderQueue::const_iterator& RenderQueue::const_iterator::operator=(const const_iterator& it) + { + m_nextDataId = it.m_nextDataId; + m_queue = it.m_queue; + + return *this; + } + + template + typename RenderQueue::const_iterator& RenderQueue::const_iterator::operator++() + { + ++m_nextDataId; + + return *this; + } + + template + typename RenderQueue::const_iterator RenderQueue::const_iterator::operator++(int) + { + return iterator(m_queue, m_nextDataId++); + } + + template + bool RenderQueue::const_iterator::operator==(const typename RenderQueue::const_iterator& rhs) const + { + NazaraAssert(m_queue == rhs.m_queue, "Cannot compare iterator coming from different queues"); + + return m_nextDataId == rhs.m_nextDataId; + } + + template + bool RenderQueue::const_iterator::operator!=(const typename RenderQueue::const_iterator& rhs) const + { + return !operator==(rhs); + } + + template + void RenderQueue::const_iterator::swap(typename RenderQueue::const_iterator& rhs) + { + NazaraAssert(m_queue == rhs.m_queue, "Cannot swap iterator coming from different queues"); + + using std::swap; + + swap(m_nextDataId, rhs.m_nextDataId); + } +} diff --git a/include/Nazara/Renderer/RenderPipeline.hpp b/include/Nazara/Renderer/RenderPipeline.hpp index 6e938eba7..82f08e7c4 100644 --- a/include/Nazara/Renderer/RenderPipeline.hpp +++ b/include/Nazara/Renderer/RenderPipeline.hpp @@ -10,7 +10,6 @@ #include #include #include -//#include namespace Nz { diff --git a/src/Nazara/Graphics/BasicMaterial.cpp b/src/Nazara/Graphics/BasicMaterial.cpp new file mode 100644 index 000000000..6843562b5 --- /dev/null +++ b/src/Nazara/Graphics/BasicMaterial.cpp @@ -0,0 +1,203 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + namespace + { + constexpr std::size_t AlphaMapBinding = 0; + constexpr std::size_t DiffuseMapBinding = 1; + constexpr std::size_t TextureOverlayBinding = 2; + } + + BasicMaterial::BasicMaterial(Material* material) : + m_material(material) + { + NazaraAssert(material, "Invalid material"); + + // Most common case: don't fetch texture indexes as a little optimization + const std::shared_ptr& materialSettings = material->GetSettings(); + if (materialSettings == s_materialSettings) + { + m_textureIndexes = s_textureIndexes; + m_uniformBlockIndex = s_uniformBlockIndex; + m_uniformOffsets = s_uniformOffsets; + } + else + { + m_textureIndexes.alpha = materialSettings->GetTextureIndex("Alpha"); + m_textureIndexes.diffuse = materialSettings->GetTextureIndex("Diffuse"); + + m_uniformBlockIndex = materialSettings->GetUniformBlockIndex("BasicSettings"); + + m_uniformOffsets.alphaThreshold = materialSettings->GetUniformBlockVariableOffset(m_uniformBlockIndex, "AlphaThreshold"); + m_uniformOffsets.diffuseColor = materialSettings->GetUniformBlockVariableOffset(m_uniformBlockIndex, "DiffuseColor"); + } + } + + float BasicMaterial::GetAlphaThreshold() const + { + NazaraAssert(HasAlphaThreshold(), "Material has no alpha threshold uniform"); + + BufferMapper mapper(m_material->GetUniformBuffer(m_uniformBlockIndex), BufferAccess_ReadOnly); + return *AccessByOffset(mapper.GetPointer(), m_uniformOffsets.alphaThreshold); + } + + Color BasicMaterial::GetDiffuseColor() const + { + NazaraAssert(HasDiffuseColor(), "Material has no diffuse color uniform"); + + BufferMapper mapper(m_material->GetUniformBuffer(m_uniformBlockIndex), BufferAccess_ReadOnly); + + const float* colorPtr = AccessByOffset(mapper.GetPointer(), m_uniformOffsets.diffuseColor); + return Color(colorPtr[0] * 255, colorPtr[1] * 255, colorPtr[2] * 255, colorPtr[3] * 255); //< TODO: Make color able to use float + } + + void BasicMaterial::SetAlphaThreshold(float alphaThreshold) + { + NazaraAssert(HasAlphaThreshold(), "Material has no alpha threshold uniform"); + + BufferMapper mapper(m_material->GetUniformBuffer(m_uniformBlockIndex), BufferAccess_WriteOnly); + *AccessByOffset(mapper.GetPointer(), m_uniformOffsets.alphaThreshold) = alphaThreshold; + } + + void BasicMaterial::SetDiffuseColor(const Color& diffuse) + { + NazaraAssert(HasDiffuseColor(), "Material has no diffuse color uniform"); + + BufferMapper mapper(m_material->GetUniformBuffer(m_uniformBlockIndex), BufferAccess_WriteOnly); + float* colorPtr = AccessByOffset(mapper.GetPointer(), m_uniformOffsets.diffuseColor); + colorPtr[0] = diffuse.r / 255.f; + colorPtr[1] = diffuse.g / 255.f; + colorPtr[2] = diffuse.b / 255.f; + colorPtr[3] = diffuse.a / 255.f; + } + + const std::shared_ptr& BasicMaterial::GetSettings() + { + return s_materialSettings; + } + + bool BasicMaterial::Initialize() + { + RenderPipelineLayoutInfo info; + info.bindings.assign({ + { + "MaterialAlphaMap", + ShaderBindingType_Texture, + ShaderStageType_Fragment, + AlphaMapBinding + }, + { + "MaterialDiffuseMap", + ShaderBindingType_Texture, + ShaderStageType_Fragment, + DiffuseMapBinding + }, + { + "TextureOverlay", + ShaderBindingType_Texture, + ShaderStageType_Fragment, + TextureOverlayBinding + } + }); + + s_renderPipelineLayout = RenderPipelineLayout::New(); + s_renderPipelineLayout->Create(info); + + FieldOffsets fieldOffsets(StructLayout_Std140); + + s_uniformOffsets.diffuseColor = fieldOffsets.AddField(StructFieldType_Float4); + s_uniformOffsets.alphaThreshold = fieldOffsets.AddField(StructFieldType_Float1); + + MaterialSettings::PredefinedBinding predefinedBinding; + predefinedBinding.fill(MaterialSettings::InvalidIndex); + + std::vector variables; + variables.assign({ + { + "AlphaThreshold", + s_uniformOffsets.alphaThreshold + }, + { + "DiffuseColor", + s_uniformOffsets.diffuseColor + } + }); + + static_assert(sizeof(Vector4f) == 4 * sizeof(float), "Vector4f is expected to be exactly 4 floats wide"); + + std::vector defaultValues(fieldOffsets.GetSize()); + *AccessByOffset(defaultValues.data(), s_uniformOffsets.diffuseColor) = Vector4f(1.f, 1.f, 1.f, 1.f); + *AccessByOffset(defaultValues.data(), s_uniformOffsets.alphaThreshold) = 0.2f; + + std::vector uniformBlocks; + s_uniformBlockIndex = uniformBlocks.size(); + uniformBlocks.assign({ + { + "BasicSettings", + fieldOffsets.GetSize(), + "MaterialBasicSettings", + std::move(variables), + std::move(defaultValues) + } + }); + + std::vector sharedUniformBlock; + + predefinedBinding[PredefinedShaderBinding_UboInstanceData] = sharedUniformBlock.size(); + sharedUniformBlock.push_back(PredefinedInstanceData::GetUniformBlock()); + predefinedBinding[PredefinedShaderBinding_UboViewerData] = sharedUniformBlock.size(); + sharedUniformBlock.push_back(PredefinedViewerData::GetUniformBlock()); + + std::vector textures; + s_textureIndexes.alpha = textures.size(); + textures.push_back({ + "Alpha", + ImageType_2D, + "MaterialAlphaMap" + }); + + s_textureIndexes.diffuse = textures.size(); + textures.push_back({ + "Diffuse", + ImageType_2D, + "MaterialDiffuseMap" + }); + + predefinedBinding[PredefinedShaderBinding_TexOverlay] = textures.size(); + textures.push_back({ + "Overlay", + ImageType_2D, + "TextureOverlay" + }); + + s_materialSettings = std::make_shared(std::move(textures), std::move(uniformBlocks), std::move(sharedUniformBlock), predefinedBinding); + + return true; + } + + void BasicMaterial::Uninitialize() + { + s_renderPipelineLayout.Reset(); + s_materialSettings.reset(); + } + + std::shared_ptr BasicMaterial::s_materialSettings; + std::size_t BasicMaterial::s_uniformBlockIndex; + RenderPipelineLayoutRef BasicMaterial::s_renderPipelineLayout; + BasicMaterial::TextureIndexes BasicMaterial::s_textureIndexes; + BasicMaterial::UniformOffsets BasicMaterial::s_uniformOffsets; +} diff --git a/src/Nazara/Graphics/BasicRenderQueue.cpp b/src/Nazara/Graphics/BasicRenderQueue.cpp new file mode 100644 index 000000000..88ce8ddbd --- /dev/null +++ b/src/Nazara/Graphics/BasicRenderQueue.cpp @@ -0,0 +1,956 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include + +///TODO: Replace sinus/cosinus by a lookup table (which will lead to a speed up about 10x) + +namespace Nz +{ + /*! + * \ingroup graphics + * \class Nz::BasicRenderQueue + * \brief Graphics class that represents a simple rendering queue + */ + + /*! + * \brief Adds multiple billboards to the queue + * + * \param renderOrder Order of rendering + * \param material Material of the billboards + * \param count Number of billboards + * \param positionPtr Position of the billboards + * \param sizePtr Sizes of the billboards + * \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used + * \param colorPtr Color of the billboards if null, Color::White is used + * + * \remark Produces a NazaraAssert if material is invalid + */ + + void BasicRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr positionPtr, SparsePtr sizePtr, SparsePtr sinCosPtr, SparsePtr colorPtr) + { + NazaraAssert(material, "Invalid material"); + + RegisterLayer(renderOrder); + + Vector2f defaultSinCos(0.f, 1.f); // sin(0) = 0, cos(0) = 1 + + if (!sinCosPtr) + sinCosPtr.Reset(&defaultSinCos, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile + + if (!colorPtr) + colorPtr.Reset(&Color::White, 0); // Same + + if (material->IsDepthSortingEnabled()) + { + for (std::size_t i = 0; i < billboardCount; ++i) + { + depthSortedBillboards.Insert({ + renderOrder, + material, + scissorRect, + { + *colorPtr++, + *positionPtr++, + *sizePtr++, + *sinCosPtr++ + } + }); + } + } + else + { + std::size_t billboardIndex = m_billboards.size(); + m_billboards.resize(billboardIndex + billboardCount); + BillboardData* data = &m_billboards[billboardIndex]; + + for (std::size_t i = 0; i < billboardCount; ++i) + { + data->center = *positionPtr++; + data->color = *colorPtr++; + data->sinCos = *sinCosPtr++; + data->size = *sizePtr++; + data++; + } + + billboards.Insert({ + renderOrder, + material, + scissorRect, + billboardCount, + billboardIndex + }); + } + } + + /*! + * \brief Adds multiple billboards to the queue + * + * \param renderOrder Order of rendering + * \param material Material of the billboards + * \param count Number of billboards + * \param positionPtr Position of the billboards + * \param sizePtr Sizes of the billboards + * \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used + * \param alphaPtr Alpha parameters of the billboards if null, 1.f is used + * + * \remark Produces a NazaraAssert if material is invalid + */ + + void BasicRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr positionPtr, SparsePtr sizePtr, SparsePtr sinCosPtr, SparsePtr alphaPtr) + { + NazaraAssert(material, "Invalid material"); + + RegisterLayer(renderOrder); + + Vector2f defaultSinCos(0.f, 1.f); // sin(0) = 0, cos(0) = 1 + + if (!sinCosPtr) + sinCosPtr.Reset(&defaultSinCos, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile + + float defaultAlpha = 1.f; + + if (!alphaPtr) + alphaPtr.Reset(&defaultAlpha, 0); // Same + + if (material->IsDepthSortingEnabled()) + { + for (std::size_t i = 0; i < billboardCount; ++i) + { + depthSortedBillboards.Insert({ + renderOrder, + material, + scissorRect, + { + ComputeColor(*alphaPtr++), + *positionPtr++, + *sizePtr++, + *sinCosPtr++ + } + }); + } + } + else + { + std::size_t billboardIndex = m_billboards.size(); + m_billboards.resize(billboardIndex + billboardCount); + BillboardData* data = &m_billboards[billboardIndex]; + + for (std::size_t i = 0; i < billboardCount; ++i) + { + data->center = *positionPtr++; + data->color = ComputeColor(*alphaPtr++); + data->sinCos = *sinCosPtr++; + data->size = *sizePtr++; + data++; + } + + billboards.Insert({ + renderOrder, + material, + scissorRect, + billboardCount, + billboardIndex + }); + } + } + + /*! + * \brief Adds multiple billboards to the queue + * + * \param renderOrder Order of rendering + * \param material Material of the billboards + * \param count Number of billboards + * \param positionPtr Position of the billboards + * \param sizePtr Sizes of the billboards + * \param anglePtr Rotation of the billboards if null, 0.f is used + * \param colorPtr Color of the billboards if null, Color::White is used + * + * \remark Produces a NazaraAssert if material is invalid + */ + + void BasicRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr positionPtr, SparsePtr sizePtr, SparsePtr anglePtr, SparsePtr colorPtr) + { + NazaraAssert(material, "Invalid material"); + + RegisterLayer(renderOrder); + + float defaultRotation = 0.f; + + if (!anglePtr) + anglePtr.Reset(&defaultRotation, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile + + if (!colorPtr) + colorPtr.Reset(&Color::White, 0); // Same + + if (material->IsDepthSortingEnabled()) + { + for (std::size_t i = 0; i < billboardCount; ++i) + { + depthSortedBillboards.Insert({ + renderOrder, + material, + scissorRect, + { + *colorPtr++, + *positionPtr++, + *sizePtr++, + ComputeSinCos(*anglePtr++) + } + }); + } + } + else + { + std::size_t billboardIndex = m_billboards.size(); + m_billboards.resize(billboardIndex + billboardCount); + BillboardData* data = &m_billboards[billboardIndex]; + + for (std::size_t i = 0; i < billboardCount; ++i) + { + data->center = *positionPtr++; + data->color = *colorPtr++; + data->sinCos = ComputeSinCos(*anglePtr++); + data->size = *sizePtr++; + data++; + } + + billboards.Insert({ + renderOrder, + material, + scissorRect, + billboardCount, + billboardIndex + }); + } + } + + /*! + * \brief Adds multiple billboards to the queue + * + * \param renderOrder Order of rendering + * \param material Material of the billboards + * \param count Number of billboards + * \param positionPtr Position of the billboards + * \param sizePtr Sizes of the billboards + * \param anglePtr Rotation of the billboards if null, 0.f is used + * \param alphaPtr Alpha parameters of the billboards if null, 1.f is used + * + * \remark Produces a NazaraAssert if material is invalid + */ + + void BasicRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr positionPtr, SparsePtr sizePtr, SparsePtr anglePtr, SparsePtr alphaPtr) + { + NazaraAssert(material, "Invalid material"); + + RegisterLayer(renderOrder); + + float defaultRotation = 0.f; + + if (!anglePtr) + anglePtr.Reset(&defaultRotation, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile + + float defaultAlpha = 1.f; + + if (!alphaPtr) + alphaPtr.Reset(&defaultAlpha, 0); // Same + + if (material->IsDepthSortingEnabled()) + { + for (std::size_t i = 0; i < billboardCount; ++i) + { + depthSortedBillboards.Insert({ + renderOrder, + material, + scissorRect, + { + ComputeColor(*alphaPtr++), + *positionPtr++, + *sizePtr++, + ComputeSinCos(*anglePtr++) + } + }); + } + } + else + { + std::size_t billboardIndex = m_billboards.size(); + m_billboards.resize(billboardIndex + billboardCount); + BillboardData* data = &m_billboards[billboardIndex]; + + for (std::size_t i = 0; i < billboardCount; ++i) + { + data->center = *positionPtr++; + data->color = ComputeColor(*alphaPtr++); + data->sinCos = ComputeSinCos(*anglePtr++); + data->size = *sizePtr++; + data++; + } + + billboards.Insert({ + renderOrder, + material, + scissorRect, + billboardCount, + billboardIndex + }); + } + } + + /*! + * \brief Adds multiple billboards to the queue + * + * \param renderOrder Order of rendering + * \param material Material of the billboards + * \param count Number of billboards + * \param positionPtr Position of the billboards + * \param sizePtr Size of the billboards + * \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used + * \param colorPtr Color of the billboards if null, Color::White is used + * + * \remark Produces a NazaraAssert if material is invalid + */ + + void BasicRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr positionPtr, SparsePtr sizePtr, SparsePtr sinCosPtr, SparsePtr colorPtr) + { + NazaraAssert(material, "Invalid material"); + + RegisterLayer(renderOrder); + + Vector2f defaultSinCos(0.f, 1.f); // sin(0) = 0, cos(0) = 1 + + if (!sinCosPtr) + sinCosPtr.Reset(&defaultSinCos, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile + + if (!colorPtr) + colorPtr.Reset(&Color::White, 0); // Same + + if (material->IsDepthSortingEnabled()) + { + for (std::size_t i = 0; i < billboardCount; ++i) + { + depthSortedBillboards.Insert({ + renderOrder, + material, + scissorRect, + { + *colorPtr++, + *positionPtr++, + ComputeSize(*sizePtr++), + *sinCosPtr++ + } + }); + } + } + else + { + std::size_t billboardIndex = m_billboards.size(); + m_billboards.resize(billboardIndex + billboardCount); + BillboardData* data = &m_billboards[billboardIndex]; + + for (std::size_t i = 0; i < billboardCount; ++i) + { + data->center = *positionPtr++; + data->color = *colorPtr++; + data->sinCos = *sinCosPtr++; + data->size = ComputeSize(*sizePtr++); + data++; + } + + billboards.Insert({ + renderOrder, + material, + scissorRect, + billboardCount, + billboardIndex + }); + } + } + + /*! + * \brief Adds multiple billboards to the queue + * + * \param renderOrder Order of rendering + * \param material Material of the billboards + * \param count Number of billboards + * \param positionPtr Position of the billboards + * \param sizePtr Size of the billboards + * \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used + * \param alphaPtr Alpha parameters of the billboards if null, 1.f is used + * + * \remark Produces a NazaraAssert if material is invalid + */ + + void BasicRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr positionPtr, SparsePtr sizePtr, SparsePtr sinCosPtr, SparsePtr alphaPtr) + { + NazaraAssert(material, "Invalid material"); + + RegisterLayer(renderOrder); + + Vector2f defaultSinCos(0.f, 1.f); // sin(0) = 0, cos(0) = 1 + + if (!sinCosPtr) + sinCosPtr.Reset(&defaultSinCos, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile + + float defaultAlpha = 1.f; + + if (!alphaPtr) + alphaPtr.Reset(&defaultAlpha, 0); // Same + + if (material->IsDepthSortingEnabled()) + { + for (std::size_t i = 0; i < billboardCount; ++i) + { + depthSortedBillboards.Insert({ + renderOrder, + material, + scissorRect, + { + ComputeColor(*alphaPtr++), + *positionPtr++, + ComputeSize(*sizePtr++), + *sinCosPtr++ + } + }); + } + } + else + { + std::size_t billboardIndex = m_billboards.size(); + m_billboards.resize(billboardIndex + billboardCount); + BillboardData* data = &m_billboards[billboardIndex]; + + for (std::size_t i = 0; i < billboardCount; ++i) + { + data->center = *positionPtr++; + data->color = ComputeColor(*alphaPtr++); + data->sinCos = *sinCosPtr++; + data->size = ComputeSize(*sizePtr++); + data++; + } + + billboards.Insert({ + renderOrder, + material, + scissorRect, + billboardCount, + billboardIndex + }); + } + } + + /*! + * \brief Adds multiple billboards to the queue + * + * \param renderOrder Order of rendering + * \param material Material of the billboards + * \param count Number of billboards + * \param positionPtr Position of the billboards + * \param sizePtr Size of the billboards + * \param anglePtr Rotation of the billboards if null, 0.f is used + * \param colorPtr Color of the billboards if null, Color::White is used + * + * \remark Produces a NazaraAssert if material is invalid + */ + + void BasicRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr positionPtr, SparsePtr sizePtr, SparsePtr anglePtr, SparsePtr colorPtr) + { + NazaraAssert(material, "Invalid material"); + + RegisterLayer(renderOrder); + + float defaultRotation = 0.f; + + if (!anglePtr) + anglePtr.Reset(&defaultRotation, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile + + if (!colorPtr) + colorPtr.Reset(&Color::White, 0); // Same + + if (material->IsDepthSortingEnabled()) + { + for (std::size_t i = 0; i < billboardCount; ++i) + { + depthSortedBillboards.Insert({ + renderOrder, + material, + scissorRect, + { + *colorPtr++, + *positionPtr++, + ComputeSize(*sizePtr++), + ComputeSinCos(*anglePtr++) + } + }); + } + } + else + { + std::size_t billboardIndex = m_billboards.size(); + m_billboards.resize(billboardIndex + billboardCount); + BillboardData* data = &m_billboards[billboardIndex]; + + for (std::size_t i = 0; i < billboardCount; ++i) + { + data->center = *positionPtr++; + data->color = *colorPtr++; + data->sinCos = ComputeSinCos(*anglePtr++); + data->size = ComputeSize(*sizePtr++); + data++; + } + + billboards.Insert({ + renderOrder, + material, + scissorRect, + billboardCount, + billboardIndex + }); + } + } + + /*! + * \brief Adds multiple billboards to the queue + * + * \param renderOrder Order of rendering + * \param material Material of the billboards + * \param count Number of billboards + * \param positionPtr Position of the billboards + * \param sizePtr Size of the billboards + * \param anglePtr Rotation of the billboards if null, 0.f is used + * \param alphaPtr Alpha parameters of the billboards if null, 1.f is used + * + * \remark Produces a NazaraAssert if material is invalid + */ + + void BasicRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr positionPtr, SparsePtr sizePtr, SparsePtr anglePtr, SparsePtr alphaPtr) + { + NazaraAssert(material, "Invalid material"); + + RegisterLayer(renderOrder); + + float defaultRotation = 0.f; + + if (!anglePtr) + anglePtr.Reset(&defaultRotation, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile + + float defaultAlpha = 1.f; + + if (!alphaPtr) + alphaPtr.Reset(&defaultAlpha, 0); // Same + + if (material->IsDepthSortingEnabled()) + { + for (std::size_t i = 0; i < billboardCount; ++i) + { + depthSortedBillboards.Insert({ + renderOrder, + material, + scissorRect, + { + ComputeColor(*alphaPtr++), + *positionPtr++, + ComputeSize(*sizePtr++), + ComputeSinCos(*anglePtr++) + } + }); + } + } + else + { + std::size_t billboardIndex = m_billboards.size(); + m_billboards.resize(billboardIndex + billboardCount); + BillboardData* data = &m_billboards[billboardIndex]; + + for (std::size_t i = 0; i < billboardCount; ++i) + { + data->center = *positionPtr++; + data->color = ComputeColor(*alphaPtr++); + data->sinCos = ComputeSinCos(*anglePtr++); + data->size = ComputeSize(*sizePtr++); + data++; + } + + billboards.Insert({ + renderOrder, + material, + scissorRect, + billboardCount, + billboardIndex + }); + } + } + + /*! + * \brief Adds drawable to the queue + * + * \param renderOrder Order of rendering + * \param drawable Drawable user defined + * + * \remark Produces a NazaraError if drawable is invalid + */ + void BasicRenderQueue::AddDrawable(int renderOrder, const Drawable* drawable) + { + NazaraAssert(drawable, "Invalid material"); + + RegisterLayer(renderOrder); + + customDrawables.Insert({ + renderOrder, + drawable + }); + } + + /*! + * \brief Adds mesh to the queue + * + * \param renderOrder Order of rendering + * \param material Material of the mesh + * \param meshData Data of the mesh + * \param meshAABB Box of the mesh + * \param transformMatrix Matrix of the mesh + * + * \remark Produces a NazaraAssert if material is invalid + */ + void BasicRenderQueue::AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Nz::Matrix4f& transformMatrix, std::size_t instanceIndex, const Recti& scissorRect) + { + NazaraAssert(material, "Invalid material"); + + RegisterLayer(renderOrder); + + Spheref obbSphere(transformMatrix.GetTranslation() + meshAABB.GetCenter(), meshAABB.GetSquaredRadius()); + + if (material->IsDepthSortingEnabled()) + { + depthSortedModels.Insert({ + renderOrder, + instanceIndex, + meshData, + material, + scissorRect, + obbSphere + }); + } + else + { + models.Insert({ + renderOrder, + instanceIndex, + meshData, + material, + scissorRect, + obbSphere + }); + } + } + + /*! + * \brief Adds sprites to the queue + * + * \param renderOrder Order of rendering + * \param material Material of the sprites + * \param vertices Buffer of data for the sprites + * \param spriteCount Number of sprites + * \param overlay Texture of the sprites + * + * \remark Produces a NazaraAssert if material is invalid + */ + void BasicRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Recti& scissorRect, const Texture* overlay /*= nullptr*/) + { + NazaraAssert(material, "Invalid material"); + + RegisterLayer(renderOrder); + + if (material->IsDepthSortingEnabled()) + { + depthSortedSprites.Insert({ + renderOrder, + spriteCount, + material, + overlay, + vertices, + scissorRect + }); + } + else + { + basicSprites.Insert({ + renderOrder, + spriteCount, + material, + overlay, + vertices, + scissorRect + }); + } + } + + /*! + * \brief Clears the queue + * + * \param fully Should everything be cleared or we can keep layers + */ + + void BasicRenderQueue::Clear(bool fully) + { + AbstractRenderQueue::Clear(fully); + + basicSprites.Clear(); + billboards.Clear(); + depthSortedBillboards.Clear(); + depthSortedModels.Clear(); + depthSortedSprites.Clear(); + models.Clear(); + + m_pipelineCache.clear(); + m_materialCache.clear(); + m_overlayCache.clear(); + m_shaderCache.clear(); + m_textureCache.clear(); + m_vertexBufferCache.clear(); + + m_billboards.clear(); + m_renderLayers.clear(); + } + + /*! + * \brief Sorts the object according to the viewer position, furthest to nearest + * + * \param viewer Viewer of the scene + */ + void BasicRenderQueue::Sort(const AbstractViewer* viewer) + { + m_layerCache.clear(); + for (int layer : m_renderLayers) + m_layerCache.emplace(layer, m_layerCache.size()); + + auto GetOrInsert = [](auto& container, auto&& value) + { + auto it = container.find(value); + if (it == container.end()) + it = container.emplace(value, container.size()).first; + + return it->second; + }; + + basicSprites.Sort([&](const SpriteChain& vertices) + { + // RQ index: + // - Layer (16bits) + // - Pipeline (8bits) + // - Material (8bits) + // - Shader? (8bits) + // - Textures (8bits) + // - Overlay (8bits) + // - Scissor (4bits) + // - ??? (4bits) + + UInt64 layerIndex = m_layerCache[vertices.layerIndex]; + UInt64 pipelineIndex = GetOrInsert(m_pipelineCache, vertices.material->GetPipeline()); + UInt64 materialIndex = GetOrInsert(m_materialCache, vertices.material); + UInt64 shaderIndex = GetOrInsert(m_shaderCache, vertices.material->GetShader()); + UInt64 textureIndex = 0;/* GetOrInsert(m_textureCache, vertices.material->GetDiffuseMap());*/ + UInt64 overlayIndex = GetOrInsert(m_overlayCache, vertices.overlay); + UInt64 scissorIndex = 0; //< TODO + + UInt64 index = (layerIndex & 0xFFFF) << 48 | + (pipelineIndex & 0xFF) << 40 | + (materialIndex & 0xFF) << 32 | + (shaderIndex & 0xFF) << 24 | + (textureIndex & 0xFF) << 16 | + (overlayIndex & 0xFF) << 8 | + (scissorIndex & 0x0F) << 4; + + return index; + }); + + billboards.Sort([&](const BillboardChain& billboard) + { + // RQ index: + // - Layer (16bits) + // - Pipeline (8bits) + // - Material (8bits) + // - Shader? (8bits) + // - Textures (8bits) + // - Scissor (4bits) + // - ??? (12bits) + + UInt64 layerIndex = m_layerCache[billboard.layerIndex]; + UInt64 pipelineIndex = GetOrInsert(m_pipelineCache, billboard.material->GetPipeline()); + UInt64 materialIndex = GetOrInsert(m_materialCache, billboard.material); + UInt64 shaderIndex = GetOrInsert(m_shaderCache, billboard.material->GetShader()); + UInt64 textureIndex = 0; /*GetOrInsert(m_textureCache, billboard.material->GetDiffuseMap())*/; + UInt64 unknownIndex = 0; //< ??? + UInt64 scissorIndex = 0; //< TODO + + UInt64 index = (layerIndex & 0xFFFF) << 48 | + (pipelineIndex & 0xFF) << 40 | + (materialIndex & 0xFF) << 32 | + (shaderIndex & 0xFF) << 24 | + (textureIndex & 0xFF) << 16 | + (scissorIndex & 0x0F) << 12 | + (unknownIndex & 0xFF) << 0; + + return index; + }); + + customDrawables.Sort([&](const CustomDrawable& drawable) + { + // RQ index: + // - Layer (16bits) + + UInt64 layerIndex = m_layerCache[drawable.layerIndex]; + + UInt64 index = (layerIndex & 0xFFFF) << 48; + + return index; + + }); + + models.Sort([&](const Model& renderData) + { + // RQ index: + // - Layer (16bits) + // - Pipeline (8bits) + // - Material (8bits) + // - Shader? (8bits) + // - Textures (8bits) + // - Buffers (8bits) + // - Scissor (4bits) + // - ??? (4bits) + + UInt64 layerIndex = m_layerCache[renderData.layerIndex]; + UInt64 pipelineIndex = GetOrInsert(m_pipelineCache, renderData.material->GetPipeline()); + UInt64 materialIndex = GetOrInsert(m_materialCache, renderData.material); + UInt64 shaderIndex = GetOrInsert(m_shaderCache, renderData.material->GetShader()); + UInt64 textureIndex = 0;/* GetOrInsert(m_textureCache, renderData.material->GetDiffuseMap()) */; + UInt64 bufferIndex = GetOrInsert(m_vertexBufferCache, renderData.meshData.vertexBuffer); + UInt64 scissorIndex = 0; //< TODO + UInt64 depthIndex = 0; //< TODO + + UInt64 index = (layerIndex & 0xFFFF) << 48 | + (pipelineIndex & 0xFF) << 40 | + (materialIndex & 0xFF) << 32 | + (shaderIndex & 0xFF) << 24 | + (textureIndex & 0xFF) << 16 | + (bufferIndex & 0xFF) << 8 | + (scissorIndex & 0x0F) << 4; + + return index; + }); + + static_assert(std::numeric_limits::is_iec559, "The following sorting functions relies on IEEE 754 floatings-points"); + +#if defined(arm) && \ + ((defined(__MAVERICK__) && defined(NAZARA_BIG_ENDIAN)) || \ + (!defined(__SOFTFP__) && !defined(__VFP_FP__) && !defined(__MAVERICK__))) + #error The following code relies on native-endian IEEE-754 representation, which your platform does not guarantee +#endif + + Planef nearPlane = viewer->GetFrustum().GetPlane(FrustumPlane_Near); + + depthSortedBillboards.Sort([&](const Billboard& billboard) + { + // RQ index: + // - Layer (16bits) + // - Depth (32bits) + // - ?? (16bits) + + // Reinterpret depth as UInt32 (this will work as long as they're all either positive or negative, + // a negative distance may happen with billboard behind the camera which we don't care about since they'll not be rendered) + float depth = nearPlane.Distance(billboard.data.center); + + UInt64 layerIndex = m_layerCache[billboard.layerIndex]; + UInt64 depthIndex = ~reinterpret_cast(depth); + + UInt64 index = (layerIndex & 0xFFFF) << 48 | + (depthIndex & 0xFFFFFFFF) << 16; + + return index; + }); + + if (viewer->GetProjectionType() == ProjectionType_Orthogonal) + { + depthSortedModels.Sort([&](const Model& model) + { + // RQ index: + // - Layer (16bits) + // - Depth (32bits) + // - ?? (16bits) + + float depth = nearPlane.Distance(model.obbSphere.GetPosition()); + + UInt64 layerIndex = m_layerCache[model.layerIndex]; + UInt64 depthIndex = ~reinterpret_cast(depth); + + UInt64 index = (layerIndex & 0xFFFF) << 48 | + (depthIndex & 0xFFFFFFFF) << 16; + + return index; + }); + + depthSortedSprites.Sort([&](const SpriteChain& spriteChain) + { + // RQ index: + // - Layer (16bits) + // - Depth (32bits) + // - ?? (16bits) + + float depth = nearPlane.Distance(spriteChain.vertices[0].position); + + UInt64 layerIndex = m_layerCache[spriteChain.layerIndex]; + UInt64 depthIndex = ~reinterpret_cast(depth); + + UInt64 index = (layerIndex & 0xFFFF) << 48 | + (depthIndex & 0xFFFFFFFF) << 16; + + return index; + }); + } + else + { + Vector3f viewerPos = viewer->GetEyePosition(); + + depthSortedModels.Sort([&](const Model& model) + { + // RQ index: + // - Layer (16bits) + // - Depth (32bits) + // - ?? (16bits) + + float depth = viewerPos.SquaredDistance(model.obbSphere.GetPosition()); + + UInt64 layerIndex = m_layerCache[model.layerIndex]; + UInt64 depthIndex = ~reinterpret_cast(depth); + + UInt64 index = (layerIndex & 0x0F) << 48 | + (depthIndex & 0xFFFFFFFF) << 16; + + return index; + }); + + depthSortedSprites.Sort([&](const SpriteChain& sprites) + { + // RQ index: + // - Layer (16bits) + // - Depth (32bits) + // - ?? (16bits) + + float depth = viewerPos.SquaredDistance(sprites.vertices[0].position); + + UInt64 layerIndex = m_layerCache[sprites.layerIndex]; + UInt64 depthIndex = ~reinterpret_cast(depth); + + UInt64 index = (layerIndex & 0xFFFF) << 48 | + (depthIndex & 0xFFFFFFFF) << 16; + + return index; + }); + } + } +} diff --git a/src/Nazara/Graphics/Graphics.cpp b/src/Nazara/Graphics/Graphics.cpp index b2ac1d928..0ae24e7c6 100644 --- a/src/Nazara/Graphics/Graphics.cpp +++ b/src/Nazara/Graphics/Graphics.cpp @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include namespace Nz @@ -13,13 +14,29 @@ namespace Nz * \brief Audio class that represents the module initializer of Graphics */ - Graphics::Graphics(Config /*config*/) : + Graphics::Graphics(Config config) : ModuleBase("Graphics", this) { - } + Renderer* renderer = Renderer::Instance(); + RendererImpl* rendererImpl = renderer->GetRendererImpl(); //< FIXME + std::vector renderDeviceInfo = rendererImpl->QueryRenderDevices(); + if (renderDeviceInfo.empty()) + throw std::runtime_error("no render device available"); - Graphics::~Graphics() - { + std::size_t bestRenderDeviceIndex = 0; + for (std::size_t i = 0; i < renderDeviceInfo.size(); ++i) + { + const auto& deviceInfo = renderDeviceInfo[i]; + if (config.useDedicatedRenderDevice && deviceInfo.type == RenderDeviceType::Dedicated) + { + bestRenderDeviceIndex = i; + break; + } + } + + m_renderDevice = rendererImpl->InstanciateRenderDevice(bestRenderDeviceIndex); + if (!m_renderDevice) + throw std::runtime_error("failed to instantiate render device"); } Graphics* Graphics::s_instance = nullptr; diff --git a/src/Nazara/Graphics/Material.cpp b/src/Nazara/Graphics/Material.cpp new file mode 100644 index 000000000..8b8fafaf5 --- /dev/null +++ b/src/Nazara/Graphics/Material.cpp @@ -0,0 +1,487 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + /*! + * \ingroup graphics + * \class Nz::Material + * \brief Graphics class that represents a material + */ + + /*! + * \brief Checks whether the parameters for the material are correct + * \return true If parameters are valid + */ + bool MaterialParams::IsValid() const + { + if (!UberShaderLibrary::Has(shaderName)) + return false; + + return true; + } + + /*! + * \brief Constructs a Material object with default states + * + * \see Reset + */ + Material::Material(std::shared_ptr settings) : + m_settings(std::move(settings)), + m_reflectionMode(ReflectionMode_Skybox), + m_pipelineUpdated(false), + m_shadowCastingEnabled(true), + m_reflectionSize(256) + { + m_pipelineInfo.settings = m_settings; + SetShader("Basic"); + + m_textures.resize(m_settings->GetTextures().size()); + + m_uniformBuffers.reserve(m_settings->GetUniformBlocks().size()); + for (const auto& uniformBufferInfo : m_settings->GetUniformBlocks()) + { + //TODO: Use pools + UniformBufferRef ubo = UniformBuffer::New(static_cast(uniformBufferInfo.blockSize), DataStorage_Hardware, BufferUsage_Dynamic); + ubo->Fill(uniformBufferInfo.defaultValues.data(), 0, uniformBufferInfo.defaultValues.size()); + + m_uniformBuffers.emplace_back(std::move(ubo)); + } + } + + /*! + * \brief Applies shader to the material + * + * \param instance Pipeline instance to update + * \param textureUnit Unit for the texture GL_TEXTURE"i" + * \param lastUsedUnit Optional argument to get the last texture unit + */ + void Material::Apply(const MaterialPipeline::Instance& instance) const + { + const Shader* shader = instance.renderPipeline.GetInfo().shader; + + unsigned int bindingIndex = 0; + + for (const MaterialTexture& textureData : m_textures) + { + auto it = instance.bindings.find(bindingIndex++); + assert(it != instance.bindings.end()); + + unsigned int textureIndex = it->second; + + Renderer::SetTexture(textureIndex, textureData.texture); + Renderer::SetTextureSampler(textureIndex, textureData.sampler); + } + + for (const UniformBufferRef& ubo : m_uniformBuffers) + { + auto it = instance.bindings.find(bindingIndex++); + assert(it != instance.bindings.end()); + + unsigned int uniformBufferIndex = it->second; + + Renderer::SetUniformBuffer(uniformBufferIndex, ubo); + } + + /*if (instance.uniforms[MaterialUniform_AlphaThreshold] != -1) + shader->SendFloat(instance.uniforms[MaterialUniform_AlphaThreshold], m_alphaThreshold); + + if (instance.uniforms[MaterialUniform_Ambient] != -1) + shader->SendColor(instance.uniforms[MaterialUniform_Ambient], m_ambientColor); + + if (instance.uniforms[MaterialUniform_Diffuse] != -1) + shader->SendColor(instance.uniforms[MaterialUniform_Diffuse], m_diffuseColor); + + if (instance.uniforms[MaterialUniform_Shininess] != -1) + shader->SendFloat(instance.uniforms[MaterialUniform_Shininess], m_shininess); + + if (instance.uniforms[MaterialUniform_Specular] != -1) + shader->SendColor(instance.uniforms[MaterialUniform_Specular], m_specularColor);*/ + + /*if (m_alphaMap && instance.uniforms[MaterialUniform_AlphaMap] != -1) + { + unsigned int textureUnit = s_textureUnits[TextureMap_Alpha]; + + Renderer::SetTexture(textureUnit, m_alphaMap); + Renderer::SetTextureSampler(textureUnit, m_diffuseSampler); + } + + if (m_diffuseMap && instance.uniforms[MaterialUniform_DiffuseMap] != -1) + { + unsigned int textureUnit = s_textureUnits[TextureMap_Diffuse]; + + Renderer::SetTexture(textureUnit, m_diffuseMap); + Renderer::SetTextureSampler(textureUnit, m_diffuseSampler); + } + + if (m_emissiveMap && instance.uniforms[MaterialUniform_EmissiveMap] != -1) + { + unsigned int textureUnit = s_textureUnits[TextureMap_Emissive]; + + Renderer::SetTexture(textureUnit, m_emissiveMap); + Renderer::SetTextureSampler(textureUnit, m_diffuseSampler); + } + + if (m_heightMap && instance.uniforms[MaterialUniform_HeightMap] != -1) + { + unsigned int textureUnit = s_textureUnits[TextureMap_Height]; + + Renderer::SetTexture(textureUnit, m_heightMap); + Renderer::SetTextureSampler(textureUnit, m_diffuseSampler); + } + + if (m_normalMap && instance.uniforms[MaterialUniform_NormalMap] != -1) + { + unsigned int textureUnit = s_textureUnits[TextureMap_Normal]; + + Renderer::SetTexture(textureUnit, m_normalMap); + Renderer::SetTextureSampler(textureUnit, m_diffuseSampler); + } + + if (m_specularMap && instance.uniforms[MaterialUniform_SpecularMap] != -1) + { + unsigned int textureUnit = s_textureUnits[TextureMap_Specular]; + + Renderer::SetTexture(textureUnit, m_specularMap); + Renderer::SetTextureSampler(textureUnit, m_specularSampler); + }*/ + } + + /*! + * \brief Builds the material from a parameter list + * + * \param matData Data information for the material + * \param matParams Additional parameters for the material + */ + void Material::BuildFromParameters(const ParameterList& matData, const MaterialParams& matParams) + { + Color color; + bool isEnabled; + double dValue; + long long iValue; + String path; + + ErrorFlags errFlags(ErrorFlag_Silent | ErrorFlag_ThrowExceptionDisabled, true); + + /*if (matData.GetDoubleParameter(MaterialData::AlphaThreshold, &dValue)) + SetAlphaThreshold(float(dValue));*/ + + if (matData.GetBooleanParameter(MaterialData::AlphaTest, &isEnabled)) + EnableAlphaTest(isEnabled); + + /*if (matData.GetColorParameter(MaterialData::AmbientColor, &color)) + SetAmbientColor(color);*/ + + if (matData.GetIntegerParameter(MaterialData::CullingSide, &iValue)) + SetFaceCulling(static_cast(iValue)); + + if (matData.GetIntegerParameter(MaterialData::DepthFunc, &iValue)) + SetDepthFunc(static_cast(iValue)); + + if (matData.GetBooleanParameter(MaterialData::DepthSorting, &isEnabled)) + EnableDepthSorting(isEnabled); + + /*if (matData.GetColorParameter(MaterialData::DiffuseColor, &color)) + SetDiffuseColor(color);*/ + + if (matData.GetIntegerParameter(MaterialData::DstBlend, &iValue)) + SetDstBlend(static_cast(iValue)); + + if (matData.GetIntegerParameter(MaterialData::FaceFilling, &iValue)) + SetFaceFilling(static_cast(iValue)); + + if (matData.GetDoubleParameter(MaterialData::LineWidth, &dValue)) + SetLineWidth(float(dValue)); + + if (matData.GetDoubleParameter(MaterialData::PointSize, &dValue)) + SetPointSize(float(dValue)); + + /*if (matData.GetColorParameter(MaterialData::SpecularColor, &color)) + SetSpecularColor(color); + + if (matData.GetDoubleParameter(MaterialData::Shininess, &dValue)) + SetShininess(float(dValue));*/ + + if (matData.GetIntegerParameter(MaterialData::SrcBlend, &iValue)) + SetSrcBlend(static_cast(iValue)); + + // RendererParameter + if (matData.GetBooleanParameter(MaterialData::Blending, &isEnabled)) + EnableBlending(isEnabled); + + if (matData.GetBooleanParameter(MaterialData::ColorWrite, &isEnabled)) + EnableColorWrite(isEnabled); + + if (matData.GetBooleanParameter(MaterialData::DepthBuffer, &isEnabled)) + EnableDepthBuffer(isEnabled); + + if (matData.GetBooleanParameter(MaterialData::DepthWrite, &isEnabled)) + EnableDepthWrite(isEnabled); + + if (matData.GetBooleanParameter(MaterialData::FaceCulling, &isEnabled)) + EnableFaceCulling(isEnabled); + + if (matData.GetBooleanParameter(MaterialData::ScissorTest, &isEnabled)) + EnableScissorTest(isEnabled); + + if (matData.GetBooleanParameter(MaterialData::StencilTest, &isEnabled)) + EnableStencilTest(isEnabled); + + if (matData.GetBooleanParameter(MaterialData::VertexColor, &isEnabled)) + EnableVertexColor(isEnabled); + + // Samplers + /*if (matData.GetIntegerParameter(MaterialData::DiffuseAnisotropyLevel, &iValue)) + m_diffuseSampler.SetAnisotropyLevel(static_cast(iValue)); + + if (matData.GetIntegerParameter(MaterialData::DiffuseFilter, &iValue)) + m_diffuseSampler.SetFilterMode(static_cast(iValue)); + + if (matData.GetIntegerParameter(MaterialData::DiffuseWrap, &iValue)) + m_diffuseSampler.SetWrapMode(static_cast(iValue)); + + if (matData.GetIntegerParameter(MaterialData::SpecularAnisotropyLevel, &iValue)) + m_specularSampler.SetAnisotropyLevel(static_cast(iValue)); + + if (matData.GetIntegerParameter(MaterialData::SpecularFilter, &iValue)) + m_specularSampler.SetFilterMode(static_cast(iValue)); + + if (matData.GetIntegerParameter(MaterialData::SpecularWrap, &iValue)) + m_specularSampler.SetWrapMode(static_cast(iValue));*/ + + // Stencil + if (matData.GetIntegerParameter(MaterialData::StencilCompare, &iValue)) + m_pipelineInfo.stencilCompare.front = static_cast(iValue); + + if (matData.GetIntegerParameter(MaterialData::StencilFail, &iValue)) + m_pipelineInfo.stencilFail.front = static_cast(iValue); + + if (matData.GetIntegerParameter(MaterialData::StencilPass, &iValue)) + m_pipelineInfo.stencilPass.front = static_cast(iValue); + + if (matData.GetIntegerParameter(MaterialData::StencilZFail, &iValue)) + m_pipelineInfo.stencilDepthFail.front = static_cast(iValue); + + if (matData.GetIntegerParameter(MaterialData::StencilMask, &iValue)) + m_pipelineInfo.stencilWriteMask.front = static_cast(iValue); + + if (matData.GetIntegerParameter(MaterialData::StencilReference, &iValue)) + m_pipelineInfo.stencilReference.front = static_cast(iValue); + + // Stencil (back) + if (matData.GetIntegerParameter(MaterialData::BackFaceStencilCompare, &iValue)) + m_pipelineInfo.stencilCompare.back = static_cast(iValue); + + if (matData.GetIntegerParameter(MaterialData::BackFaceStencilFail, &iValue)) + m_pipelineInfo.stencilFail.back = static_cast(iValue); + + if (matData.GetIntegerParameter(MaterialData::BackFaceStencilPass, &iValue)) + m_pipelineInfo.stencilPass.back = static_cast(iValue); + + if (matData.GetIntegerParameter(MaterialData::BackFaceStencilZFail, &iValue)) + m_pipelineInfo.stencilDepthFail.back = static_cast(iValue); + + if (matData.GetIntegerParameter(MaterialData::BackFaceStencilMask, &iValue)) + m_pipelineInfo.stencilWriteMask.back = static_cast(iValue); + + if (matData.GetIntegerParameter(MaterialData::BackFaceStencilReference, &iValue)) + m_pipelineInfo.stencilReference.back = static_cast(iValue); + + InvalidatePipeline(); + + // Textures + /*if (matParams.loadAlphaMap && matData.GetStringParameter(MaterialData::AlphaTexturePath, &path)) + SetAlphaMap(path); + + if (matParams.loadDiffuseMap && matData.GetStringParameter(MaterialData::DiffuseTexturePath, &path)) + SetDiffuseMap(path); + + if (matParams.loadEmissiveMap && matData.GetStringParameter(MaterialData::EmissiveTexturePath, &path)) + SetEmissiveMap(path); + + if (matParams.loadHeightMap && matData.GetStringParameter(MaterialData::HeightTexturePath, &path)) + SetHeightMap(path); + + if (matParams.loadNormalMap && matData.GetStringParameter(MaterialData::NormalTexturePath, &path)) + SetNormalMap(path); + + if (matParams.loadSpecularMap && matData.GetStringParameter(MaterialData::SpecularTexturePath, &path)) + SetSpecularMap(path);*/ + + SetShader(matParams.shaderName); + } + + /*! + * \brief Builds a ParameterList with material data + * + * \param matData Destination parameter list which will receive material data + */ + void Material::SaveToParameters(ParameterList* matData) + { + NazaraAssert(matData, "Invalid ParameterList"); + + matData->SetParameter(MaterialData::AlphaTest, IsAlphaTestEnabled()); + //matData->SetParameter(MaterialData::AlphaThreshold, GetAlphaThreshold()); + //matData->SetParameter(MaterialData::AmbientColor, GetAmbientColor()); + matData->SetParameter(MaterialData::CullingSide, static_cast(GetFaceCulling())); + matData->SetParameter(MaterialData::DepthFunc, static_cast(GetDepthFunc())); + matData->SetParameter(MaterialData::DepthSorting, IsDepthSortingEnabled()); + //matData->SetParameter(MaterialData::DiffuseColor, GetDiffuseColor()); + matData->SetParameter(MaterialData::DstBlend, static_cast(GetDstBlend())); + matData->SetParameter(MaterialData::FaceFilling, static_cast(GetFaceFilling())); + matData->SetParameter(MaterialData::LineWidth, GetLineWidth()); + matData->SetParameter(MaterialData::PointSize, GetPointSize()); + //matData->SetParameter(MaterialData::Shininess, GetShininess()); + //matData->SetParameter(MaterialData::SpecularColor, GetSpecularColor()); + matData->SetParameter(MaterialData::SrcBlend, static_cast(GetSrcBlend())); + + // RendererParameter + matData->SetParameter(MaterialData::Blending, IsBlendingEnabled()); + matData->SetParameter(MaterialData::ColorWrite, IsColorWriteEnabled()); + matData->SetParameter(MaterialData::DepthBuffer, IsDepthBufferEnabled()); + matData->SetParameter(MaterialData::DepthWrite, IsDepthWriteEnabled()); + matData->SetParameter(MaterialData::FaceCulling, IsFaceCullingEnabled()); + matData->SetParameter(MaterialData::ScissorTest, IsScissorTestEnabled()); + matData->SetParameter(MaterialData::StencilTest, IsStencilTestEnabled()); + matData->SetParameter(MaterialData::VertexColor, HasVertexColor()); + + // Samplers + /*matData->SetParameter(MaterialData::DiffuseAnisotropyLevel, static_cast(GetDiffuseSampler().GetAnisotropicLevel())); + matData->SetParameter(MaterialData::DiffuseFilter, static_cast(GetDiffuseSampler().GetFilterMode())); + matData->SetParameter(MaterialData::DiffuseWrap, static_cast(GetDiffuseSampler().GetWrapMode())); + + matData->SetParameter(MaterialData::SpecularAnisotropyLevel, static_cast(GetSpecularSampler().GetAnisotropicLevel())); + matData->SetParameter(MaterialData::SpecularFilter, static_cast(GetSpecularSampler().GetFilterMode())); + matData->SetParameter(MaterialData::SpecularWrap, static_cast(GetSpecularSampler().GetWrapMode()));*/ + + // Stencil + matData->SetParameter(MaterialData::StencilCompare, static_cast(GetPipelineInfo().stencilCompare.front)); + matData->SetParameter(MaterialData::StencilFail, static_cast(GetPipelineInfo().stencilFail.front)); + matData->SetParameter(MaterialData::StencilPass, static_cast(GetPipelineInfo().stencilPass.front)); + matData->SetParameter(MaterialData::StencilZFail, static_cast(GetPipelineInfo().stencilDepthFail.front)); + matData->SetParameter(MaterialData::StencilMask, static_cast(GetPipelineInfo().stencilWriteMask.front)); + matData->SetParameter(MaterialData::StencilReference, static_cast(GetPipelineInfo().stencilReference.front)); + + // Stencil (back) + matData->SetParameter(MaterialData::BackFaceStencilCompare, static_cast(GetPipelineInfo().stencilCompare.back)); + matData->SetParameter(MaterialData::BackFaceStencilFail, static_cast(GetPipelineInfo().stencilFail.back)); + matData->SetParameter(MaterialData::BackFaceStencilPass, static_cast(GetPipelineInfo().stencilPass.back)); + matData->SetParameter(MaterialData::BackFaceStencilZFail, static_cast(GetPipelineInfo().stencilDepthFail.back)); + matData->SetParameter(MaterialData::BackFaceStencilMask, static_cast(GetPipelineInfo().stencilWriteMask.back)); + matData->SetParameter(MaterialData::BackFaceStencilReference, static_cast(GetPipelineInfo().stencilReference.back)); + + // Textures + /*if (HasAlphaMap()) + { + const String& path = GetAlphaMap()->GetFilePath(); + if (!path.IsEmpty()) + matData->SetParameter(MaterialData::AlphaTexturePath, path); + } + + if (HasDiffuseMap()) + { + const String& path = GetDiffuseMap()->GetFilePath(); + if (!path.IsEmpty()) + matData->SetParameter(MaterialData::DiffuseTexturePath, path); + } + + if (HasEmissiveMap()) + { + const String& path = GetEmissiveMap()->GetFilePath(); + if (!path.IsEmpty()) + matData->SetParameter(MaterialData::EmissiveTexturePath, path); + } + + if (HasHeightMap()) + { + const String& path = GetHeightMap()->GetFilePath(); + if (!path.IsEmpty()) + matData->SetParameter(MaterialData::HeightTexturePath, path); + } + + if (HasNormalMap()) + { + const String& path = GetNormalMap()->GetFilePath(); + if (!path.IsEmpty()) + matData->SetParameter(MaterialData::NormalTexturePath, path); + } + + if (HasSpecularMap()) + { + const String& path = GetSpecularMap()->GetFilePath(); + if (!path.IsEmpty()) + matData->SetParameter(MaterialData::SpecularTexturePath, path); + }*/ + } + + /*! + * \brief Initializes the material librairies + * \return true If successful + * + * \remark Produces a NazaraError if the material library failed to be initialized + */ + bool Material::Initialize() + { + if (!MaterialLibrary::Initialize()) + { + NazaraError("Failed to initialise library"); + return false; + } + + if (!MaterialManager::Initialize()) + { + NazaraError("Failed to initialise manager"); + return false; + } + + s_defaultMaterial = New(BasicMaterial::GetSettings()); + s_defaultMaterial->EnableFaceCulling(false); + s_defaultMaterial->SetFaceFilling(FaceFilling_Line); + MaterialLibrary::Register("Default", s_defaultMaterial); + + unsigned int textureUnit = 0; + + s_textureUnits[TextureMap_Diffuse] = textureUnit++; + s_textureUnits[TextureMap_Alpha] = textureUnit++; + s_textureUnits[TextureMap_Specular] = textureUnit++; + s_textureUnits[TextureMap_Normal] = textureUnit++; + s_textureUnits[TextureMap_Emissive] = textureUnit++; + s_textureUnits[TextureMap_Overlay] = textureUnit++; + s_textureUnits[TextureMap_ReflectionCube] = textureUnit++; + s_textureUnits[TextureMap_Height] = textureUnit++; + s_textureUnits[TextureMap_Shadow2D_1] = textureUnit++; + s_textureUnits[TextureMap_ShadowCube_1] = textureUnit++; + s_textureUnits[TextureMap_Shadow2D_2] = textureUnit++; + s_textureUnits[TextureMap_ShadowCube_2] = textureUnit++; + s_textureUnits[TextureMap_Shadow2D_3] = textureUnit++; + s_textureUnits[TextureMap_ShadowCube_3] = textureUnit++; + + return true; + } + + /*! + * \brief Uninitializes the material librairies + */ + void Material::Uninitialize() + { + s_defaultMaterial.Reset(); + + MaterialManager::Uninitialize(); + MaterialLibrary::Uninitialize(); + } + + std::array Material::s_textureUnits; + MaterialLibrary::LibraryMap Material::s_library; + MaterialLoader::LoaderList Material::s_loaders; + MaterialManager::ManagerMap Material::s_managerMap; + MaterialManager::ManagerParams Material::s_managerParameters; + MaterialRef Material::s_defaultMaterial = nullptr; +} diff --git a/src/Nazara/Graphics/MaterialPipeline.cpp b/src/Nazara/Graphics/MaterialPipeline.cpp new file mode 100644 index 000000000..7cd4b808c --- /dev/null +++ b/src/Nazara/Graphics/MaterialPipeline.cpp @@ -0,0 +1,235 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + namespace + { + const UInt8 r_basicFragmentShader[] = { + #include + }; + + const UInt8 r_basicVertexShader[] = { + #include + }; + + const UInt8 r_phongLightingFragmentShader[] = { + #include + }; + + const UInt8 r_phongLightingVertexShader[] = { + #include + }; + + void OverrideShader(const String& path, String* source) + { + ErrorFlags errFlags(ErrorFlag_Silent | ErrorFlag_ThrowExceptionDisabled); + + File shaderFile(path, Nz::OpenMode_ReadOnly | Nz::OpenMode_Text); + if (shaderFile.IsOpen()) + { + StringStream shaderSource; + + while (!shaderFile.EndOfFile()) + { + shaderSource << shaderFile.ReadLine(); + shaderSource << '\n'; + } + + *source = shaderSource; + + NazaraNotice(path + " will be used to override built-in shader"); + } + } + } + + /*! + * \ingroup graphics + * \class Nz::MaterialPipeline + * + * \brief Graphics class used to contains all rendering states that are not allowed to change individually on rendering devices + */ + + /*! + * \brief Returns a reference to a MaterialPipeline built with MaterialPipelineInfo + * + * This function is using a cache, calling it multiples times with the same MaterialPipelineInfo will returns references to a single MaterialPipeline + * + * \param pipelineInfo Pipeline informations used to build/retrieve a MaterialPipeline object + */ + MaterialPipelineRef MaterialPipeline::GetPipeline(const MaterialPipelineInfo& pipelineInfo) + { + auto it = s_pipelineCache.find(pipelineInfo); + if (it == s_pipelineCache.end()) + it = s_pipelineCache.insert(it, PipelineCache::value_type(pipelineInfo, New(pipelineInfo))); + + return it->second; + } + + void MaterialPipeline::GenerateRenderPipeline(UInt32 flags) const + { + NazaraAssert(m_pipelineInfo.settings, "Material pipeline has no settings"); + NazaraAssert(m_pipelineInfo.uberShader, "Material pipeline has no uber shader"); + + const auto& textures = m_pipelineInfo.settings->GetTextures(); + + ParameterList list; + for (std::size_t i = 0, texCount = textures.size(); i < texCount; ++i) + { + const auto& texture = textures[i]; + String parameterName = "HAS_" + texture.name.ToUpper() + "_TEXTURE"; + + list.SetParameter(parameterName, (m_pipelineInfo.textures & (1 << i)) != 0); + } + + list.SetParameter("ALPHA_TEST", m_pipelineInfo.alphaTest); + list.SetParameter("REFLECTION_MAPPING", m_pipelineInfo.reflectionMapping); + list.SetParameter("SHADOW_MAPPING", m_pipelineInfo.shadowReceive); + list.SetParameter("TEXTURE_MAPPING", m_pipelineInfo.textures != 0 || + m_pipelineInfo.reflectionMapping || flags & ShaderFlags_TextureOverlay); + list.SetParameter("TRANSFORM", true); + + list.SetParameter("FLAG_BILLBOARD", static_cast((flags & ShaderFlags_Billboard) != 0)); + list.SetParameter("FLAG_DEFERRED", static_cast((flags & ShaderFlags_Deferred) != 0)); + list.SetParameter("FLAG_INSTANCING", static_cast((flags & ShaderFlags_Instancing) != 0)); + list.SetParameter("FLAG_TEXTUREOVERLAY", static_cast((flags & ShaderFlags_TextureOverlay) != 0)); + list.SetParameter("FLAG_VERTEXCOLOR", m_pipelineInfo.hasVertexColor || static_cast((flags & ShaderFlags_VertexColor) != 0)); + + Instance& instance = m_instances[flags]; + instance.uberInstance = m_pipelineInfo.uberShader->Get(list); + + RenderPipelineInfo renderPipelineInfo; + static_cast(renderPipelineInfo).operator=(m_pipelineInfo); // Not my proudest line + + renderPipelineInfo.shader = instance.uberInstance->GetShader(); + + instance.renderPipeline.Create(renderPipelineInfo); + + // Send texture units (those never changes) + const RenderPipelineLayout* pipelineLayout = m_pipelineInfo.pipelineLayout; + if (!pipelineLayout) + pipelineLayout = m_pipelineInfo.settings->GetRenderPipelineLayout(); + + instance.bindings = renderPipelineInfo.shader->ApplyLayout(pipelineLayout); + + renderPipelineInfo.shader->SendInteger(renderPipelineInfo.shader->GetUniformLocation("ReflectionMap"), Material::GetTextureUnit(TextureMap_ReflectionCube)); + + renderPipelineInfo.shader->SendInteger(renderPipelineInfo.shader->GetUniformLocation("DirectionalSpotLightShadowMap[0]"), Material::GetTextureUnit(TextureMap_Shadow2D_1)); + renderPipelineInfo.shader->SendInteger(renderPipelineInfo.shader->GetUniformLocation("DirectionalSpotLightShadowMap[1]"), Material::GetTextureUnit(TextureMap_Shadow2D_2)); + renderPipelineInfo.shader->SendInteger(renderPipelineInfo.shader->GetUniformLocation("DirectionalSpotLightShadowMap[2]"), Material::GetTextureUnit(TextureMap_Shadow2D_3)); + + renderPipelineInfo.shader->SendInteger(renderPipelineInfo.shader->GetUniformLocation("PointLightShadowMap[0]"), Material::GetTextureUnit(TextureMap_ShadowCube_1)); + renderPipelineInfo.shader->SendInteger(renderPipelineInfo.shader->GetUniformLocation("PointLightShadowMap[1]"), Material::GetTextureUnit(TextureMap_ShadowCube_2)); + renderPipelineInfo.shader->SendInteger(renderPipelineInfo.shader->GetUniformLocation("PointLightShadowMap[2]"), Material::GetTextureUnit(TextureMap_ShadowCube_3)); + } + + bool MaterialPipeline::Initialize() + { + // Basic shader + { + UberShaderPreprocessorRef uberShader = UberShaderPreprocessor::New(); + + String fragmentShader(reinterpret_cast(r_basicFragmentShader), sizeof(r_basicFragmentShader)); + String vertexShader(reinterpret_cast(r_basicVertexShader), sizeof(r_basicVertexShader)); + + #ifdef NAZARA_DEBUG + OverrideShader("Shaders/Basic/core.frag", &fragmentShader); + OverrideShader("Shaders/Basic/core.vert", &vertexShader); + #endif + + uberShader->SetShader(ShaderStageType_Fragment, fragmentShader, "FLAG_TEXTUREOVERLAY AUTO_TEXCOORDS HAS_ALPHA_TEXTURE HAS_DIFFUSE_TEXTURE TEXTURE_MAPPING"); + uberShader->SetShader(ShaderStageType_Vertex, vertexShader, "FLAG_BILLBOARD FLAG_INSTANCING FLAG_VERTEXCOLOR TEXTURE_MAPPING TRANSFORM UNIFORM_VERTEX_DEPTH"); + + UberShaderLibrary::Register("Basic", uberShader); + } + + if (!BasicMaterial::Initialize()) + { + NazaraError("Failed to initialize phong lighting materials"); + return false; + } + + // PhongLighting shader + { + UberShaderPreprocessorRef uberShader = UberShaderPreprocessor::New(); + + String fragmentShader(reinterpret_cast(r_phongLightingFragmentShader), sizeof(r_phongLightingFragmentShader)); + String vertexShader(reinterpret_cast(r_phongLightingVertexShader), sizeof(r_phongLightingVertexShader)); + + #ifdef NAZARA_DEBUG + OverrideShader("Shaders/PhongLighting/core.frag", &fragmentShader); + OverrideShader("Shaders/PhongLighting/core.vert", &vertexShader); + #endif + + uberShader->SetShader(ShaderStageType_Fragment, fragmentShader, "FLAG_DEFERRED FLAG_TEXTUREOVERLAY ALPHA_TEST AUTO_TEXCOORDS HAS_ALPHA_TEXTURE HAS_DIFFUSE_TEXTURE HAS_EMISSIVE_TEXTURE HAS_NORMAL_TEXTURE HAS_HEIGHT_TEXTURE HAS_SPECULAR_TEXTURE REFLECTION_MAPPING SHADOW_MAPPING"); + uberShader->SetShader(ShaderStageType_Vertex, vertexShader, "FLAG_BILLBOARD FLAG_DEFERRED FLAG_INSTANCING FLAG_VERTEXCOLOR HAS_NORMAL_TEXTURE SHADOW_MAPPING TEXTURE_MAPPING TRANSFORM UNIFORM_VERTEX_DEPTH"); + + UberShaderLibrary::Register("PhongLighting", uberShader); + } + + if (!PhongLightingMaterial::Initialize()) + { + NazaraError("Failed to initialize phong lighting materials"); + return false; + } + + // Once the base shaders are registered, we can now set some default materials + MaterialPipelineInfo pipelineInfo; + pipelineInfo.settings = BasicMaterial::GetSettings(); + pipelineInfo.uberShader = UberShaderLibrary::Get("Basic"); + + // Basic 2D - No depth write/face culling with scissoring + pipelineInfo.depthWrite = false; + pipelineInfo.faceCulling = false; + pipelineInfo.scissorTest = true; + + MaterialPipelineLibrary::Register("Basic2D", GetPipeline(pipelineInfo)); + + // Translucent 2D - Alpha blending with no depth write/face culling and scissoring + pipelineInfo.blending = true; + pipelineInfo.depthWrite = false; + pipelineInfo.faceCulling = false; + pipelineInfo.depthSorting = false; + pipelineInfo.scissorTest = true; + pipelineInfo.dstBlend = BlendFunc_InvSrcAlpha; + pipelineInfo.srcBlend = BlendFunc_SrcAlpha; + + MaterialPipelineLibrary::Register("Translucent2D", GetPipeline(pipelineInfo)); + + // Translucent 3D - Alpha blending with depth buffer and no depth write/face culling + pipelineInfo.blending = true; + pipelineInfo.depthBuffer = true; + pipelineInfo.depthWrite = false; + pipelineInfo.faceCulling = false; + pipelineInfo.depthSorting = true; + pipelineInfo.scissorTest = false; + pipelineInfo.dstBlend = BlendFunc_InvSrcAlpha; + pipelineInfo.srcBlend = BlendFunc_SrcAlpha; + + MaterialPipelineLibrary::Register("Translucent3D", GetPipeline(pipelineInfo)); + + return true; + } + + void MaterialPipeline::Uninitialize() + { + s_pipelineCache.clear(); + UberShaderLibrary::Unregister("PhongLighting"); + PhongLightingMaterial::Uninitialize(); + UberShaderLibrary::Unregister("Basic"); + BasicMaterial::Uninitialize(); + MaterialPipelineLibrary::Uninitialize(); + } + + MaterialPipelineLibrary::LibraryMap MaterialPipeline::s_library; + MaterialPipeline::PipelineCache MaterialPipeline::s_pipelineCache; +} diff --git a/src/Nazara/Graphics/PhongLightingMaterial.cpp b/src/Nazara/Graphics/PhongLightingMaterial.cpp new file mode 100644 index 000000000..53b5a61c1 --- /dev/null +++ b/src/Nazara/Graphics/PhongLightingMaterial.cpp @@ -0,0 +1,331 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + namespace + { + constexpr std::size_t AlphaMapBinding = 0; + constexpr std::size_t DiffuseMapBinding = 1; + constexpr std::size_t EmissiveMapBinding = 2; + constexpr std::size_t HeightMapBinding = 3; + constexpr std::size_t NormalMapBinding = 4; + constexpr std::size_t SpecularMapBinding = 5; + constexpr std::size_t TextureOverlayBinding = 6; + } + + PhongLightingMaterial::PhongLightingMaterial(Material* material) : + m_material(material) + { + NazaraAssert(material, "Invalid material"); + + // Most common case: don't fetch texture indexes as a little optimization + const std::shared_ptr& materialSettings = material->GetSettings(); + if (materialSettings == s_materialSettings) + { + m_textureIndexes = s_textureIndexes; + m_phongUniformIndex = s_phongUniformBlockIndex; + m_phongUniformOffsets = s_phongUniformOffsets; + } + else + { + m_textureIndexes.alpha = materialSettings->GetTextureIndex("Alpha"); + m_textureIndexes.diffuse = materialSettings->GetTextureIndex("Diffuse"); + m_textureIndexes.emissive = materialSettings->GetTextureIndex("Emissive"); + m_textureIndexes.height = materialSettings->GetTextureIndex("Height"); + m_textureIndexes.normal = materialSettings->GetTextureIndex("Normal"); + m_textureIndexes.specular = materialSettings->GetTextureIndex("Specular"); + + m_phongUniformIndex = materialSettings->GetUniformBlockIndex("PhongSettings"); + + m_phongUniformOffsets.alphaThreshold = materialSettings->GetUniformBlockVariableOffset(m_phongUniformIndex, "AlphaThreshold"); + m_phongUniformOffsets.ambientColor = materialSettings->GetUniformBlockVariableOffset(m_phongUniformIndex, "AmbientColor"); + m_phongUniformOffsets.diffuseColor = materialSettings->GetUniformBlockVariableOffset(m_phongUniformIndex, "DiffuseColor"); + m_phongUniformOffsets.shininess = materialSettings->GetUniformBlockVariableOffset(m_phongUniformIndex, "Shininess"); + m_phongUniformOffsets.specularColor = materialSettings->GetUniformBlockVariableOffset(m_phongUniformIndex, "SpecularColor"); + } + } + + float PhongLightingMaterial::GetAlphaThreshold() const + { + NazaraAssert(HasAlphaThreshold(), "Material has no alpha threshold uniform"); + + BufferMapper mapper(m_material->GetUniformBuffer(m_phongUniformIndex), BufferAccess_ReadOnly); + return *AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.alphaThreshold); + } + + Color PhongLightingMaterial::GetAmbientColor() const + { + NazaraAssert(HasAmbientColor(), "Material has no ambient color uniform"); + + BufferMapper mapper(m_material->GetUniformBuffer(m_phongUniformIndex), BufferAccess_ReadOnly); + + const float* colorPtr = AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.ambientColor); + return Color(colorPtr[0] * 255, colorPtr[1] * 255, colorPtr[2] * 255, colorPtr[3] * 255); //< TODO: Make color able to use float + } + + Color PhongLightingMaterial::GetDiffuseColor() const + { + NazaraAssert(HasDiffuseColor(), "Material has no diffuse color uniform"); + + BufferMapper mapper(m_material->GetUniformBuffer(m_phongUniformIndex), BufferAccess_ReadOnly); + + const float* colorPtr = AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.diffuseColor); + return Color(colorPtr[0] * 255, colorPtr[1] * 255, colorPtr[2] * 255, colorPtr[3] * 255); //< TODO: Make color able to use float + } + + float Nz::PhongLightingMaterial::GetShininess() const + { + NazaraAssert(HasShininess(), "Material has no shininess uniform"); + + BufferMapper mapper(m_material->GetUniformBuffer(m_phongUniformIndex), BufferAccess_ReadOnly); + return *AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.shininess); + } + + Color PhongLightingMaterial::GetSpecularColor() const + { + NazaraAssert(HasSpecularColor(), "Material has no specular color uniform"); + + BufferMapper mapper(m_material->GetUniformBuffer(m_phongUniformIndex), BufferAccess_ReadOnly); + + const float* colorPtr = AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.specularColor); + return Color(colorPtr[0] * 255, colorPtr[1] * 255, colorPtr[2] * 255, colorPtr[3] * 255); //< TODO: Make color able to use float + } + + void PhongLightingMaterial::SetAlphaThreshold(float alphaThreshold) + { + NazaraAssert(HasAlphaThreshold(), "Material has no alpha threshold uniform"); + + BufferMapper mapper(m_material->GetUniformBuffer(m_phongUniformIndex), BufferAccess_WriteOnly); + *AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.alphaThreshold) = alphaThreshold; + } + + void PhongLightingMaterial::SetAmbientColor(const Color& ambient) + { + NazaraAssert(HasAmbientColor(), "Material has no ambient color uniform"); + + BufferMapper mapper(m_material->GetUniformBuffer(m_phongUniformIndex), BufferAccess_WriteOnly); + float* colorPtr = AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.ambientColor); + colorPtr[0] = ambient.r / 255.f; + colorPtr[1] = ambient.g / 255.f; + colorPtr[2] = ambient.b / 255.f; + colorPtr[3] = ambient.a / 255.f; + } + + void PhongLightingMaterial::SetDiffuseColor(const Color& diffuse) + { + NazaraAssert(HasDiffuseColor(), "Material has no diffuse color uniform"); + + BufferMapper mapper(m_material->GetUniformBuffer(m_phongUniformIndex), BufferAccess_WriteOnly); + float* colorPtr = AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.diffuseColor); + colorPtr[0] = diffuse.r / 255.f; + colorPtr[1] = diffuse.g / 255.f; + colorPtr[2] = diffuse.b / 255.f; + colorPtr[3] = diffuse.a / 255.f; + } + + void PhongLightingMaterial::SetSpecularColor(const Color& diffuse) + { + NazaraAssert(HasSpecularColor(), "Material has no specular color uniform"); + + BufferMapper mapper(m_material->GetUniformBuffer(m_phongUniformIndex), BufferAccess_WriteOnly); + float* colorPtr = AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.specularColor); + colorPtr[0] = diffuse.r / 255.f; + colorPtr[1] = diffuse.g / 255.f; + colorPtr[2] = diffuse.b / 255.f; + colorPtr[3] = diffuse.a / 255.f; + } + + const std::shared_ptr& PhongLightingMaterial::GetSettings() + { + return s_materialSettings; + } + + bool PhongLightingMaterial::Initialize() + { + RenderPipelineLayoutInfo info; + info.bindings.assign({ + { + "MaterialAlphaMap", + ShaderBindingType_Texture, + ShaderStageType_Fragment, + AlphaMapBinding + }, + { + "MaterialDiffuseMap", + ShaderBindingType_Texture, + ShaderStageType_Fragment, + DiffuseMapBinding + }, + { + "MaterialEmissiveMap", + ShaderBindingType_Texture, + ShaderStageType_Fragment, + EmissiveMapBinding + }, + { + "MaterialHeightMap", + ShaderBindingType_Texture, + ShaderStageType_Fragment, + HeightMapBinding + }, + { + "MaterialNormalMap", + ShaderBindingType_Texture, + ShaderStageType_Fragment, + NormalMapBinding + }, + { + "MaterialSpecularMap", + ShaderBindingType_Texture, + ShaderStageType_Fragment, + SpecularMapBinding + } + }); + + s_renderPipelineLayout = RenderPipelineLayout::New(); + s_renderPipelineLayout->Create(info); + + std::vector uniformBlocks; + + // MaterialPhongSettings + FieldOffsets phongUniformStruct(StructLayout_Std140); + + s_phongUniformOffsets.alphaThreshold = phongUniformStruct.AddField(StructFieldType_Float1); + s_phongUniformOffsets.shininess = phongUniformStruct.AddField(StructFieldType_Float1); + s_phongUniformOffsets.ambientColor = phongUniformStruct.AddField(StructFieldType_Float4); + s_phongUniformOffsets.diffuseColor = phongUniformStruct.AddField(StructFieldType_Float4); + s_phongUniformOffsets.specularColor = phongUniformStruct.AddField(StructFieldType_Float4); + + MaterialSettings::PredefinedBinding predefinedBinding; + predefinedBinding.fill(MaterialSettings::InvalidIndex); + + std::vector phongVariables; + phongVariables.assign({ + { + "AlphaThreshold", + s_phongUniformOffsets.alphaThreshold + }, + { + "Shininess", + s_phongUniformOffsets.shininess + }, + { + "AmbientColor", + s_phongUniformOffsets.ambientColor + }, + { + "DiffuseColor", + s_phongUniformOffsets.diffuseColor + }, + { + "SpecularColor", + s_phongUniformOffsets.specularColor + } + }); + + static_assert(sizeof(Vector4f) == 4 * sizeof(float), "Vector4f is expected to be exactly 4 floats wide"); + + std::vector defaultValues(phongUniformStruct.GetSize()); + *AccessByOffset(defaultValues.data(), s_phongUniformOffsets.ambientColor) = Vector4f(0.5f, 0.5f, 0.5f, 1.f); + *AccessByOffset(defaultValues.data(), s_phongUniformOffsets.diffuseColor) = Vector4f(1.f, 1.f, 1.f, 1.f); + *AccessByOffset(defaultValues.data(), s_phongUniformOffsets.specularColor) = Vector4f(1.f, 1.f, 1.f, 1.f); + *AccessByOffset(defaultValues.data(), s_phongUniformOffsets.alphaThreshold) = 0.2f; + *AccessByOffset(defaultValues.data(), s_phongUniformOffsets.shininess) = 50.f; + + s_phongUniformBlockIndex = uniformBlocks.size(); + uniformBlocks.push_back({ + "PhongSettings", + phongUniformStruct.GetSize(), + "MaterialPhongSettings", + std::move(phongVariables), + std::move(defaultValues) + }); + + std::vector sharedUniformBlock; + predefinedBinding[PredefinedShaderBinding_UboInstanceData] = sharedUniformBlock.size(); + sharedUniformBlock.push_back(PredefinedInstanceData::GetUniformBlock()); + predefinedBinding[PredefinedShaderBinding_UboLighData] = sharedUniformBlock.size(); + sharedUniformBlock.push_back(PredefinedLightData::GetUniformBlock()); + predefinedBinding[PredefinedShaderBinding_UboViewerData] = sharedUniformBlock.size(); + sharedUniformBlock.push_back(PredefinedViewerData::GetUniformBlock()); + + std::vector textures; + s_textureIndexes.alpha = textures.size(); + textures.push_back({ + "Alpha", + ImageType_2D, + "MaterialAlphaMap" + }); + + s_textureIndexes.diffuse = textures.size(); + textures.push_back({ + "Diffuse", + ImageType_2D, + "MaterialDiffuseMap" + }); + + s_textureIndexes.emissive = textures.size(); + textures.push_back({ + "Emissive", + ImageType_2D, + "MaterialEmissiveMap" + }); + + s_textureIndexes.height = textures.size(); + textures.push_back({ + "Height", + ImageType_2D, + "MaterialHeightMap" + }); + + s_textureIndexes.normal = textures.size(); + textures.push_back({ + "Normal", + ImageType_2D, + "MaterialNormalMap" + }); + + s_textureIndexes.specular = textures.size(); + textures.push_back({ + "Specular", + ImageType_2D, + "MaterialSpecularMap" + }); + + predefinedBinding[PredefinedShaderBinding_TexOverlay] = textures.size(); + textures.push_back({ + "Overlay", + ImageType_2D, + "TextureOverlay" + }); + + s_materialSettings = std::make_shared(std::move(textures), std::move(uniformBlocks), std::move(sharedUniformBlock), predefinedBinding); + + return true; + } + + void PhongLightingMaterial::Uninitialize() + { + s_renderPipelineLayout.Reset(); + s_materialSettings.reset(); + } + + std::shared_ptr PhongLightingMaterial::s_materialSettings; + std::size_t PhongLightingMaterial::s_phongUniformBlockIndex; + RenderPipelineLayoutRef PhongLightingMaterial::s_renderPipelineLayout; + PhongLightingMaterial::TextureIndexes PhongLightingMaterial::s_textureIndexes; + PhongLightingMaterial::PhongUniformOffsets PhongLightingMaterial::s_phongUniformOffsets; +} diff --git a/src/Nazara/Graphics/PredefinedShaderStructs.cpp b/src/Nazara/Graphics/PredefinedShaderStructs.cpp new file mode 100644 index 000000000..feb8f590b --- /dev/null +++ b/src/Nazara/Graphics/PredefinedShaderStructs.cpp @@ -0,0 +1,167 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +namespace Nz +{ + PredefinedLightData PredefinedLightData::GetOffset() + { + PredefinedLightData lightData; + + FieldOffsets lightStruct(StructLayout_Std140); + lightData.innerOffsets.type = lightStruct.AddField(StructFieldType_Int1); + lightData.innerOffsets.color = lightStruct.AddField(StructFieldType_Float4); + lightData.innerOffsets.factor = lightStruct.AddField(StructFieldType_Float2); + lightData.innerOffsets.parameter1 = lightStruct.AddField(StructFieldType_Float4); + lightData.innerOffsets.parameter2 = lightStruct.AddField(StructFieldType_Float4); + lightData.innerOffsets.parameter3 = lightStruct.AddField(StructFieldType_Float2); + lightData.innerOffsets.shadowMappingFlag = lightStruct.AddField(StructFieldType_Bool1); + + lightData.innerOffsets.totalSize = lightStruct.GetSize(); + + FieldOffsets lightDataStruct(StructLayout_Std140); + for (std::size_t& lightOffset : lightData.lightArray) + lightOffset = lightDataStruct.AddStruct(lightStruct); + + lightData.lightArraySize = lightDataStruct.GetSize(); + + return lightData; + } + + MaterialSettings::SharedUniformBlock PredefinedLightData::GetUniformBlock() + { + PredefinedLightData lightData = GetOffset(); + + std::vector lightDataVariables; + for (std::size_t i = 0; i < lightData.lightArray.size(); ++i) + { + lightDataVariables.push_back({ + "LightData[" + std::to_string(i) + "]", + lightData.lightArray[i] + }); + } + + MaterialSettings::SharedUniformBlock uniformBlock = { + "Light", + "LightData", + std::move(lightDataVariables) + }; + + return uniformBlock; + } + + PredefinedInstanceData PredefinedInstanceData::GetOffset() + { + FieldOffsets viewerStruct(StructLayout_Std140); + + PredefinedInstanceData instanceData; + instanceData.worldMatrixOffset = viewerStruct.AddMatrix(StructFieldType_Float1, 4, 4, true); + instanceData.invWorldMatrixOffset = viewerStruct.AddMatrix(StructFieldType_Float1, 4, 4, true); + + instanceData.totalSize = viewerStruct.GetSize(); + + return instanceData; + } + + MaterialSettings::SharedUniformBlock PredefinedInstanceData::GetUniformBlock() + { + PredefinedInstanceData instanceData = GetOffset(); + + std::vector instanceDataVariables; + instanceDataVariables.assign({ + { + "WorldMatrix", + instanceData.worldMatrixOffset + }, + { + "InvWorldMatrix", + instanceData.invWorldMatrixOffset + }, + }); + + MaterialSettings::SharedUniformBlock uniformBlock = { + "Instance", + "InstanceData", + std::move(instanceDataVariables) + }; + + return uniformBlock; + } + + PredefinedViewerData PredefinedViewerData::GetOffset() + { + FieldOffsets viewerStruct(StructLayout_Std140); + + PredefinedViewerData viewerData; + viewerData.projMatrixOffset = viewerStruct.AddMatrix(StructFieldType_Float1, 4, 4, true); + viewerData.invProjMatrixOffset = viewerStruct.AddMatrix(StructFieldType_Float1, 4, 4, true); + viewerData.viewMatrixOffset = viewerStruct.AddMatrix(StructFieldType_Float1, 4, 4, true); + viewerData.invViewMatrixOffset = viewerStruct.AddMatrix(StructFieldType_Float1, 4, 4, true); + viewerData.viewProjMatrixOffset = viewerStruct.AddMatrix(StructFieldType_Float1, 4, 4, true); + viewerData.invViewProjMatrixOffset = viewerStruct.AddMatrix(StructFieldType_Float1, 4, 4, true); + viewerData.targetSizeOffset = viewerStruct.AddField(StructFieldType_Float2); + viewerData.invTargetSizeOffset = viewerStruct.AddField(StructFieldType_Float2); + viewerData.eyePositionOffset = viewerStruct.AddField(StructFieldType_Float3); + + viewerData.totalSize = viewerStruct.GetSize(); + + return viewerData; + } + + MaterialSettings::SharedUniformBlock PredefinedViewerData::GetUniformBlock() + { + PredefinedViewerData viewerData = GetOffset(); + + std::vector viewerDataVariables; + viewerDataVariables.assign({ + { + "ProjMatrix", + viewerData.projMatrixOffset + }, + { + "InvProjMatrix", + viewerData.invProjMatrixOffset + }, + { + "ViewMatrix", + viewerData.viewMatrixOffset + }, + { + "InvViewMatrix", + viewerData.invViewMatrixOffset + }, + { + "ViewProjMatrix", + viewerData.viewProjMatrixOffset + }, + { + "InvViewProjMatrix", + viewerData.invViewProjMatrixOffset + }, + { + "TargetSize", + viewerData.targetSizeOffset + }, + { + "InvTargetSize", + viewerData.invTargetSizeOffset + }, + { + "EyePosition", + viewerData.eyePositionOffset + } + }); + + MaterialSettings::SharedUniformBlock uniformBlock = { + "Viewer", + "ViewerData", + std::move(viewerDataVariables) + }; + + return uniformBlock; + } +} From 0d779077c11c0fabce2291237fa503986c61e50b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 30 Oct 2020 23:04:22 +0100 Subject: [PATCH 002/278] Core/Algorithm: Add AccessByOffset functions --- include/Nazara/Core/Algorithm.hpp | 2 ++ include/Nazara/Core/Algorithm.inl | 38 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/include/Nazara/Core/Algorithm.hpp b/include/Nazara/Core/Algorithm.hpp index dec6312a4..6f0754c1b 100644 --- a/include/Nazara/Core/Algorithm.hpp +++ b/include/Nazara/Core/Algorithm.hpp @@ -21,6 +21,8 @@ namespace Nz { class ByteArray; + template decltype(auto) AccessByOffset(void* basePtr, std::size_t offset); + template decltype(auto) AccessByOffset(const void* basePtr, std::size_t offset); template constexpr T Align(T offset, T alignment); template constexpr T AlignPow2(T offset, T alignment); template decltype(auto) Apply(F&& fn, Tuple&& t); diff --git a/include/Nazara/Core/Algorithm.inl b/include/Nazara/Core/Algorithm.inl index 3560f775c..3a163cd55 100644 --- a/include/Nazara/Core/Algorithm.inl +++ b/include/Nazara/Core/Algorithm.inl @@ -36,6 +36,44 @@ namespace Nz NAZARA_CORE_API extern const UInt8 BitReverseTable256[256]; } + /*! + * \ingroup core + * \brief Access a non-typed struct field by offset + * \return A pointer to the field of the asked type + * + * \param basePtr Pointer to the start of the struct + * \param offset Offset to the field (as generated by offsetof or similar) + */ + template + decltype(auto) AccessByOffset(void* basePtr, std::size_t offset) + { + static_assert((std::is_reference_v && !std::is_rvalue_reference_v) || std::is_pointer_v); + + if constexpr (std::is_reference_v) + return *reinterpret_cast*>(static_cast(basePtr) + offset); + else + return reinterpret_cast(static_cast(basePtr) + offset); + } + + /*! + * \ingroup core + * \brief Access a non-typed struct field by offset + * \return A pointer to the field of the asked type + * + * \param basePtr Pointer to the start of the struct + * \param offset Offset to the field (as generated by offsetof or similar) + */ + template + decltype(auto) AccessByOffset(const void* basePtr, std::size_t offset) + { + static_assert((std::is_reference_v && !std::is_rvalue_reference_v) || std::is_pointer_v); + + if constexpr (std::is_reference_v) + return *reinterpret_cast*>(static_cast(basePtr) + offset); + else + return reinterpret_cast(static_cast(basePtr) + offset); + } + /*! * \ingroup core * \brief Align an offset From 009e5a0466a611b76a73193ce2096e7e61e96119 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 30 Oct 2020 23:06:15 +0100 Subject: [PATCH 003/278] Renderer: Rename ShaderStageImpl to ShaderStage --- include/Nazara/OpenGLRenderer/OpenGLDevice.hpp | 2 +- include/Nazara/OpenGLRenderer/OpenGLShaderStage.hpp | 4 ++-- include/Nazara/Renderer.hpp | 2 +- include/Nazara/Renderer/RenderDevice.hpp | 6 +++--- include/Nazara/Renderer/RenderStates.hpp | 2 +- .../{ShaderStageImpl.hpp => ShaderStage.hpp} | 12 ++++++------ include/Nazara/VulkanRenderer/VulkanDevice.hpp | 2 +- include/Nazara/VulkanRenderer/VulkanShaderStage.hpp | 4 ++-- src/Nazara/OpenGLRenderer/OpenGLDevice.cpp | 2 +- src/Nazara/Renderer/RenderDevice.cpp | 2 +- .../{ShaderStageImpl.cpp => ShaderStage.cpp} | 4 ++-- src/Nazara/VulkanRenderer/VulkanDevice.cpp | 2 +- 12 files changed, 22 insertions(+), 22 deletions(-) rename include/Nazara/Renderer/{ShaderStageImpl.hpp => ShaderStage.hpp} (58%) rename src/Nazara/Renderer/{ShaderStageImpl.cpp => ShaderStage.cpp} (71%) diff --git a/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp b/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp index a75140840..8398c8e61 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp @@ -36,7 +36,7 @@ namespace Nz std::shared_ptr InstantiateCommandPool(QueueType queueType) override; std::shared_ptr InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override; std::shared_ptr InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) override; - std::shared_ptr InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) override; + std::shared_ptr InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) override; std::shared_ptr InstantiateTexture(const TextureInfo& params) override; std::shared_ptr InstantiateTextureSampler(const TextureSamplerInfo& params) override; diff --git a/include/Nazara/OpenGLRenderer/OpenGLShaderStage.hpp b/include/Nazara/OpenGLRenderer/OpenGLShaderStage.hpp index 8768befb7..0463f5b49 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLShaderStage.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLShaderStage.hpp @@ -9,14 +9,14 @@ #include #include -#include +#include #include #include #include namespace Nz { - class NAZARA_OPENGLRENDERER_API OpenGLShaderStage : public ShaderStageImpl + class NAZARA_OPENGLRENDERER_API OpenGLShaderStage : public ShaderStage { public: OpenGLShaderStage(OpenGLDevice& device, ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize); diff --git a/include/Nazara/Renderer.hpp b/include/Nazara/Renderer.hpp index 3b792a6b1..3d3a8e027 100644 --- a/include/Nazara/Renderer.hpp +++ b/include/Nazara/Renderer.hpp @@ -53,7 +53,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/Nazara/Renderer/RenderDevice.hpp b/include/Nazara/Renderer/RenderDevice.hpp index 000aca2e2..fb26dc58f 100644 --- a/include/Nazara/Renderer/RenderDevice.hpp +++ b/include/Nazara/Renderer/RenderDevice.hpp @@ -21,7 +21,7 @@ namespace Nz { class CommandPool; - class ShaderStageImpl; + class ShaderStage; class NAZARA_RENDERER_API RenderDevice { @@ -33,8 +33,8 @@ namespace Nz virtual std::shared_ptr InstantiateCommandPool(QueueType queueType) = 0; virtual std::shared_ptr InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) = 0; virtual std::shared_ptr InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) = 0; - virtual std::shared_ptr InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) = 0; - std::shared_ptr InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const std::filesystem::path& sourcePath); + virtual std::shared_ptr InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) = 0; + std::shared_ptr InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const std::filesystem::path& sourcePath); virtual std::shared_ptr InstantiateTexture(const TextureInfo& params) = 0; virtual std::shared_ptr InstantiateTextureSampler(const TextureSamplerInfo& params) = 0; }; diff --git a/include/Nazara/Renderer/RenderStates.hpp b/include/Nazara/Renderer/RenderStates.hpp index dca3d4c7c..d04a2fe1e 100644 --- a/include/Nazara/Renderer/RenderStates.hpp +++ b/include/Nazara/Renderer/RenderStates.hpp @@ -15,7 +15,7 @@ namespace Nz { - class ShaderStageImpl; + class ShaderStage; struct RenderStates { diff --git a/include/Nazara/Renderer/ShaderStageImpl.hpp b/include/Nazara/Renderer/ShaderStage.hpp similarity index 58% rename from include/Nazara/Renderer/ShaderStageImpl.hpp rename to include/Nazara/Renderer/ShaderStage.hpp index 4bee731e2..c24c287ad 100644 --- a/include/Nazara/Renderer/ShaderStageImpl.hpp +++ b/include/Nazara/Renderer/ShaderStage.hpp @@ -4,8 +4,8 @@ #pragma once -#ifndef NAZARA_RENDERER_SHADERSTAGEIMPL_HPP -#define NAZARA_RENDERER_SHADERSTAGEIMPL_HPP +#ifndef NAZARA_RENDERER_SHADERSTAGE_HPP +#define NAZARA_RENDERER_SHADERSTAGE_HPP #include #include @@ -13,12 +13,12 @@ namespace Nz { - class NAZARA_RENDERER_API ShaderStageImpl + class NAZARA_RENDERER_API ShaderStage { public: - ShaderStageImpl() = default; - virtual ~ShaderStageImpl(); + ShaderStage() = default; + virtual ~ShaderStage(); }; } -#endif // NAZARA_RENDERER_SHADERSTAGEIMPL_HPP +#endif // NAZARA_RENDERER_SHADERSTAGE_HPP diff --git a/include/Nazara/VulkanRenderer/VulkanDevice.hpp b/include/Nazara/VulkanRenderer/VulkanDevice.hpp index b7d8e095c..873c7dc9c 100644 --- a/include/Nazara/VulkanRenderer/VulkanDevice.hpp +++ b/include/Nazara/VulkanRenderer/VulkanDevice.hpp @@ -27,7 +27,7 @@ namespace Nz std::shared_ptr InstantiateCommandPool(QueueType queueType) override; std::shared_ptr InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override; std::shared_ptr InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) override; - std::shared_ptr InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) override; + std::shared_ptr InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) override; std::shared_ptr InstantiateTexture(const TextureInfo& params) override; std::shared_ptr InstantiateTextureSampler(const TextureSamplerInfo& params) override; diff --git a/include/Nazara/VulkanRenderer/VulkanShaderStage.hpp b/include/Nazara/VulkanRenderer/VulkanShaderStage.hpp index 50644f102..059183853 100644 --- a/include/Nazara/VulkanRenderer/VulkanShaderStage.hpp +++ b/include/Nazara/VulkanRenderer/VulkanShaderStage.hpp @@ -9,13 +9,13 @@ #include #include -#include +#include #include #include namespace Nz { - class NAZARA_VULKANRENDERER_API VulkanShaderStage : public ShaderStageImpl + class NAZARA_VULKANRENDERER_API VulkanShaderStage : public ShaderStage { public: VulkanShaderStage() = default; diff --git a/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp b/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp index e7c0c070f..3085a7955 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp @@ -68,7 +68,7 @@ namespace Nz return std::make_shared(std::move(pipelineLayoutInfo)); } - std::shared_ptr OpenGLDevice::InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) + std::shared_ptr OpenGLDevice::InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) { return std::make_shared(*this, type, lang, source, sourceSize); } diff --git a/src/Nazara/Renderer/RenderDevice.cpp b/src/Nazara/Renderer/RenderDevice.cpp index a4d377db6..0a56e5f46 100644 --- a/src/Nazara/Renderer/RenderDevice.cpp +++ b/src/Nazara/Renderer/RenderDevice.cpp @@ -11,7 +11,7 @@ namespace Nz { RenderDevice::~RenderDevice() = default; - std::shared_ptr RenderDevice::InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const std::filesystem::path& sourcePath) + std::shared_ptr RenderDevice::InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const std::filesystem::path& sourcePath) { File file(sourcePath); if (!file.Open(OpenMode_ReadOnly | OpenMode_Text)) diff --git a/src/Nazara/Renderer/ShaderStageImpl.cpp b/src/Nazara/Renderer/ShaderStage.cpp similarity index 71% rename from src/Nazara/Renderer/ShaderStageImpl.cpp rename to src/Nazara/Renderer/ShaderStage.cpp index dd3e48a63..1b2b87813 100644 --- a/src/Nazara/Renderer/ShaderStageImpl.cpp +++ b/src/Nazara/Renderer/ShaderStage.cpp @@ -2,10 +2,10 @@ // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include namespace Nz { - ShaderStageImpl::~ShaderStageImpl() = default; + ShaderStage::~ShaderStage() = default; } diff --git a/src/Nazara/VulkanRenderer/VulkanDevice.cpp b/src/Nazara/VulkanRenderer/VulkanDevice.cpp index adc23c0b8..2d67003e7 100644 --- a/src/Nazara/VulkanRenderer/VulkanDevice.cpp +++ b/src/Nazara/VulkanRenderer/VulkanDevice.cpp @@ -39,7 +39,7 @@ namespace Nz return pipelineLayout; } - std::shared_ptr VulkanDevice::InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) + std::shared_ptr VulkanDevice::InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) { auto stage = std::make_shared(); if (!stage->Create(*this, type, lang, source, sourceSize)) From b62130dab99a4d31c967862f66654823e041aa1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 30 Oct 2020 23:06:56 +0100 Subject: [PATCH 004/278] VulkanRenderer: Fix physical device bullshit Keep a single list instead of many --- include/Nazara/VulkanRenderer/VulkanRenderer.hpp | 1 - src/Nazara/VulkanRenderer/VulkanRenderer.cpp | 14 +++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/include/Nazara/VulkanRenderer/VulkanRenderer.hpp b/include/Nazara/VulkanRenderer/VulkanRenderer.hpp index d52086dce..881118bfe 100644 --- a/include/Nazara/VulkanRenderer/VulkanRenderer.hpp +++ b/include/Nazara/VulkanRenderer/VulkanRenderer.hpp @@ -41,7 +41,6 @@ namespace Nz private: std::list m_devices; - std::vector m_physDevices; ParameterList m_initializationParameters; Vk::Instance m_instance; }; diff --git a/src/Nazara/VulkanRenderer/VulkanRenderer.cpp b/src/Nazara/VulkanRenderer/VulkanRenderer.cpp index 6f1213a34..cb349a454 100644 --- a/src/Nazara/VulkanRenderer/VulkanRenderer.cpp +++ b/src/Nazara/VulkanRenderer/VulkanRenderer.cpp @@ -32,8 +32,10 @@ namespace Nz std::shared_ptr VulkanRenderer::InstanciateRenderDevice(std::size_t deviceIndex) { - assert(deviceIndex < m_physDevices.size()); - return Vulkan::SelectDevice(m_physDevices[deviceIndex]); + const auto& physDevices = Vulkan::GetPhysicalDevices(); + + assert(deviceIndex < physDevices.size()); + return Vulkan::SelectDevice(physDevices[deviceIndex]); } bool VulkanRenderer::Prepare(const ParameterList& parameters) @@ -61,10 +63,12 @@ namespace Nz std::vector VulkanRenderer::QueryRenderDevices() const { - std::vector devices; - devices.reserve(m_physDevices.size()); + const auto& physDevices = Vulkan::GetPhysicalDevices(); - for (const Vk::PhysicalDevice& physDevice : m_physDevices) + std::vector devices; + devices.reserve(physDevices.size()); + + for (const Vk::PhysicalDevice& physDevice : physDevices) { RenderDeviceInfo& device = devices.emplace_back(); device.name = physDevice.properties.deviceName; From 40f3072ff9d5de4f045d1529b67c3ebce4095106 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 30 Oct 2020 23:07:21 +0100 Subject: [PATCH 005/278] Renderer: Add RenderPipeline::GetPipelineInfo --- include/Nazara/OpenGLRenderer/OpenGLRenderPipeline.hpp | 2 +- include/Nazara/Renderer/RenderPipeline.hpp | 4 +++- include/Nazara/VulkanRenderer/VulkanRenderPipeline.hpp | 2 ++ include/Nazara/VulkanRenderer/VulkanRenderPipeline.inl | 4 ++++ 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/Nazara/OpenGLRenderer/OpenGLRenderPipeline.hpp b/include/Nazara/OpenGLRenderer/OpenGLRenderPipeline.hpp index ddc6526af..3c40eca7a 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLRenderPipeline.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLRenderPipeline.hpp @@ -24,7 +24,7 @@ namespace Nz void Apply(const GL::Context& context) const; - inline const RenderPipelineInfo& GetPipelineInfo() const; + inline const RenderPipelineInfo& GetPipelineInfo() const override; private: RenderPipelineInfo m_pipelineInfo; diff --git a/include/Nazara/Renderer/RenderPipeline.hpp b/include/Nazara/Renderer/RenderPipeline.hpp index 82f08e7c4..59981f831 100644 --- a/include/Nazara/Renderer/RenderPipeline.hpp +++ b/include/Nazara/Renderer/RenderPipeline.hpp @@ -22,7 +22,7 @@ namespace Nz }; std::shared_ptr pipelineLayout; - std::vector> shaderStages; + std::vector> shaderStages; std::vector vertexBuffers; }; @@ -31,6 +31,8 @@ namespace Nz public: RenderPipeline() = default; virtual ~RenderPipeline(); + + virtual const RenderPipelineInfo& GetPipelineInfo() const = 0; }; } diff --git a/include/Nazara/VulkanRenderer/VulkanRenderPipeline.hpp b/include/Nazara/VulkanRenderer/VulkanRenderPipeline.hpp index 8165d56f0..df48fe046 100644 --- a/include/Nazara/VulkanRenderer/VulkanRenderPipeline.hpp +++ b/include/Nazara/VulkanRenderer/VulkanRenderPipeline.hpp @@ -28,6 +28,8 @@ namespace Nz VkPipeline Get(const Vk::RenderPass& renderPass) const; + inline const RenderPipelineInfo& GetPipelineInfo() const override; + static std::vector BuildColorBlendAttachmentStateList(const RenderPipelineInfo& pipelineInfo); static VkPipelineColorBlendStateCreateInfo BuildColorBlendInfo(const RenderPipelineInfo& pipelineInfo, const std::vector& attachmentState); static VkPipelineDepthStencilStateCreateInfo BuildDepthStencilInfo(const RenderPipelineInfo& pipelineInfo); diff --git a/include/Nazara/VulkanRenderer/VulkanRenderPipeline.inl b/include/Nazara/VulkanRenderer/VulkanRenderPipeline.inl index 00c03d4d2..954464855 100644 --- a/include/Nazara/VulkanRenderer/VulkanRenderPipeline.inl +++ b/include/Nazara/VulkanRenderer/VulkanRenderPipeline.inl @@ -7,6 +7,10 @@ namespace Nz { + inline const RenderPipelineInfo& VulkanRenderPipeline::GetPipelineInfo() const + { + return m_pipelineInfo; + } } #include From 5ca9776755cdc6ca73bc2540215ab5a902be0803 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 30 Oct 2020 23:07:42 +0100 Subject: [PATCH 006/278] ShaderNode: Fix missing "add texture" button --- src/ShaderNode/Widgets/TextureEditor.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ShaderNode/Widgets/TextureEditor.cpp b/src/ShaderNode/Widgets/TextureEditor.cpp index 99b40316a..c9bcf7d1c 100644 --- a/src/ShaderNode/Widgets/TextureEditor.cpp +++ b/src/ShaderNode/Widgets/TextureEditor.cpp @@ -19,11 +19,15 @@ m_shaderGraph(graph) m_pixmapLabel = new QLabel; - QPushButton* updateTextureButton = new QPushButton(tr("Load texture...")); + QPushButton* addTextureButton = new QPushButton(tr("Add texture...")); + connect(addTextureButton, &QPushButton::released, this, &TextureEditor::OnAddTexture); + + QPushButton* updateTextureButton = new QPushButton(tr("Load texture preview...")); connect(updateTextureButton, &QPushButton::released, this, &TextureEditor::OnLoadTexture); m_layout = new QVBoxLayout; m_layout->addWidget(m_textureList); + m_layout->addWidget(addTextureButton); m_layout->addWidget(updateTextureButton); m_layout->addWidget(m_pixmapLabel); From e5cd461bae40065cdb4f9a0d8796aaaee99ad71f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 30 Oct 2020 23:08:03 +0100 Subject: [PATCH 007/278] ShaderNode: Fix possible crash with incompatible types --- src/ShaderNode/DataModels/Cast.inl | 2 +- src/ShaderNode/DataModels/Mat4BinOp.inl | 3 +-- src/ShaderNode/DataModels/Mat4VecMul.cpp | 4 ++-- src/ShaderNode/DataModels/OutputValue.cpp | 15 +++++++++++++++ src/ShaderNode/DataModels/PositionOutputValue.cpp | 2 +- src/ShaderNode/DataModels/SampleTexture.cpp | 6 ++---- src/ShaderNode/DataModels/VecBinOp.inl | 6 +----- src/ShaderNode/DataModels/VecDot.cpp | 3 +-- src/ShaderNode/DataModels/VecFloatMul.cpp | 6 ++---- 9 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/ShaderNode/DataModels/Cast.inl b/src/ShaderNode/DataModels/Cast.inl index cd96d6ccc..0bad72055 100644 --- a/src/ShaderNode/DataModels/Cast.inl +++ b/src/ShaderNode/DataModels/Cast.inl @@ -141,7 +141,7 @@ template void CastVec::setInData(std::shared_ptr value, int index) { assert(index == 0); - if (value) + if (value && value->type().id == VecData::Type().id) { assert(dynamic_cast(value.get()) != nullptr); m_input = std::static_pointer_cast(value); diff --git a/src/ShaderNode/DataModels/Mat4BinOp.inl b/src/ShaderNode/DataModels/Mat4BinOp.inl index 05cdb0479..eb57e74c2 100644 --- a/src/ShaderNode/DataModels/Mat4BinOp.inl +++ b/src/ShaderNode/DataModels/Mat4BinOp.inl @@ -50,10 +50,9 @@ void Mat4BinOp::setInData(std::shared_ptr value, int i assert(index == 0 || index == 1); std::shared_ptr castedValue; - if (value) + if (value && value->type().id == Matrix4Data::Type().id) { assert(dynamic_cast(value.get()) != nullptr); - castedValue = std::static_pointer_cast(value); } diff --git a/src/ShaderNode/DataModels/Mat4VecMul.cpp b/src/ShaderNode/DataModels/Mat4VecMul.cpp index 983545973..af43e4f1d 100644 --- a/src/ShaderNode/DataModels/Mat4VecMul.cpp +++ b/src/ShaderNode/DataModels/Mat4VecMul.cpp @@ -77,7 +77,7 @@ void Mat4VecMul::setInData(std::shared_ptr value, int index) { case 0: { - if (value) + if (value && value->type().id == Matrix4Data::Type().id) { assert(dynamic_cast(value.get()) != nullptr); m_lhs = std::static_pointer_cast(value); @@ -90,7 +90,7 @@ void Mat4VecMul::setInData(std::shared_ptr value, int index) case 1: { - if (value) + if (value && value->type().id == VecData::Type().id) { assert(dynamic_cast(value.get()) != nullptr); m_rhs = std::static_pointer_cast(value); diff --git a/src/ShaderNode/DataModels/OutputValue.cpp b/src/ShaderNode/DataModels/OutputValue.cpp index 63a481588..9a2cb7030 100644 --- a/src/ShaderNode/DataModels/OutputValue.cpp +++ b/src/ShaderNode/DataModels/OutputValue.cpp @@ -126,6 +126,9 @@ QtNodes::NodeValidationState OutputValue::validationState() const case PrimitiveType::Float3: case PrimitiveType::Float4: { + if (m_input->type().id != VecData::Type().id) + return QtNodes::NodeValidationState::Error; + assert(dynamic_cast(m_input.get()) != nullptr); const VecData& vec = static_cast(*m_input); if (GetComponentCount(outputEntry.type) != vec.componentCount) @@ -156,6 +159,9 @@ QString OutputValue::validationMessage() const case PrimitiveType::Float3: case PrimitiveType::Float4: { + if (m_input->type().id != VecData::Type().id) + return "Expected vector"; + assert(dynamic_cast(m_input.get()) != nullptr); const VecData& vec = static_cast(*m_input); @@ -179,6 +185,9 @@ bool OutputValue::ComputePreview(QPixmap& pixmap) { case PrimitiveType::Bool: { + if (m_input->type().id != BoolData::Type().id) + return false; + assert(dynamic_cast(m_input.get()) != nullptr); const BoolData& data = static_cast(*m_input); @@ -188,6 +197,9 @@ bool OutputValue::ComputePreview(QPixmap& pixmap) case PrimitiveType::Float1: { + if (m_input->type().id != FloatData::Type().id) + return false; + assert(dynamic_cast(m_input.get()) != nullptr); const FloatData& data = static_cast(*m_input); @@ -208,6 +220,9 @@ bool OutputValue::ComputePreview(QPixmap& pixmap) case PrimitiveType::Float3: case PrimitiveType::Float4: { + if (m_input->type().id != VecData::Type().id) + return false; + assert(dynamic_cast(m_input.get()) != nullptr); const VecData& data = static_cast(*m_input); diff --git a/src/ShaderNode/DataModels/PositionOutputValue.cpp b/src/ShaderNode/DataModels/PositionOutputValue.cpp index c3d252f54..6f2ab9d3a 100644 --- a/src/ShaderNode/DataModels/PositionOutputValue.cpp +++ b/src/ShaderNode/DataModels/PositionOutputValue.cpp @@ -52,7 +52,7 @@ std::shared_ptr PositionOutputValue::outData(QtNodes::PortInd void PositionOutputValue::setInData(std::shared_ptr value, int index) { assert(index == 0); - if (value) + if (value && value->type().id == VecData::Type().id) { assert(dynamic_cast(value.get()) != nullptr); m_input = std::static_pointer_cast(value); diff --git a/src/ShaderNode/DataModels/SampleTexture.cpp b/src/ShaderNode/DataModels/SampleTexture.cpp index c784b83af..f0eccc770 100644 --- a/src/ShaderNode/DataModels/SampleTexture.cpp +++ b/src/ShaderNode/DataModels/SampleTexture.cpp @@ -154,10 +154,9 @@ void SampleTexture::setInData(std::shared_ptr value, int inde { case 0: { - if (value) + if (value && value->type().id == Texture2Data::Type().id) { assert(dynamic_cast(value.get()) != nullptr); - m_texture = std::static_pointer_cast(value); } else @@ -168,10 +167,9 @@ void SampleTexture::setInData(std::shared_ptr value, int inde case 1: { - if (value) + if (value && value->type().id == VecData::Type().id) { assert(dynamic_cast(value.get()) != nullptr); - m_uv = std::static_pointer_cast(value); } else diff --git a/src/ShaderNode/DataModels/VecBinOp.inl b/src/ShaderNode/DataModels/VecBinOp.inl index d16347799..a8b9d6d2d 100644 --- a/src/ShaderNode/DataModels/VecBinOp.inl +++ b/src/ShaderNode/DataModels/VecBinOp.inl @@ -50,12 +50,8 @@ void VecBinOp::setInData(std::shared_ptr value, int in assert(index == 0 || index == 1); std::shared_ptr castedValue; - if (value) - { - assert(dynamic_cast(value.get()) != nullptr); - + if (value && value->type().id == VecData::Type().id) castedValue = std::static_pointer_cast(value); - } if (index == 0) m_lhs = std::move(castedValue); diff --git a/src/ShaderNode/DataModels/VecDot.cpp b/src/ShaderNode/DataModels/VecDot.cpp index b083623d0..516e1b19b 100644 --- a/src/ShaderNode/DataModels/VecDot.cpp +++ b/src/ShaderNode/DataModels/VecDot.cpp @@ -71,10 +71,9 @@ void VecDot::setInData(std::shared_ptr value, int index) assert(index == 0 || index == 1); std::shared_ptr castedValue; - if (value) + if (value && value->type().id == VecData::Type().id) { assert(dynamic_cast(value.get()) != nullptr); - castedValue = std::static_pointer_cast(value); } diff --git a/src/ShaderNode/DataModels/VecFloatMul.cpp b/src/ShaderNode/DataModels/VecFloatMul.cpp index 9dd3b02c3..06ee951c6 100644 --- a/src/ShaderNode/DataModels/VecFloatMul.cpp +++ b/src/ShaderNode/DataModels/VecFloatMul.cpp @@ -77,10 +77,9 @@ void VecFloatMul::setInData(std::shared_ptr value, int index) { case 0: { - if (value) + if (value && value->type().id == FloatData::Type().id) { assert(dynamic_cast(value.get()) != nullptr); - m_lhs = std::static_pointer_cast(value); } else @@ -91,10 +90,9 @@ void VecFloatMul::setInData(std::shared_ptr value, int index) case 1: { - if (value) + if (value && value->type().id == VecData::Type().id) { assert(dynamic_cast(value.get()) != nullptr); - m_rhs = std::static_pointer_cast(value); } else From 73e86407b3ec24d85175662299f4f878575ca443 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 30 Oct 2020 23:08:27 +0100 Subject: [PATCH 008/278] Fix some warnings --- include/Nazara/Core/Modules.inl | 3 +++ src/Nazara/OpenGLRenderer/OpenGLBuffer.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/Nazara/Core/Modules.inl b/include/Nazara/Core/Modules.inl index 933720166..79dafd7a5 100644 --- a/include/Nazara/Core/Modules.inl +++ b/include/Nazara/Core/Modules.inl @@ -18,7 +18,10 @@ namespace Nz if constexpr (std::is_same_v>) return std::forward(first); else + { + NazaraUnused(first); return Get(std::forward(args)...); + } } static auto Get() diff --git a/src/Nazara/OpenGLRenderer/OpenGLBuffer.cpp b/src/Nazara/OpenGLRenderer/OpenGLBuffer.cpp index 236380511..b94e2dc8a 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLBuffer.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLBuffer.cpp @@ -19,7 +19,7 @@ namespace Nz bool OpenGLBuffer::Fill(const void* data, UInt64 offset, UInt64 size) { - m_buffer.SubData(offset, size, data); + m_buffer.SubData(GLintptr(offset), GLsizeiptr(size), data); return true; } From 89609570f4a80b91e9ca208a6637cc48730d972a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 30 Oct 2020 23:08:48 +0100 Subject: [PATCH 009/278] Graphics: WIP (almost working) --- include/Nazara/Graphics.hpp | 8 + include/Nazara/Graphics/BasicMaterial.hpp | 15 +- include/Nazara/Graphics/BasicMaterial.inl | 50 +- include/Nazara/Graphics/Graphics.hpp | 2 +- include/Nazara/Graphics/Material.hpp | 48 +- include/Nazara/Graphics/Material.inl | 274 +---- include/Nazara/Graphics/MaterialPipeline.hpp | 37 +- include/Nazara/Graphics/MaterialPipeline.inl | 61 +- include/Nazara/Graphics/MaterialSettings.hpp | 7 +- include/Nazara/Graphics/MaterialSettings.inl | 23 +- .../Nazara/Graphics/PhongLightingMaterial.hpp | 35 +- .../Nazara/Graphics/PhongLightingMaterial.inl | 70 +- .../Graphics/PredefinedShaderStructs.hpp | 4 +- .../Nazara/Renderer/RenderPipelineLayout.hpp | 1 - include/Nazara/Utility/Enums.hpp | 2 + .../basicmaterial.frag.shaderflow | 361 +++++++ .../basicmaterial.vert.shaderflow | 392 +++++++ src/Nazara/Graphics/BasicMaterial.cpp | 118 +-- src/Nazara/Graphics/BasicRenderQueue.cpp | 956 ------------------ src/Nazara/Graphics/Graphics.cpp | 11 +- src/Nazara/Graphics/Material.cpp | 446 +------- src/Nazara/Graphics/MaterialPipeline.cpp | 225 +---- src/Nazara/Graphics/PhongLightingMaterial.cpp | 142 +-- .../Graphics/PredefinedShaderStructs.cpp | 8 +- .../Shaders/basicmaterial.frag.shader | Bin 0 -> 1126 bytes .../Shaders/basicmaterial.frag.shader.h | 1 + .../Shaders/basicmaterial.vert.shader | Bin 0 -> 1046 bytes .../Shaders/basicmaterial.vert.shader.h | 1 + 28 files changed, 1036 insertions(+), 2262 deletions(-) create mode 100644 shaders/BasicMaterial/basicmaterial.frag.shaderflow create mode 100644 shaders/BasicMaterial/basicmaterial.vert.shaderflow delete mode 100644 src/Nazara/Graphics/BasicRenderQueue.cpp create mode 100644 src/Nazara/Graphics/Resources/Shaders/basicmaterial.frag.shader create mode 100644 src/Nazara/Graphics/Resources/Shaders/basicmaterial.frag.shader.h create mode 100644 src/Nazara/Graphics/Resources/Shaders/basicmaterial.vert.shader create mode 100644 src/Nazara/Graphics/Resources/Shaders/basicmaterial.vert.shader.h diff --git a/include/Nazara/Graphics.hpp b/include/Nazara/Graphics.hpp index dfdcd7991..44540452e 100644 --- a/include/Nazara/Graphics.hpp +++ b/include/Nazara/Graphics.hpp @@ -29,8 +29,16 @@ #ifndef NAZARA_GLOBAL_GRAPHICS_HPP #define NAZARA_GLOBAL_GRAPHICS_HPP +#include #include +#include #include #include +#include +#include +#include +#include +#include +#include #endif // NAZARA_GLOBAL_GRAPHICS_HPP diff --git a/include/Nazara/Graphics/BasicMaterial.hpp b/include/Nazara/Graphics/BasicMaterial.hpp index a623d973a..ef7488a5e 100644 --- a/include/Nazara/Graphics/BasicMaterial.hpp +++ b/include/Nazara/Graphics/BasicMaterial.hpp @@ -17,24 +17,22 @@ namespace Nz friend class MaterialPipeline; public: - BasicMaterial(Material* material); + BasicMaterial(Material& material); - inline const TextureRef& GetAlphaMap() const; + inline const std::shared_ptr& GetAlphaMap() const; float GetAlphaThreshold() const; Color GetDiffuseColor() const; - inline const TextureRef& GetDiffuseMap() const; + inline const std::shared_ptr& GetDiffuseMap() const; inline bool HasAlphaMap() const; inline bool HasAlphaThreshold() const; inline bool HasDiffuseColor() const; inline bool HasDiffuseMap() const; - inline bool SetAlphaMap(const String& textureName); - inline void SetAlphaMap(TextureRef alphaMap); + inline void SetAlphaMap(std::shared_ptr alphaMap); void SetAlphaThreshold(float alphaThreshold); void SetDiffuseColor(const Color& diffuse); - inline bool SetDiffuseMap(const String& textureName); - inline void SetDiffuseMap(TextureRef diffuseMap); + inline void SetDiffuseMap(std::shared_ptr diffuseMap); static const std::shared_ptr& GetSettings(); @@ -54,14 +52,13 @@ namespace Nz static bool Initialize(); static void Uninitialize(); - MaterialRef m_material; + Material& m_material; std::size_t m_uniformBlockIndex; TextureIndexes m_textureIndexes; UniformOffsets m_uniformOffsets; static std::shared_ptr s_materialSettings; static std::size_t s_uniformBlockIndex; - static RenderPipelineLayoutRef s_renderPipelineLayout; static TextureIndexes s_textureIndexes; static UniformOffsets s_uniformOffsets; }; diff --git a/include/Nazara/Graphics/BasicMaterial.inl b/include/Nazara/Graphics/BasicMaterial.inl index 79e92e8a2..7a13539c8 100644 --- a/include/Nazara/Graphics/BasicMaterial.inl +++ b/include/Nazara/Graphics/BasicMaterial.inl @@ -9,16 +9,16 @@ namespace Nz { - inline const TextureRef& BasicMaterial::GetAlphaMap() const + inline const std::shared_ptr& BasicMaterial::GetAlphaMap() const { NazaraAssert(HasAlphaMap(), "Material has no alpha map slot"); - return m_material->GetTexture(m_textureIndexes.alpha); + return m_material.GetTexture(m_textureIndexes.alpha); } - inline const TextureRef& BasicMaterial::GetDiffuseMap() const + inline const std::shared_ptr& BasicMaterial::GetDiffuseMap() const { NazaraAssert(HasDiffuseMap(), "Material has no alpha map slot"); - return m_material->GetTexture(m_textureIndexes.diffuse); + return m_material.GetTexture(m_textureIndexes.diffuse); } inline bool BasicMaterial::HasAlphaMap() const @@ -41,50 +41,16 @@ namespace Nz return m_textureIndexes.diffuse != MaterialSettings::InvalidIndex; } - inline bool BasicMaterial::SetAlphaMap(const String& textureName) - { - TextureRef texture = TextureLibrary::Query(textureName); - if (!texture) - { - texture = TextureManager::Get(textureName); - if (!texture) - { - NazaraError("Failed to get alpha map \"" + textureName + "\""); - return false; - } - } - - SetAlphaMap(std::move(texture)); - return true; - } - - inline void BasicMaterial::SetAlphaMap(TextureRef alphaMap) + inline void BasicMaterial::SetAlphaMap(std::shared_ptr alphaMap) { NazaraAssert(HasAlphaMap(), "Material has no alpha map slot"); - m_material->SetTexture(m_textureIndexes.alpha, std::move(alphaMap)); + m_material.SetTexture(m_textureIndexes.alpha, std::move(alphaMap)); } - inline bool BasicMaterial::SetDiffuseMap(const String& textureName) - { - TextureRef texture = TextureLibrary::Query(textureName); - if (!texture) - { - texture = TextureManager::Get(textureName); - if (!texture) - { - NazaraError("Failed to get diffuse map \"" + textureName + "\""); - return false; - } - } - - SetDiffuseMap(std::move(texture)); - return true; - } - - inline void BasicMaterial::SetDiffuseMap(TextureRef diffuseMap) + inline void BasicMaterial::SetDiffuseMap(std::shared_ptr diffuseMap) { NazaraAssert(HasDiffuseMap(), "Material has no diffuse map slot"); - m_material->SetTexture(m_textureIndexes.diffuse, std::move(diffuseMap)); + m_material.SetTexture(m_textureIndexes.diffuse, std::move(diffuseMap)); } } diff --git a/include/Nazara/Graphics/Graphics.hpp b/include/Nazara/Graphics/Graphics.hpp index 7cf692bc4..d1f988f04 100644 --- a/include/Nazara/Graphics/Graphics.hpp +++ b/include/Nazara/Graphics/Graphics.hpp @@ -26,7 +26,7 @@ namespace Nz struct Config; Graphics(Config config); - ~Graphics() = default; + ~Graphics(); inline RenderDevice& GetRenderDevice(); diff --git a/include/Nazara/Graphics/Material.hpp b/include/Nazara/Graphics/Material.hpp index 31e732125..1459e21d0 100644 --- a/include/Nazara/Graphics/Material.hpp +++ b/include/Nazara/Graphics/Material.hpp @@ -23,38 +23,20 @@ #include #include #include +#include #include #include namespace Nz { - struct NAZARA_GRAPHICS_API MaterialParams : ResourceParameters - { - bool loadAlphaMap = true; - bool loadDiffuseMap = true; - bool loadEmissiveMap = true; - bool loadHeightMap = true; - bool loadNormalMap = true; - bool loadSpecularMap = true; - std::string shaderName = "Basic"; - - bool IsValid() const; - }; - class NAZARA_GRAPHICS_API Material : public RefCounted, public Resource { public: Material(std::shared_ptr settings); - inline Material(const Material& material); inline ~Material(); - void Apply(const MaterialPipeline::Instance& instance) const; - - void BuildFromParameters(const ParameterList& matData, const MaterialParams& matParams = MaterialParams()); - - inline void Configure(const MaterialPipeline* pipeline); + inline void Configure(std::shared_ptr pipeline); inline void Configure(const MaterialPipelineInfo& pipelineInfo); - inline bool Configure(const String& pipelineName); inline void EnableAlphaTest(bool alphaTest); inline void EnableBlending(bool blending); @@ -71,25 +53,23 @@ namespace Nz inline void EnableVertexColor(bool vertexColor); inline void EnsurePipelineUpdate() const; - - inline RendererComparison GetDepthFunc() const; + + inline RendererComparison GetDepthCompareFunc() const; inline BlendFunc GetDstBlend() const; inline FaceSide GetFaceCulling() const; inline FaceFilling GetFaceFilling() const; inline float GetLineWidth() const; - inline const MaterialPipeline* GetPipeline() const; + inline const std::shared_ptr& GetPipeline() const; inline const MaterialPipelineInfo& GetPipelineInfo() const; inline float GetPointSize() const; inline const std::shared_ptr& GetSettings() const; - inline const std::shared_ptr& GetShader() const; + inline const std::shared_ptr& GetShader(ShaderStageType shaderStage) const; inline BlendFunc GetSrcBlend() const; - inline UniformBuffer* GetSharedUniformBuffer(std::size_t bufferIndex) const; inline const std::shared_ptr& GetTexture(std::size_t textureIndex) const; inline const std::shared_ptr& GetTextureSampler(std::size_t textureIndex) const; inline UniformBufferRef& GetUniformBuffer(std::size_t bufferIndex); inline const UniformBufferRef& GetUniformBuffer(std::size_t bufferIndex) const; - inline bool HasDepthMaterial() const; inline bool HasTexture(std::size_t textureIndex) const; inline bool HasVertexColor() const; @@ -106,21 +86,17 @@ namespace Nz inline bool IsShadowCastingEnabled() const; inline bool IsShadowReceiveEnabled() const; - void SaveToParameters(ParameterList* matData); - - inline void SetDepthFunc(RendererComparison depthFunc); + inline void SetDepthCompareFunc(RendererComparison depthFunc); inline void SetDstBlend(BlendFunc func); inline void SetFaceCulling(FaceSide faceSide); inline void SetFaceFilling(FaceFilling filling); inline void SetLineWidth(float lineWidth); inline void SetPointSize(float pointSize); - inline void SetShader(std::shared_ptr shader); - inline void SetUniformBuffer(std::size_t bufferIndex, UniformBuffer* uniformBuffer); + inline void SetShader(ShaderStageType shaderStage, std::shared_ptr shader); + inline void SetUniformBuffer(std::size_t bufferIndex, UniformBufferRef uniformBuffer); inline void SetSrcBlend(BlendFunc func); - inline void SetTexture(std::size_t textureIndex, Texture* texture); - inline void SetTextureSampler(std::size_t textureIndex, const TextureSampler& sampler); - - inline Material& operator=(const Material& material); + inline void SetTexture(std::size_t textureIndex, std::shared_ptr texture); + inline void SetTextureSampler(std::size_t textureIndex, std::shared_ptr sampler); // Signals: NazaraSignal(OnMaterialRelease, const Material* /*material*/); @@ -138,7 +114,7 @@ namespace Nz std::shared_ptr m_settings; std::vector m_textures; std::vector m_uniformBuffers; - mutable const MaterialPipeline* m_pipeline; + mutable std::shared_ptr m_pipeline; MaterialPipelineInfo m_pipelineInfo; mutable bool m_pipelineUpdated; bool m_shadowCastingEnabled; diff --git a/include/Nazara/Graphics/Material.inl b/include/Nazara/Graphics/Material.inl index d60bde1c1..3729bf2e2 100644 --- a/include/Nazara/Graphics/Material.inl +++ b/include/Nazara/Graphics/Material.inl @@ -9,18 +9,6 @@ namespace Nz { - /*! - * \brief Constructs a Material object by assignation - * - * \param material Material to copy into this - */ - inline Material::Material(const Material& material) : - RefCounted(), - Resource(material) - { - operator=(material); - } - /*! * \brief Destructs the object and calls OnMaterialRelease * @@ -40,11 +28,11 @@ namespace Nz * * \see Configure */ - inline void Material::Configure(const MaterialPipeline* pipeline) + inline void Material::Configure(std::shared_ptr pipeline) { NazaraAssert(pipeline, "Invalid material pipeline"); - m_pipeline = pipeline; + m_pipeline = std::move(pipeline); m_pipelineInfo = m_pipeline->GetInfo(); m_pipelineUpdated = true; } @@ -65,28 +53,6 @@ namespace Nz InvalidatePipeline(); } - /*! - * \brief Reset material pipeline state - * - * Sets the material pipeline using a name to lookup in the MaterialPipelineLibrary - * - * \return True if the material pipeline was found in the library - * - * \see Configure - */ - inline bool Material::Configure(const String& pipelineName) - { - MaterialPipelineRef pipeline = MaterialPipelineLibrary::Query(pipelineName); - if (!pipeline) - { - NazaraError("Failed to get pipeline \"" + pipelineName + "\""); - return false; - } - - Configure(std::move(pipeline)); - return true; - } - /*! * \brief Enable/Disable alpha test for this material * @@ -377,23 +343,11 @@ namespace Nz * \see EnableDepthTest * \see SetAmbientColor */ - inline RendererComparison Material::GetDepthFunc() const + inline RendererComparison Material::GetDepthCompareFunc() const { return m_pipelineInfo.depthCompare; } - /*! - * \brief Gets the depth material - * - * \return Constant reference to the depth material - * - * \see EnableShadowCasting - */ - inline const MaterialRef& Material::GetDepthMaterial() const - { - return m_depthMaterial; - } - /*! * \brief Gets the dst in blend * @@ -440,7 +394,7 @@ namespace Nz * \brief Gets the render states * \return Constant reference to the render states */ - inline const MaterialPipeline* Material::GetPipeline() const + inline const std::shared_ptr& Material::GetPipeline() const { EnsurePipelineUpdate(); @@ -465,18 +419,6 @@ namespace Nz return m_pipelineInfo.pointSize; } - /*! - * \brief Gets the reflection mode of the material - * - * \return Current reflection mode - * - * \see SetReflectionMode - */ - inline ReflectionMode Material::GetReflectionMode() const - { - return m_reflectionMode; - } - inline const std::shared_ptr& Material::GetSettings() const { return m_settings; @@ -486,9 +428,9 @@ namespace Nz * \brief Gets the über-shader used by this material * \return Constant pointer to the über-shader used */ - inline const UberShader* Material::GetShader() const + inline const std::shared_ptr& Material::GetShader(ShaderStageType shaderStage) const { - return m_pipelineInfo.uberShader; + return m_pipelineInfo.shaders[UnderlyingCast(shaderStage)]; } /*! @@ -500,19 +442,13 @@ namespace Nz return m_pipelineInfo.srcBlend; } - inline const TextureRef& Material::GetTexture(std::size_t textureIndex) const + inline const std::shared_ptr& Material::GetTexture(std::size_t textureIndex) const { NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index"); return m_textures[textureIndex].texture; } - inline TextureSampler& Material::GetTextureSampler(std::size_t textureIndex) - { - NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index"); - return m_textures[textureIndex].sampler; - } - - inline const TextureSampler& Material::GetTextureSampler(std::size_t textureIndex) const + inline const std::shared_ptr& Material::GetTextureSampler(std::size_t textureIndex) const { NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index"); return m_textures[textureIndex].sampler; @@ -530,15 +466,9 @@ namespace Nz return m_uniformBuffers[bufferIndex]; } - inline bool Material::HasDepthMaterial() const - { - return m_depthMaterial.IsValid(); - } - inline bool Material::HasTexture(std::size_t textureIndex) const { - Texture* texture = GetTexture(textureIndex); - return texture && texture->IsValid(); + return GetTexture(textureIndex) != nullptr; } /*! @@ -667,24 +597,13 @@ namespace Nz * * \remark Invalidates the pipeline */ - inline void Material::SetDepthFunc(RendererComparison depthFunc) + inline void Material::SetDepthCompareFunc(RendererComparison depthFunc) { - m_pipelineInfo.depthFunc = depthFunc; + m_pipelineInfo.depthCompare = depthFunc; InvalidatePipeline(); } - /*! - * \brief Sets the depth material - * \return true If successful - * - * \param depthMaterial Material for depth - */ - inline void Material::SetDepthMaterial(MaterialRef depthMaterial) - { - m_depthMaterial = std::move(depthMaterial); - } - /*! * \brief Sets the dst in blend * @@ -763,34 +682,6 @@ namespace Nz InvalidatePipeline(); } - /*! - * \brief Changes reflection mode of the material - * - * When reflections are enabled, the material will render reflections from the object environment according to the reflection mode. - * This function does change the reflection mode used by the material. - * - * Skyboxes reflections are the cheapest but are static and thus can't reflect other objects. - * Probes reflections are cheap, depending on probes reflection mode, but require regular probe finding from objects using it. - * Real-time reflections are expensive but provide the most accurate reflection map (and can reflect other objects around). - * - * \param reflectionMode The new reflection mode this material should use - * - * \remark May invalidates the pipeline - * - * \see EnableReflectionMapping - * \see IsReflectionMappingEnabled - * \see SetReflectionSize - */ - inline void Material::SetReflectionMode(ReflectionMode reflectionMode) - { - if (m_reflectionMode != reflectionMode) - { - OnMaterialReflectionModeChange(this, reflectionMode); - - m_reflectionMode = reflectionMode; - } - } - /*! * \brief Sets the shader with a constant reference to a ubershader * @@ -800,52 +691,29 @@ namespace Nz * * \see GetShader */ - inline void Material::SetShader(UberShaderConstRef uberShader) + inline void Material::SetShader(ShaderStageType shaderStage, std::shared_ptr shader) { - m_pipelineInfo.uberShader = std::move(uberShader); + m_pipelineInfo.shaders[UnderlyingCast(shaderStage)] = std::move(shader); InvalidatePipeline(); } - /*! - * \brief Sets the shader by name - * \return true If successful - * - * \param uberShaderName Named shader - */ - inline bool Material::SetShader(const String& uberShaderName) - { - UberShaderConstRef uberShader = UberShaderLibrary::Get(uberShaderName); - if (!uberShader) - return false; - - SetShader(std::move(uberShader)); - return true; - } - - inline void Material::SetUniformBuffer(std::size_t bufferIndex, UniformBuffer* uniformBuffer) + inline void Material::SetUniformBuffer(std::size_t bufferIndex, UniformBufferRef uniformBuffer) { NazaraAssert(bufferIndex < m_uniformBuffers.size(), "Invalid shared uniform buffer index"); - m_uniformBuffers[bufferIndex] = uniformBuffer; + m_uniformBuffers[bufferIndex] = std::move(uniformBuffer); } - inline void Material::SetTexture(std::size_t textureIndex, Texture* texture) + inline void Material::SetTexture(std::size_t textureIndex, std::shared_ptr texture) { NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index"); - m_textures[textureIndex].texture = texture; - - if (texture) - m_pipelineInfo.textures |= UInt64(1) << UInt64(textureIndex); - else - m_pipelineInfo.textures &= ~(UInt64(1) << UInt64(textureIndex)); - - InvalidatePipeline(); + m_textures[textureIndex].texture = std::move(texture); } - inline void Material::SetTextureSampler(std::size_t textureIndex, const TextureSampler& sampler) + inline void Material::SetTextureSampler(std::size_t textureIndex, std::shared_ptr sampler) { NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index"); - m_textures[textureIndex].sampler = sampler; + m_textures[textureIndex].sampler = std::move(sampler); } /*! @@ -864,93 +732,6 @@ namespace Nz InvalidatePipeline(); } - /*! - * \brief Sets the current material with the content of the other one - * \return A reference to this - * - * \param material The other Material - */ - inline Material& Material::operator=(const Material& material) - { - Resource::operator=(material); - - m_settings = material.m_settings; - m_textures = material.m_textures; - m_depthMaterial = material.m_depthMaterial; - m_pipeline = material.m_pipeline; - m_pipelineInfo = material.m_pipelineInfo; - m_pipelineUpdated = material.m_pipelineUpdated; - m_shadowCastingEnabled = material.m_shadowCastingEnabled; - m_reflectionSize = material.m_reflectionSize; - - m_pipelineInfo.settings = m_settings; - - for (std::size_t i = 0; i < m_uniformBuffers.size(); ++i) - { - const UniformBuffer* sourceBuffer = material.GetUniformBuffer(i); - UniformBuffer* targetBuffer = m_uniformBuffers[i] = UniformBuffer::New(sourceBuffer->GetEndOffset() - sourceBuffer->GetStartOffset(), DataStorage_Hardware, BufferUsage_Dynamic); - if (!targetBuffer->CopyContent(sourceBuffer)) - NazaraError("Failed to copy uniform buffer content"); - } - - SetReflectionMode(material.GetReflectionMode()); - return *this; - } - - /*! - * \brief Gets the default material - * - * \return Reference to the default material - * - * \remark This material should NOT be modified as it would affect all objects using it - */ - inline MaterialRef Material::GetDefault() - { - return s_defaultMaterial; - } - - inline int Material::GetTextureUnit(TextureMap textureMap) - { - return s_textureUnits[textureMap]; - } - - /*! - * \brief Loads the material from file - * \return true if loading is successful - * - * \param filePath Path to the file - * \param params Parameters for the material - */ - inline MaterialRef Material::LoadFromFile(const String& filePath, const MaterialParams& params) - { - return MaterialLoader::LoadFromFile(filePath, params); - } - - /*! - * \brief Loads the material from memory - * \return true if loading is successful - * - * \param data Raw memory - * \param size Size of the memory - * \param params Parameters for the material - */ - inline MaterialRef Material::LoadFromMemory(const void* data, std::size_t size, const MaterialParams& params) - { - return MaterialLoader::LoadFromMemory(data, size, params); - } - - /*! - * \brief Loads the material from stream - * \return true if loading is successful - * - * \param stream Stream to the material - * \param params Parameters for the material - */ - inline MaterialRef Material::LoadFromStream(Stream& stream, const MaterialParams& params) - { - return MaterialLoader::LoadFromStream(stream, params); - } - inline void Material::InvalidatePipeline() { m_pipelineUpdated = false; @@ -958,24 +739,9 @@ namespace Nz inline void Material::UpdatePipeline() const { - m_pipeline = MaterialPipeline::GetPipeline(m_pipelineInfo); + m_pipeline = MaterialPipeline::Get(m_pipelineInfo); m_pipelineUpdated = true; } - - /*! - * \brief Creates a new material from the arguments - * \return A reference to the newly created material - * - * \param args Arguments for the material - */ - template - MaterialRef Material::New(Args&&... args) - { - std::unique_ptr object(new Material(std::forward(args)...)); - object->SetPersistent(false); - - return object.release(); - } } #include diff --git a/include/Nazara/Graphics/MaterialPipeline.hpp b/include/Nazara/Graphics/MaterialPipeline.hpp index 6147e50b9..188536b23 100644 --- a/include/Nazara/Graphics/MaterialPipeline.hpp +++ b/include/Nazara/Graphics/MaterialPipeline.hpp @@ -17,7 +17,7 @@ namespace Nz { - class Shader; + class ShaderStage; struct MaterialPipelineInfo : RenderStates { @@ -26,11 +26,9 @@ namespace Nz bool hasVertexColor = false; bool reflectionMapping = false; bool shadowReceive = true; - Nz::UInt64 textures = 0; - std::shared_ptr pipelineLayout; std::shared_ptr settings; - std::shared_ptr shader; + std::array, ShaderStageTypeCount> shaders; }; inline bool operator==(const MaterialPipelineInfo& lhs, const MaterialPipelineInfo& rhs); @@ -39,46 +37,33 @@ namespace Nz class NAZARA_GRAPHICS_API MaterialPipeline { - public: - struct Instance; + friend class Graphics; + struct Token {}; + + public: + inline MaterialPipeline(const MaterialPipelineInfo& pipelineInfo, Token); MaterialPipeline(const MaterialPipeline&) = delete; MaterialPipeline(MaterialPipeline&&) = delete; ~MaterialPipeline() = default; - inline const Instance& Apply(UInt32 flags = ShaderFlags_None) const; - MaterialPipeline& operator=(const MaterialPipeline&) = delete; MaterialPipeline& operator=(MaterialPipeline&&) = delete; inline const MaterialPipelineInfo& GetInfo() const; - inline const Instance& GetInstance(UInt32 flags = ShaderFlags_None) const; + const std::shared_ptr& GetRenderPipeline(const std::vector& vertexBuffers) const; - static MaterialPipelineRef GetPipeline(const MaterialPipelineInfo& pipelineInfo); - - struct Instance - { - RenderPipeline renderPipeline; - //Shader::LayoutBindings bindings; - //UberShaderInstance* uberInstance = nullptr; - }; + static const std::shared_ptr& Get(const MaterialPipelineInfo& pipelineInfo); private: - inline MaterialPipeline(const MaterialPipelineInfo& pipelineInfo); - - void GenerateRenderPipeline(UInt32 flags) const; - static bool Initialize(); - template static MaterialPipelineRef New(Args&&... args); static void Uninitialize(); + mutable std::vector> m_renderPipelines; MaterialPipelineInfo m_pipelineInfo; - mutable std::array m_instances; - using PipelineCache = std::unordered_map; + using PipelineCache = std::unordered_map>; static PipelineCache s_pipelineCache; - - static MaterialPipelineLibrary::LibraryMap s_library; }; } diff --git a/include/Nazara/Graphics/MaterialPipeline.inl b/include/Nazara/Graphics/MaterialPipeline.inl index f771f8a52..f4d80e9c4 100644 --- a/include/Nazara/Graphics/MaterialPipeline.inl +++ b/include/Nazara/Graphics/MaterialPipeline.inl @@ -3,32 +3,16 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include #include #include namespace Nz { - inline MaterialPipeline::MaterialPipeline(const MaterialPipelineInfo& pipelineInfo) : + inline MaterialPipeline::MaterialPipeline(const MaterialPipelineInfo& pipelineInfo, Token) : m_pipelineInfo(pipelineInfo) { } - /*! - * \brief Enable pipeline states for rendering - * - * \param flags Shader flags - */ - inline const MaterialPipeline::Instance& MaterialPipeline::Apply(UInt32 flags) const - { - const Instance& instance = GetInstance(flags); - instance.uberInstance->Activate(); - - Renderer::SetRenderStates(m_pipelineInfo); - - return instance; - } - /*! * \brief Retrieve a MaterialPipelineInfo object describing this pipeline * @@ -39,22 +23,6 @@ namespace Nz return m_pipelineInfo; } - /*! - * \brief Retrieve (and generate if required) a pipeline instance using shader flags without applying it - * - * \param flags Shader flags - * - * \return Pipeline instance - */ - inline const MaterialPipeline::Instance& MaterialPipeline::GetInstance(UInt32 flags) const - { - const Instance& instance = m_instances[flags]; - if (!instance.uberInstance) - GenerateRenderPipeline(flags); - - return instance; - } - bool operator==(const MaterialPipelineInfo& lhs, const MaterialPipelineInfo& rhs) { if (!operator==(static_cast(lhs), static_cast(rhs))) @@ -68,9 +36,13 @@ namespace Nz NazaraPipelineBoolMember(reflectionMapping); NazaraPipelineBoolMember(shadowReceive); - NazaraPipelineMember(pipelineLayout); NazaraPipelineMember(settings); - NazaraPipelineMember(shader); + + for (std::size_t i = 0; i < lhs.shaders.size(); ++i) + { + if (lhs.shaders[i] != rhs.shaders[i]) + return false; + } #undef NazaraPipelineMember #undef NazaraPipelineBoolMember @@ -82,20 +54,6 @@ namespace Nz { return !operator==(lhs, rhs); } - - /*! - * \brief Creates a new MaterialPipeline from the arguments - * \return A reference to the newly created material pipeline - * - * \param args Arguments for the material pipeline - */ - template - MaterialPipelineRef MaterialPipeline::New(Args&&... args) - { - std::unique_ptr object(new MaterialPipeline(std::forward(args)...)); - object->SetPersistent(false); - return object.release(); - } } namespace std @@ -121,9 +79,10 @@ namespace std NazaraPipelineBoolMember(reflectionMapping); NazaraPipelineBoolMember(shadowReceive); - NazaraPipelineMember(pipelineLayout.get()); //< Hash pointer NazaraPipelineMember(settings.get()); //< Hash pointer - NazaraPipelineMember(shader.get()); + + for (const auto& shader : pipelineInfo.shaders) + Nz::HashCombine(seed, shader.get()); #undef NazaraPipelineMember #undef NazaraPipelineBoolMember diff --git a/include/Nazara/Graphics/MaterialSettings.hpp b/include/Nazara/Graphics/MaterialSettings.hpp index 069224bc4..47aaef153 100644 --- a/include/Nazara/Graphics/MaterialSettings.hpp +++ b/include/Nazara/Graphics/MaterialSettings.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,7 @@ namespace Nz class MaterialSettings { public: + using DefaultShaders = std::array, ShaderStageTypeCount>; using PredefinedBinding = std::array; struct SharedUniformBlock; @@ -28,11 +30,13 @@ namespace Nz struct UniformBlock; inline MaterialSettings(); - inline MaterialSettings(std::vector textures, std::vector uniformBlocks, std::vector sharedUniformBlocks, const PredefinedBinding& predefinedBinding); + inline MaterialSettings(std::vector textures, std::vector uniformBlocks, std::vector sharedUniformBlocks, const PredefinedBinding& predefinedBinding, DefaultShaders defaultShaders); MaterialSettings(const MaterialSettings&) = default; MaterialSettings(MaterialSettings&&) = delete; ~MaterialSettings() = default; + inline const std::shared_ptr& GetDefaultShader(ShaderStageType stage) const; + inline const DefaultShaders& GetDefaultShaders() const; inline std::size_t GetPredefinedBindingIndex(PredefinedShaderBinding binding) const; inline const std::shared_ptr& GetRenderPipelineLayout() const; inline const std::vector& GetSharedUniformBlocks() const; @@ -83,6 +87,7 @@ namespace Nz std::vector m_sharedUniformBlocks; std::vector m_textures; std::vector m_uniformBlocks; + DefaultShaders m_defaultShaders; PredefinedBinding m_predefinedBinding; }; } diff --git a/include/Nazara/Graphics/MaterialSettings.inl b/include/Nazara/Graphics/MaterialSettings.inl index ca410d0fc..fd0356e04 100644 --- a/include/Nazara/Graphics/MaterialSettings.inl +++ b/include/Nazara/Graphics/MaterialSettings.inl @@ -10,14 +10,15 @@ namespace Nz { inline MaterialSettings::MaterialSettings() : - MaterialSettings({}, {}, {}, { InvalidIndex }) + MaterialSettings({}, {}, {}, { InvalidIndex }, {}) { } - inline MaterialSettings::MaterialSettings(std::vector textures, std::vector uniformBlocks, std::vector sharedUniformBlocks, const PredefinedBinding& predefinedBindings) : + inline MaterialSettings::MaterialSettings(std::vector textures, std::vector uniformBlocks, std::vector sharedUniformBlocks, const PredefinedBinding& predefinedBindings, DefaultShaders defaultShaders) : m_sharedUniformBlocks(std::move(sharedUniformBlocks)), m_textures(std::move(textures)), m_uniformBlocks(std::move(uniformBlocks)), + m_defaultShaders(std::move(defaultShaders)), m_predefinedBinding(predefinedBindings) { RenderPipelineLayoutInfo info; @@ -27,7 +28,7 @@ namespace Nz for (const Texture& textureInfo : m_textures) { info.bindings.push_back({ - textureInfo.bindingPoint, + //textureInfo.bindingPoint, ShaderBindingType::Texture, ShaderStageType_All, bindingIndex++ @@ -37,7 +38,7 @@ namespace Nz for (const UniformBlock& ubo : m_uniformBlocks) { info.bindings.push_back({ - ubo.bindingPoint, + //ubo.bindingPoint, ShaderBindingType::UniformBuffer, ShaderStageType_All, bindingIndex++ @@ -47,7 +48,7 @@ namespace Nz for (const SharedUniformBlock& ubo : m_sharedUniformBlocks) { info.bindings.push_back({ - ubo.bindingPoint, + //ubo.bindingPoint, ShaderBindingType::UniformBuffer, ShaderStageType_All, bindingIndex++ @@ -57,9 +58,19 @@ namespace Nz m_pipelineLayout = Graphics::Instance()->GetRenderDevice().InstantiateRenderPipelineLayout(std::move(info)); } + inline const std::shared_ptr& MaterialSettings::GetDefaultShader(ShaderStageType stage) const + { + return m_defaultShaders[UnderlyingCast(stage)]; + } + + inline auto MaterialSettings::GetDefaultShaders() const -> const DefaultShaders& + { + return m_defaultShaders; + } + inline std::size_t MaterialSettings::GetPredefinedBindingIndex(PredefinedShaderBinding binding) const { - return m_predefinedBinding[static_cast(binding)]; + return m_predefinedBinding[UnderlyingCast(binding)]; } inline const std::shared_ptr& MaterialSettings::GetRenderPipelineLayout() const diff --git a/include/Nazara/Graphics/PhongLightingMaterial.hpp b/include/Nazara/Graphics/PhongLightingMaterial.hpp index 277cdc873..34f4cf42a 100644 --- a/include/Nazara/Graphics/PhongLightingMaterial.hpp +++ b/include/Nazara/Graphics/PhongLightingMaterial.hpp @@ -17,21 +17,21 @@ namespace Nz friend class MaterialPipeline; public: - PhongLightingMaterial(Material* material); + PhongLightingMaterial(Material& material); - inline const TextureRef& GetAlphaMap() const; + inline const std::shared_ptr& GetAlphaMap() const; float GetAlphaThreshold() const; Color GetAmbientColor() const; Color GetDiffuseColor() const; - inline const TextureRef& GetDiffuseMap() const; + inline const std::shared_ptr& GetDiffuseMap() const; inline TextureSampler& GetDiffuseSampler(); inline const TextureSampler& GetDiffuseSampler() const; - inline const TextureRef& GetEmissiveMap() const; - inline const TextureRef& GetHeightMap() const; - inline const TextureRef& GetNormalMap() const; + inline const std::shared_ptr& GetEmissiveMap() const; + inline const std::shared_ptr& GetHeightMap() const; + inline const std::shared_ptr& GetNormalMap() const; float GetShininess() const; Color GetSpecularColor() const; - inline const TextureRef& GetSpecularMap() const; + inline const std::shared_ptr& GetSpecularMap() const; inline TextureSampler& GetSpecularSampler(); inline const TextureSampler& GetSpecularSampler() const; @@ -47,24 +47,18 @@ namespace Nz inline bool HasSpecularColor() const; inline bool HasSpecularMap() const; - inline bool SetAlphaMap(const String& textureName); - inline void SetAlphaMap(TextureRef alphaMap); + inline void SetAlphaMap(std::shared_ptr alphaMap); void SetAlphaThreshold(float alphaThreshold); void SetAmbientColor(const Color& ambient); void SetDiffuseColor(const Color& diffuse); - inline bool SetDiffuseMap(const String& textureName); - inline void SetDiffuseMap(TextureRef diffuseMap); + inline void SetDiffuseMap(std::shared_ptr diffuseMap); inline void SetDiffuseSampler(const TextureSampler& sampler); - inline bool SetEmissiveMap(const String& textureName); - inline void SetEmissiveMap(TextureRef textureName); - inline bool SetHeightMap(const String& textureName); - inline void SetHeightMap(TextureRef textureName); - inline bool SetNormalMap(const String& textureName); - inline void SetNormalMap(TextureRef textureName); + inline void SetEmissiveMap(std::shared_ptr textureName); + inline void SetHeightMap(std::shared_ptr textureName); + inline void SetNormalMap(std::shared_ptr textureName); void SetShininess(float shininess); void SetSpecularColor(const Color& specular); - inline bool SetSpecularMap(const String& textureName); - inline void SetSpecularMap(TextureRef specularMap); + inline void SetSpecularMap(std::shared_ptr specularMap); inline void SetSpecularSampler(const TextureSampler& sampler); static const std::shared_ptr& GetSettings(); @@ -92,14 +86,13 @@ namespace Nz static bool Initialize(); static void Uninitialize(); - MaterialRef m_material; + Material& m_material; std::size_t m_phongUniformIndex; TextureIndexes m_textureIndexes; PhongUniformOffsets m_phongUniformOffsets; static std::shared_ptr s_materialSettings; static std::size_t s_phongUniformBlockIndex; - static RenderPipelineLayoutRef s_renderPipelineLayout; static TextureIndexes s_textureIndexes; static PhongUniformOffsets s_phongUniformOffsets; }; diff --git a/include/Nazara/Graphics/PhongLightingMaterial.inl b/include/Nazara/Graphics/PhongLightingMaterial.inl index 1fc14ed20..b9bd61d20 100644 --- a/include/Nazara/Graphics/PhongLightingMaterial.inl +++ b/include/Nazara/Graphics/PhongLightingMaterial.inl @@ -9,40 +9,40 @@ namespace Nz { - inline const TextureRef& PhongLightingMaterial::GetAlphaMap() const + inline const std::shared_ptr& PhongLightingMaterial::GetAlphaMap() const { NazaraAssert(HasAlphaMap(), "Material has no alpha map slot"); - return m_material->GetTexture(m_textureIndexes.alpha); + return m_material.GetTexture(m_textureIndexes.alpha); } - inline const TextureRef& PhongLightingMaterial::GetDiffuseMap() const + inline const std::shared_ptr& PhongLightingMaterial::GetDiffuseMap() const { NazaraAssert(HasDiffuseMap(), "Material has no alpha map slot"); - return m_material->GetTexture(m_textureIndexes.diffuse); + return m_material.GetTexture(m_textureIndexes.diffuse); } - inline const TextureRef& PhongLightingMaterial::GetEmissiveMap() const + inline const std::shared_ptr& PhongLightingMaterial::GetEmissiveMap() const { NazaraAssert(HasEmissiveMap(), "Material has no alpha map slot"); - return m_material->GetTexture(m_textureIndexes.emissive); + return m_material.GetTexture(m_textureIndexes.emissive); } - inline const TextureRef& PhongLightingMaterial::GetHeightMap() const + inline const std::shared_ptr& PhongLightingMaterial::GetHeightMap() const { NazaraAssert(HasHeightMap(), "Material has no alpha map slot"); - return m_material->GetTexture(m_textureIndexes.height); + return m_material.GetTexture(m_textureIndexes.height); } - inline const TextureRef& PhongLightingMaterial::GetNormalMap() const + inline const std::shared_ptr& PhongLightingMaterial::GetNormalMap() const { NazaraAssert(HasNormalMap(), "Material has no alpha map slot"); - return m_material->GetTexture(m_textureIndexes.normal); + return m_material.GetTexture(m_textureIndexes.normal); } - inline const TextureRef& PhongLightingMaterial::GetSpecularMap() const + inline const std::shared_ptr& PhongLightingMaterial::GetSpecularMap() const { NazaraAssert(HasSpecularMap(), "Material has no alpha map slot"); - return m_material->GetTexture(m_textureIndexes.specular); + return m_material.GetTexture(m_textureIndexes.specular); } inline bool PhongLightingMaterial::HasAlphaMap() const @@ -100,56 +100,22 @@ namespace Nz return m_textureIndexes.specular != MaterialSettings::InvalidIndex; } - inline void PhongLightingMaterial::SetAlphaMap(TextureRef alphaMap) + inline void PhongLightingMaterial::SetAlphaMap(std::shared_ptr alphaMap) { NazaraAssert(HasAlphaMap(), "Material has no alpha map slot"); - m_material->SetTexture(m_textureIndexes.alpha, std::move(alphaMap)); + m_material.SetTexture(m_textureIndexes.alpha, std::move(alphaMap)); } - inline bool PhongLightingMaterial::SetDiffuseMap(const String& textureName) - { - TextureRef texture = TextureLibrary::Query(textureName); - if (!texture) - { - texture = TextureManager::Get(textureName); - if (!texture) - { - NazaraError("Failed to get diffuse map \"" + textureName + "\""); - return false; - } - } - - SetDiffuseMap(std::move(texture)); - return true; - } - - inline void PhongLightingMaterial::SetDiffuseMap(TextureRef diffuseMap) + inline void PhongLightingMaterial::SetDiffuseMap(std::shared_ptr diffuseMap) { NazaraAssert(HasDiffuseMap(), "Material has no diffuse map slot"); - m_material->SetTexture(m_textureIndexes.diffuse, std::move(diffuseMap)); + m_material.SetTexture(m_textureIndexes.diffuse, std::move(diffuseMap)); } - inline bool PhongLightingMaterial::SetNormalMap(const String& textureName) - { - TextureRef texture = TextureLibrary::Query(textureName); - if (!texture) - { - texture = TextureManager::Get(textureName); - if (!texture) - { - NazaraError("Failed to get normal map \"" + textureName + "\""); - return false; - } - } - - SetNormalMap(std::move(texture)); - return true; - } - - inline void PhongLightingMaterial::SetNormalMap(TextureRef normalMap) + inline void PhongLightingMaterial::SetNormalMap(std::shared_ptr normalMap) { NazaraAssert(HasNormalMap(), "Material has no normal map slot"); - m_material->SetTexture(m_textureIndexes.normal, std::move(normalMap)); + m_material.SetTexture(m_textureIndexes.normal, std::move(normalMap)); } } diff --git a/include/Nazara/Graphics/PredefinedShaderStructs.hpp b/include/Nazara/Graphics/PredefinedShaderStructs.hpp index d196b5e0a..89b207ed1 100644 --- a/include/Nazara/Graphics/PredefinedShaderStructs.hpp +++ b/include/Nazara/Graphics/PredefinedShaderStructs.hpp @@ -41,7 +41,7 @@ namespace Nz std::size_t totalSize; std::size_t worldMatrixOffset; - static PredefinedInstanceData GetOffset(); + static PredefinedInstanceData GetOffsets(); static MaterialSettings::SharedUniformBlock GetUniformBlock(); }; @@ -58,7 +58,7 @@ namespace Nz std::size_t viewMatrixOffset; std::size_t viewProjMatrixOffset; - static PredefinedViewerData GetOffset(); + static PredefinedViewerData GetOffsets(); static MaterialSettings::SharedUniformBlock GetUniformBlock(); }; } diff --git a/include/Nazara/Renderer/RenderPipelineLayout.hpp b/include/Nazara/Renderer/RenderPipelineLayout.hpp index 38c1b6ef3..c0d64b26a 100644 --- a/include/Nazara/Renderer/RenderPipelineLayout.hpp +++ b/include/Nazara/Renderer/RenderPipelineLayout.hpp @@ -21,7 +21,6 @@ namespace Nz { struct Binding { - std::string name; //< FIXME: wtf is this? ShaderBindingType type; ShaderStageTypeFlags shaderStageFlags; unsigned int index; diff --git a/include/Nazara/Utility/Enums.hpp b/include/Nazara/Utility/Enums.hpp index ad0d11fe6..f68fb3ea6 100644 --- a/include/Nazara/Utility/Enums.hpp +++ b/include/Nazara/Utility/Enums.hpp @@ -318,6 +318,8 @@ namespace Nz Max = Vertex }; + constexpr std::size_t ShaderStageTypeCount = static_cast(ShaderStageType::Max) + 1; + template<> struct EnumAsFlags { diff --git a/shaders/BasicMaterial/basicmaterial.frag.shaderflow b/shaders/BasicMaterial/basicmaterial.frag.shaderflow new file mode 100644 index 000000000..4ffa6960d --- /dev/null +++ b/shaders/BasicMaterial/basicmaterial.frag.shaderflow @@ -0,0 +1,361 @@ +{ + "buffers": [ + { + "bindingIndex": 5, + "name": "viewerData", + "structIndex": 2, + "type": "UniformBufferObject" + }, + { + "bindingIndex": 4, + "name": "instanceData", + "structIndex": 1, + "type": "UniformBufferObject" + }, + { + "bindingIndex": 3, + "name": "settings", + "structIndex": 0, + "type": "UniformBufferObject" + } + ], + "connections": [ + { + "in_id": "{fbaddbbe-f9cd-4e8d-b7a8-40c10c96f580}", + "in_index": 0, + "out_id": "{ac98a68f-0160-4189-af31-b8278e7c119c}", + "out_index": 0 + }, + { + "in_id": "{fbaddbbe-f9cd-4e8d-b7a8-40c10c96f580}", + "in_index": 1, + "out_id": "{db10f064-504d-4072-a49e-51a061b2efbe}", + "out_index": 0 + }, + { + "in_id": "{cf0ae20a-88cd-4788-9ed7-eaf014d8f971}", + "in_index": 0, + "out_id": "{c41cd67b-2f34-4ec4-acc6-2f7285e7c6e3}", + "out_index": 0 + }, + { + "in_id": "{cf0ae20a-88cd-4788-9ed7-eaf014d8f971}", + "in_index": 1, + "out_id": "{74d3ca95-ae1d-496d-88c1-ce6c7327012a}", + "out_index": 0 + }, + { + "in_id": "{f5a6874b-0559-4fd1-9836-27567f9696a4}", + "in_index": 1, + "out_id": "{fbaddbbe-f9cd-4e8d-b7a8-40c10c96f580}", + "out_index": 0 + }, + { + "in_id": "{f5a6874b-0559-4fd1-9836-27567f9696a4}", + "in_index": 0, + "out_id": "{cf0ae20a-88cd-4788-9ed7-eaf014d8f971}", + "out_index": 0 + }, + { + "in_id": "{bed466d8-5ed0-4e8a-bba7-1c809cb4c3f7}", + "in_index": 1, + "out_id": "{43df5c43-d6f4-440f-a049-4fde6e738883}", + "out_index": 0 + }, + { + "in_id": "{43df5c43-d6f4-440f-a049-4fde6e738883}", + "in_index": 0, + "out_id": "{07a43c79-67e2-46b1-87d4-e00d2da22820}", + "out_index": 0 + }, + { + "in_id": "{be3547ff-0bf3-4701-9c27-c21e9d1322c3}", + "in_index": 0, + "out_id": "{f5a6874b-0559-4fd1-9836-27567f9696a4}", + "out_index": 0 + } + ], + "inputs": [ + { + "locationIndex": 0, + "name": "vertNormal", + "role": "Normal", + "roleIndex": 0, + "type": "Float3" + }, + { + "locationIndex": 1, + "name": "vertUV", + "role": "TexCoord", + "roleIndex": 0, + "type": "Float2" + } + ], + "nodes": [ + { + "id": "{c41cd67b-2f34-4ec4-acc6-2f7285e7c6e3}", + "model": { + "input": "vertNormal", + "name": "Input", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "variable_name": "" + }, + "position": { + "x": 103, + "y": 173 + } + }, + { + "id": "{cf0ae20a-88cd-4788-9ed7-eaf014d8f971}", + "model": { + "name": "vec_dot", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "variable_name": "lightFactor" + }, + "position": { + "x": 278, + "y": 212 + } + }, + { + "id": "{74d3ca95-ae1d-496d-88c1-ce6c7327012a}", + "model": { + "name": "vec3_constant", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "value": [ + 0, + -0.7070000171661377, + 0.7070000171661377 + ], + "variable_name": "lightDir" + }, + "position": { + "x": 115, + "y": 267 + } + }, + { + "id": "{fbaddbbe-f9cd-4e8d-b7a8-40c10c96f580}", + "model": { + "name": "SampleTexture", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "variable_name": "" + }, + "position": { + "x": 299, + "y": 488 + } + }, + { + "id": "{ac98a68f-0160-4189-af31-b8278e7c119c}", + "model": { + "name": "Texture", + "preview_enabled": true, + "preview_height": 64, + "preview_width": 64, + "texture": "MaterialDiffuseMap", + "variable_name": "" + }, + "position": { + "x": 103, + "y": 470 + } + }, + { + "id": "{db10f064-504d-4072-a49e-51a061b2efbe}", + "model": { + "input": "vertUV", + "name": "Input", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "variable_name": "" + }, + "position": { + "x": 113, + "y": 579 + } + }, + { + "id": "{f5a6874b-0559-4fd1-9836-27567f9696a4}", + "model": { + "name": "vecfloat_mul", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "variable_name": "" + }, + "position": { + "x": 488, + "y": 376 + } + }, + { + "id": "{be3547ff-0bf3-4701-9c27-c21e9d1322c3}", + "model": { + "name": "Output", + "output": "RenderTarget0", + "preview_enabled": true, + "preview_height": 128, + "preview_width": 128, + "variable_name": "" + }, + "position": { + "x": 912, + "y": 489 + } + }, + { + "id": "{bed466d8-5ed0-4e8a-bba7-1c809cb4c3f7}", + "model": { + "name": "vec_mul", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "variable_name": "" + }, + "position": { + "x": 707, + "y": 492 + } + }, + { + "id": "{43df5c43-d6f4-440f-a049-4fde6e738883}", + "model": { + "name": "cast_vec4", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "value": [ + 1, + 0, + 0, + 0 + ], + "variable_name": "matDiffuse" + }, + "position": { + "x": 521, + "y": 616 + } + }, + { + "id": "{07a43c79-67e2-46b1-87d4-e00d2da22820}", + "model": { + "buffer": "settings", + "field": "DiffuseColor", + "name": "BufferField", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "variable_name": "" + }, + "position": { + "x": 309, + "y": 637 + } + } + ], + "outputs": [ + { + "locationIndex": 0, + "name": "RenderTarget0", + "type": "Float4" + } + ], + "structs": [ + { + "members": [ + { + "name": "AlphaThreshold", + "type": "Float" + }, + { + "name": "DiffuseColor", + "type": "Float3" + } + ], + "name": "BasicSettings" + }, + { + "members": [ + { + "name": "worldMatrix", + "type": "Mat4x4" + }, + { + "name": "invWorldMatrix", + "type": "Mat4x4" + } + ], + "name": "InstanceData" + }, + { + "members": [ + { + "name": "projectionMatrix", + "type": "Mat4x4" + }, + { + "name": "invProjectionMatrix", + "type": "Mat4x4" + }, + { + "name": "viewMatrix", + "type": "Mat4x4" + }, + { + "name": "invViewMatrix", + "type": "Mat4x4" + }, + { + "name": "viewProjMatrix", + "type": "Mat4x4" + }, + { + "name": "invViewProjMatrix", + "type": "Mat4x4" + }, + { + "name": "renderTargetSize", + "type": "Float2" + }, + { + "name": "invRenderTargetSize", + "type": "Float2" + }, + { + "name": "eyePosition", + "type": "Float3" + } + ], + "name": "ViewerData" + } + ], + "textures": [ + { + "bindingIndex": 0, + "name": "MaterialAlphaMap", + "type": "Sampler2D" + }, + { + "bindingIndex": 1, + "name": "MaterialDiffuseMap", + "type": "Sampler2D" + }, + { + "bindingIndex": 2, + "name": "TextureOverlay", + "type": "Sampler2D" + } + ], + "type": "Fragment" +} diff --git a/shaders/BasicMaterial/basicmaterial.vert.shaderflow b/shaders/BasicMaterial/basicmaterial.vert.shaderflow new file mode 100644 index 000000000..4ba3f2125 --- /dev/null +++ b/shaders/BasicMaterial/basicmaterial.vert.shaderflow @@ -0,0 +1,392 @@ +{ + "buffers": [ + { + "bindingIndex": 5, + "name": "viewerData", + "structIndex": 2, + "type": "UniformBufferObject" + }, + { + "bindingIndex": 4, + "name": "instanceData", + "structIndex": 1, + "type": "UniformBufferObject" + }, + { + "bindingIndex": 3, + "name": "settings", + "structIndex": 0, + "type": "UniformBufferObject" + } + ], + "connections": [ + { + "in_id": "{1bb9712b-8bff-4398-9e4e-fba79a04df0e}", + "in_index": 1, + "out_id": "{a2fff9e2-af6e-4c7f-80ee-ca3492f3c5ab}", + "out_index": 0 + }, + { + "in_id": "{62731a4b-f054-4f78-82da-08d2584e51ab}", + "in_index": 1, + "out_id": "{7ac65f09-7f55-4a6e-9380-1bee5213f079}", + "out_index": 0 + }, + { + "in_id": "{62731a4b-f054-4f78-82da-08d2584e51ab}", + "in_index": 0, + "out_id": "{1bb9712b-8bff-4398-9e4e-fba79a04df0e}", + "out_index": 0 + }, + { + "in_id": "{43ce1867-629f-442b-a672-540fa67f1446}", + "in_index": 0, + "out_id": "{33840c70-4e37-4127-bab0-23c4a4cb6d7f}", + "out_index": 0 + }, + { + "in_id": "{7ac65f09-7f55-4a6e-9380-1bee5213f079}", + "in_index": 0, + "out_id": "{c3b906bc-d230-4026-a32e-34c00eaf4481}", + "out_index": 0 + }, + { + "in_id": "{d8f4d14a-c67a-470f-87bf-8f60d9513c3b}", + "in_index": 0, + "out_id": "{d32dfb1d-c8a4-4315-a710-90d2a51f68e8}", + "out_index": 0 + }, + { + "in_id": "{1bb9712b-8bff-4398-9e4e-fba79a04df0e}", + "in_index": 0, + "out_id": "{d8f4d14a-c67a-470f-87bf-8f60d9513c3b}", + "out_index": 0 + }, + { + "in_id": "{63bb13f0-55e3-451b-860e-568b65e09b04}", + "in_index": 0, + "out_id": "{62731a4b-f054-4f78-82da-08d2584e51ab}", + "out_index": 0 + }, + { + "in_id": "{0fc53363-dbce-4874-8de5-5ca05ae038b7}", + "in_index": 0, + "out_id": "{412684ce-0ec2-4db5-964c-10e5b68d43e8}", + "out_index": 0 + }, + { + "in_id": "{d8f4d14a-c67a-470f-87bf-8f60d9513c3b}", + "in_index": 1, + "out_id": "{c6058af1-6913-4218-a9b9-11adb5cdffa0}", + "out_index": 0 + } + ], + "inputs": [ + { + "locationIndex": 0, + "name": "inPos", + "role": "Position", + "roleIndex": 0, + "type": "Float3" + }, + { + "locationIndex": 1, + "name": "inNormals", + "role": "Normal", + "roleIndex": 0, + "type": "Float3" + }, + { + "locationIndex": 2, + "name": "inTexCoord", + "role": "TexCoord", + "roleIndex": 0, + "type": "Float2" + } + ], + "nodes": [ + { + "id": "{43ce1867-629f-442b-a672-540fa67f1446}", + "model": { + "name": "Output", + "output": "vertUV", + "preview_enabled": false, + "preview_height": 128, + "preview_width": 128, + "variable_name": "" + }, + "position": { + "x": 243, + "y": 292 + } + }, + { + "id": "{412684ce-0ec2-4db5-964c-10e5b68d43e8}", + "model": { + "input": "inNormals", + "name": "Input", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "variable_name": "" + }, + "position": { + "x": 79, + "y": 184 + } + }, + { + "id": "{0fc53363-dbce-4874-8de5-5ca05ae038b7}", + "model": { + "name": "Output", + "output": "vertNormal", + "preview_enabled": false, + "preview_height": 128, + "preview_width": 128, + "variable_name": "" + }, + "position": { + "x": 240, + "y": 192 + } + }, + { + "id": "{33840c70-4e37-4127-bab0-23c4a4cb6d7f}", + "model": { + "input": "inTexCoord", + "name": "Input", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "variable_name": "" + }, + "position": { + "x": 82, + "y": 287 + } + }, + { + "id": "{d8f4d14a-c67a-470f-87bf-8f60d9513c3b}", + "model": { + "name": "mat4_mul", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "variable_name": "" + }, + "position": { + "x": 248, + "y": 424 + } + }, + { + "id": "{1bb9712b-8bff-4398-9e4e-fba79a04df0e}", + "model": { + "name": "mat4_mul", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "variable_name": "" + }, + "position": { + "x": 463, + "y": 496 + } + }, + { + "id": "{c3b906bc-d230-4026-a32e-34c00eaf4481}", + "model": { + "input": "inPos", + "name": "Input", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "variable_name": "" + }, + "position": { + "x": 54, + "y": 675 + } + }, + { + "id": "{62731a4b-f054-4f78-82da-08d2584e51ab}", + "model": { + "name": "mat4vec_mul", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "variable_name": "" + }, + "position": { + "x": 699, + "y": 512 + } + }, + { + "id": "{7ac65f09-7f55-4a6e-9380-1bee5213f079}", + "model": { + "name": "cast_vec4", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "value": [ + 1, + 0, + 0, + 0 + ], + "variable_name": "" + }, + "position": { + "x": 345, + "y": 668 + } + }, + { + "id": "{63bb13f0-55e3-451b-860e-568b65e09b04}", + "model": { + "name": "PositionOutputValue", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "variable_name": "" + }, + "position": { + "x": 930, + "y": 524 + } + }, + { + "id": "{d32dfb1d-c8a4-4315-a710-90d2a51f68e8}", + "model": { + "buffer": "viewerData", + "field": "projectionMatrix", + "name": "BufferField", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "variable_name": "" + }, + "position": { + "x": 21, + "y": 374 + } + }, + { + "id": "{c6058af1-6913-4218-a9b9-11adb5cdffa0}", + "model": { + "buffer": "viewerData", + "field": "viewMatrix", + "name": "BufferField", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "variable_name": "" + }, + "position": { + "x": 25, + "y": 456 + } + }, + { + "id": "{a2fff9e2-af6e-4c7f-80ee-ca3492f3c5ab}", + "model": { + "buffer": "instanceData", + "field": "worldMatrix", + "name": "BufferField", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "variable_name": "" + }, + "position": { + "x": 27, + "y": 538 + } + } + ], + "outputs": [ + { + "locationIndex": 0, + "name": "vertNormal", + "type": "Float3" + }, + { + "locationIndex": 1, + "name": "vertUV", + "type": "Float2" + } + ], + "structs": [ + { + "members": [ + { + "name": "AlphaThreshold", + "type": "Float" + }, + { + "name": "DiffuseColor", + "type": "Float3" + } + ], + "name": "BasicSettings" + }, + { + "members": [ + { + "name": "worldMatrix", + "type": "Mat4x4" + }, + { + "name": "invWorldMatrix", + "type": "Mat4x4" + } + ], + "name": "InstanceData" + }, + { + "members": [ + { + "name": "projectionMatrix", + "type": "Mat4x4" + }, + { + "name": "invProjectionMatrix", + "type": "Mat4x4" + }, + { + "name": "viewMatrix", + "type": "Mat4x4" + }, + { + "name": "invViewMatrix", + "type": "Mat4x4" + }, + { + "name": "viewProjMatrix", + "type": "Mat4x4" + }, + { + "name": "invViewProjMatrix", + "type": "Mat4x4" + }, + { + "name": "renderTargetSize", + "type": "Float2" + }, + { + "name": "invRenderTargetSize", + "type": "Float2" + }, + { + "name": "eyePosition", + "type": "Float3" + } + ], + "name": "ViewerData" + } + ], + "textures": [ + ], + "type": "Vertex" +} diff --git a/src/Nazara/Graphics/BasicMaterial.cpp b/src/Nazara/Graphics/BasicMaterial.cpp index 6843562b5..96f13a05b 100644 --- a/src/Nazara/Graphics/BasicMaterial.cpp +++ b/src/Nazara/Graphics/BasicMaterial.cpp @@ -17,18 +17,20 @@ namespace Nz { namespace { - constexpr std::size_t AlphaMapBinding = 0; - constexpr std::size_t DiffuseMapBinding = 1; - constexpr std::size_t TextureOverlayBinding = 2; + const UInt8 r_fragmentShader[] = { + #include + }; + + const UInt8 r_vertexShader[] = { + #include + }; } - BasicMaterial::BasicMaterial(Material* material) : + BasicMaterial::BasicMaterial(Material& material) : m_material(material) { - NazaraAssert(material, "Invalid material"); - // Most common case: don't fetch texture indexes as a little optimization - const std::shared_ptr& materialSettings = material->GetSettings(); + const std::shared_ptr& materialSettings = material.GetSettings(); if (materialSettings == s_materialSettings) { m_textureIndexes = s_textureIndexes; @@ -51,17 +53,17 @@ namespace Nz { NazaraAssert(HasAlphaThreshold(), "Material has no alpha threshold uniform"); - BufferMapper mapper(m_material->GetUniformBuffer(m_uniformBlockIndex), BufferAccess_ReadOnly); - return *AccessByOffset(mapper.GetPointer(), m_uniformOffsets.alphaThreshold); + BufferMapper mapper(m_material.GetUniformBuffer(m_uniformBlockIndex), BufferAccess_ReadOnly); + return AccessByOffset(mapper.GetPointer(), m_uniformOffsets.alphaThreshold); } Color BasicMaterial::GetDiffuseColor() const { NazaraAssert(HasDiffuseColor(), "Material has no diffuse color uniform"); - BufferMapper mapper(m_material->GetUniformBuffer(m_uniformBlockIndex), BufferAccess_ReadOnly); + BufferMapper mapper(m_material.GetUniformBuffer(m_uniformBlockIndex), BufferAccess_ReadOnly); - const float* colorPtr = AccessByOffset(mapper.GetPointer(), m_uniformOffsets.diffuseColor); + const float* colorPtr = AccessByOffset(mapper.GetPointer(), m_uniformOffsets.diffuseColor); return Color(colorPtr[0] * 255, colorPtr[1] * 255, colorPtr[2] * 255, colorPtr[3] * 255); //< TODO: Make color able to use float } @@ -69,16 +71,16 @@ namespace Nz { NazaraAssert(HasAlphaThreshold(), "Material has no alpha threshold uniform"); - BufferMapper mapper(m_material->GetUniformBuffer(m_uniformBlockIndex), BufferAccess_WriteOnly); - *AccessByOffset(mapper.GetPointer(), m_uniformOffsets.alphaThreshold) = alphaThreshold; + BufferMapper mapper(m_material.GetUniformBuffer(m_uniformBlockIndex), BufferAccess_WriteOnly); + AccessByOffset(mapper.GetPointer(), m_uniformOffsets.alphaThreshold) = alphaThreshold; } void BasicMaterial::SetDiffuseColor(const Color& diffuse) { NazaraAssert(HasDiffuseColor(), "Material has no diffuse color uniform"); - BufferMapper mapper(m_material->GetUniformBuffer(m_uniformBlockIndex), BufferAccess_WriteOnly); - float* colorPtr = AccessByOffset(mapper.GetPointer(), m_uniformOffsets.diffuseColor); + BufferMapper mapper(m_material.GetUniformBuffer(m_uniformBlockIndex), BufferAccess_WriteOnly); + float* colorPtr = AccessByOffset(mapper.GetPointer(), m_uniformOffsets.diffuseColor); colorPtr[0] = diffuse.r / 255.f; colorPtr[1] = diffuse.g / 255.f; colorPtr[2] = diffuse.b / 255.f; @@ -92,31 +94,6 @@ namespace Nz bool BasicMaterial::Initialize() { - RenderPipelineLayoutInfo info; - info.bindings.assign({ - { - "MaterialAlphaMap", - ShaderBindingType_Texture, - ShaderStageType_Fragment, - AlphaMapBinding - }, - { - "MaterialDiffuseMap", - ShaderBindingType_Texture, - ShaderStageType_Fragment, - DiffuseMapBinding - }, - { - "TextureOverlay", - ShaderBindingType_Texture, - ShaderStageType_Fragment, - TextureOverlayBinding - } - }); - - s_renderPipelineLayout = RenderPipelineLayout::New(); - s_renderPipelineLayout->Create(info); - FieldOffsets fieldOffsets(StructLayout_Std140); s_uniformOffsets.diffuseColor = fieldOffsets.AddField(StructFieldType_Float4); @@ -140,15 +117,37 @@ namespace Nz static_assert(sizeof(Vector4f) == 4 * sizeof(float), "Vector4f is expected to be exactly 4 floats wide"); std::vector defaultValues(fieldOffsets.GetSize()); - *AccessByOffset(defaultValues.data(), s_uniformOffsets.diffuseColor) = Vector4f(1.f, 1.f, 1.f, 1.f); - *AccessByOffset(defaultValues.data(), s_uniformOffsets.alphaThreshold) = 0.2f; + AccessByOffset(defaultValues.data(), s_uniformOffsets.diffuseColor) = Vector4f(1.f, 1.f, 1.f, 1.f); + AccessByOffset(defaultValues.data(), s_uniformOffsets.alphaThreshold) = 0.2f; + + std::vector textures; + s_textureIndexes.alpha = textures.size(); + textures.push_back({ + "MaterialAlphaMap", + "Alpha", + ImageType_2D + }); + + s_textureIndexes.diffuse = textures.size(); + textures.push_back({ + "MaterialDiffuseMap", + "Diffuse", + ImageType_2D + }); + + predefinedBinding[PredefinedShaderBinding_TexOverlay] = textures.size(); + textures.push_back({ + "TextureOverlay", + "Overlay", + ImageType_2D + }); std::vector uniformBlocks; s_uniformBlockIndex = uniformBlocks.size(); uniformBlocks.assign({ { - "BasicSettings", fieldOffsets.GetSize(), + "BasicSettings", "MaterialBasicSettings", std::move(variables), std::move(defaultValues) @@ -157,47 +156,28 @@ namespace Nz std::vector sharedUniformBlock; - predefinedBinding[PredefinedShaderBinding_UboInstanceData] = sharedUniformBlock.size(); + predefinedBinding[PredefinedShaderBinding_UboInstanceData] = textures.size() + uniformBlocks.size() + sharedUniformBlock.size(); sharedUniformBlock.push_back(PredefinedInstanceData::GetUniformBlock()); - predefinedBinding[PredefinedShaderBinding_UboViewerData] = sharedUniformBlock.size(); + predefinedBinding[PredefinedShaderBinding_UboViewerData] = textures.size() + uniformBlocks.size() + sharedUniformBlock.size(); sharedUniformBlock.push_back(PredefinedViewerData::GetUniformBlock()); - std::vector textures; - s_textureIndexes.alpha = textures.size(); - textures.push_back({ - "Alpha", - ImageType_2D, - "MaterialAlphaMap" - }); - - s_textureIndexes.diffuse = textures.size(); - textures.push_back({ - "Diffuse", - ImageType_2D, - "MaterialDiffuseMap" - }); + // Shaders + MaterialSettings::DefaultShaders defaultShaders; + defaultShaders[UnderlyingCast(ShaderStageType::Fragment)] = Graphics::Instance()->GetRenderDevice().InstantiateShaderStage(Nz::ShaderStageType::Fragment, Nz::ShaderLanguage::NazaraBinary, r_fragmentShader, sizeof(r_fragmentShader)); + defaultShaders[UnderlyingCast(ShaderStageType::Vertex)] = Graphics::Instance()->GetRenderDevice().InstantiateShaderStage(Nz::ShaderStageType::Vertex, Nz::ShaderLanguage::NazaraBinary, r_vertexShader, sizeof(r_vertexShader)); - predefinedBinding[PredefinedShaderBinding_TexOverlay] = textures.size(); - textures.push_back({ - "Overlay", - ImageType_2D, - "TextureOverlay" - }); - - s_materialSettings = std::make_shared(std::move(textures), std::move(uniformBlocks), std::move(sharedUniformBlock), predefinedBinding); + s_materialSettings = std::make_shared(std::move(textures), std::move(uniformBlocks), std::move(sharedUniformBlock), predefinedBinding, std::move(defaultShaders)); return true; } void BasicMaterial::Uninitialize() { - s_renderPipelineLayout.Reset(); s_materialSettings.reset(); } std::shared_ptr BasicMaterial::s_materialSettings; std::size_t BasicMaterial::s_uniformBlockIndex; - RenderPipelineLayoutRef BasicMaterial::s_renderPipelineLayout; BasicMaterial::TextureIndexes BasicMaterial::s_textureIndexes; BasicMaterial::UniformOffsets BasicMaterial::s_uniformOffsets; } diff --git a/src/Nazara/Graphics/BasicRenderQueue.cpp b/src/Nazara/Graphics/BasicRenderQueue.cpp deleted file mode 100644 index 88ce8ddbd..000000000 --- a/src/Nazara/Graphics/BasicRenderQueue.cpp +++ /dev/null @@ -1,956 +0,0 @@ -// Copyright (C) 2017 Jérôme Leclercq -// This file is part of the "Nazara Engine - Graphics module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include -#include -#include - -///TODO: Replace sinus/cosinus by a lookup table (which will lead to a speed up about 10x) - -namespace Nz -{ - /*! - * \ingroup graphics - * \class Nz::BasicRenderQueue - * \brief Graphics class that represents a simple rendering queue - */ - - /*! - * \brief Adds multiple billboards to the queue - * - * \param renderOrder Order of rendering - * \param material Material of the billboards - * \param count Number of billboards - * \param positionPtr Position of the billboards - * \param sizePtr Sizes of the billboards - * \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used - * \param colorPtr Color of the billboards if null, Color::White is used - * - * \remark Produces a NazaraAssert if material is invalid - */ - - void BasicRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr positionPtr, SparsePtr sizePtr, SparsePtr sinCosPtr, SparsePtr colorPtr) - { - NazaraAssert(material, "Invalid material"); - - RegisterLayer(renderOrder); - - Vector2f defaultSinCos(0.f, 1.f); // sin(0) = 0, cos(0) = 1 - - if (!sinCosPtr) - sinCosPtr.Reset(&defaultSinCos, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile - - if (!colorPtr) - colorPtr.Reset(&Color::White, 0); // Same - - if (material->IsDepthSortingEnabled()) - { - for (std::size_t i = 0; i < billboardCount; ++i) - { - depthSortedBillboards.Insert({ - renderOrder, - material, - scissorRect, - { - *colorPtr++, - *positionPtr++, - *sizePtr++, - *sinCosPtr++ - } - }); - } - } - else - { - std::size_t billboardIndex = m_billboards.size(); - m_billboards.resize(billboardIndex + billboardCount); - BillboardData* data = &m_billboards[billboardIndex]; - - for (std::size_t i = 0; i < billboardCount; ++i) - { - data->center = *positionPtr++; - data->color = *colorPtr++; - data->sinCos = *sinCosPtr++; - data->size = *sizePtr++; - data++; - } - - billboards.Insert({ - renderOrder, - material, - scissorRect, - billboardCount, - billboardIndex - }); - } - } - - /*! - * \brief Adds multiple billboards to the queue - * - * \param renderOrder Order of rendering - * \param material Material of the billboards - * \param count Number of billboards - * \param positionPtr Position of the billboards - * \param sizePtr Sizes of the billboards - * \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used - * \param alphaPtr Alpha parameters of the billboards if null, 1.f is used - * - * \remark Produces a NazaraAssert if material is invalid - */ - - void BasicRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr positionPtr, SparsePtr sizePtr, SparsePtr sinCosPtr, SparsePtr alphaPtr) - { - NazaraAssert(material, "Invalid material"); - - RegisterLayer(renderOrder); - - Vector2f defaultSinCos(0.f, 1.f); // sin(0) = 0, cos(0) = 1 - - if (!sinCosPtr) - sinCosPtr.Reset(&defaultSinCos, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile - - float defaultAlpha = 1.f; - - if (!alphaPtr) - alphaPtr.Reset(&defaultAlpha, 0); // Same - - if (material->IsDepthSortingEnabled()) - { - for (std::size_t i = 0; i < billboardCount; ++i) - { - depthSortedBillboards.Insert({ - renderOrder, - material, - scissorRect, - { - ComputeColor(*alphaPtr++), - *positionPtr++, - *sizePtr++, - *sinCosPtr++ - } - }); - } - } - else - { - std::size_t billboardIndex = m_billboards.size(); - m_billboards.resize(billboardIndex + billboardCount); - BillboardData* data = &m_billboards[billboardIndex]; - - for (std::size_t i = 0; i < billboardCount; ++i) - { - data->center = *positionPtr++; - data->color = ComputeColor(*alphaPtr++); - data->sinCos = *sinCosPtr++; - data->size = *sizePtr++; - data++; - } - - billboards.Insert({ - renderOrder, - material, - scissorRect, - billboardCount, - billboardIndex - }); - } - } - - /*! - * \brief Adds multiple billboards to the queue - * - * \param renderOrder Order of rendering - * \param material Material of the billboards - * \param count Number of billboards - * \param positionPtr Position of the billboards - * \param sizePtr Sizes of the billboards - * \param anglePtr Rotation of the billboards if null, 0.f is used - * \param colorPtr Color of the billboards if null, Color::White is used - * - * \remark Produces a NazaraAssert if material is invalid - */ - - void BasicRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr positionPtr, SparsePtr sizePtr, SparsePtr anglePtr, SparsePtr colorPtr) - { - NazaraAssert(material, "Invalid material"); - - RegisterLayer(renderOrder); - - float defaultRotation = 0.f; - - if (!anglePtr) - anglePtr.Reset(&defaultRotation, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile - - if (!colorPtr) - colorPtr.Reset(&Color::White, 0); // Same - - if (material->IsDepthSortingEnabled()) - { - for (std::size_t i = 0; i < billboardCount; ++i) - { - depthSortedBillboards.Insert({ - renderOrder, - material, - scissorRect, - { - *colorPtr++, - *positionPtr++, - *sizePtr++, - ComputeSinCos(*anglePtr++) - } - }); - } - } - else - { - std::size_t billboardIndex = m_billboards.size(); - m_billboards.resize(billboardIndex + billboardCount); - BillboardData* data = &m_billboards[billboardIndex]; - - for (std::size_t i = 0; i < billboardCount; ++i) - { - data->center = *positionPtr++; - data->color = *colorPtr++; - data->sinCos = ComputeSinCos(*anglePtr++); - data->size = *sizePtr++; - data++; - } - - billboards.Insert({ - renderOrder, - material, - scissorRect, - billboardCount, - billboardIndex - }); - } - } - - /*! - * \brief Adds multiple billboards to the queue - * - * \param renderOrder Order of rendering - * \param material Material of the billboards - * \param count Number of billboards - * \param positionPtr Position of the billboards - * \param sizePtr Sizes of the billboards - * \param anglePtr Rotation of the billboards if null, 0.f is used - * \param alphaPtr Alpha parameters of the billboards if null, 1.f is used - * - * \remark Produces a NazaraAssert if material is invalid - */ - - void BasicRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr positionPtr, SparsePtr sizePtr, SparsePtr anglePtr, SparsePtr alphaPtr) - { - NazaraAssert(material, "Invalid material"); - - RegisterLayer(renderOrder); - - float defaultRotation = 0.f; - - if (!anglePtr) - anglePtr.Reset(&defaultRotation, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile - - float defaultAlpha = 1.f; - - if (!alphaPtr) - alphaPtr.Reset(&defaultAlpha, 0); // Same - - if (material->IsDepthSortingEnabled()) - { - for (std::size_t i = 0; i < billboardCount; ++i) - { - depthSortedBillboards.Insert({ - renderOrder, - material, - scissorRect, - { - ComputeColor(*alphaPtr++), - *positionPtr++, - *sizePtr++, - ComputeSinCos(*anglePtr++) - } - }); - } - } - else - { - std::size_t billboardIndex = m_billboards.size(); - m_billboards.resize(billboardIndex + billboardCount); - BillboardData* data = &m_billboards[billboardIndex]; - - for (std::size_t i = 0; i < billboardCount; ++i) - { - data->center = *positionPtr++; - data->color = ComputeColor(*alphaPtr++); - data->sinCos = ComputeSinCos(*anglePtr++); - data->size = *sizePtr++; - data++; - } - - billboards.Insert({ - renderOrder, - material, - scissorRect, - billboardCount, - billboardIndex - }); - } - } - - /*! - * \brief Adds multiple billboards to the queue - * - * \param renderOrder Order of rendering - * \param material Material of the billboards - * \param count Number of billboards - * \param positionPtr Position of the billboards - * \param sizePtr Size of the billboards - * \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used - * \param colorPtr Color of the billboards if null, Color::White is used - * - * \remark Produces a NazaraAssert if material is invalid - */ - - void BasicRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr positionPtr, SparsePtr sizePtr, SparsePtr sinCosPtr, SparsePtr colorPtr) - { - NazaraAssert(material, "Invalid material"); - - RegisterLayer(renderOrder); - - Vector2f defaultSinCos(0.f, 1.f); // sin(0) = 0, cos(0) = 1 - - if (!sinCosPtr) - sinCosPtr.Reset(&defaultSinCos, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile - - if (!colorPtr) - colorPtr.Reset(&Color::White, 0); // Same - - if (material->IsDepthSortingEnabled()) - { - for (std::size_t i = 0; i < billboardCount; ++i) - { - depthSortedBillboards.Insert({ - renderOrder, - material, - scissorRect, - { - *colorPtr++, - *positionPtr++, - ComputeSize(*sizePtr++), - *sinCosPtr++ - } - }); - } - } - else - { - std::size_t billboardIndex = m_billboards.size(); - m_billboards.resize(billboardIndex + billboardCount); - BillboardData* data = &m_billboards[billboardIndex]; - - for (std::size_t i = 0; i < billboardCount; ++i) - { - data->center = *positionPtr++; - data->color = *colorPtr++; - data->sinCos = *sinCosPtr++; - data->size = ComputeSize(*sizePtr++); - data++; - } - - billboards.Insert({ - renderOrder, - material, - scissorRect, - billboardCount, - billboardIndex - }); - } - } - - /*! - * \brief Adds multiple billboards to the queue - * - * \param renderOrder Order of rendering - * \param material Material of the billboards - * \param count Number of billboards - * \param positionPtr Position of the billboards - * \param sizePtr Size of the billboards - * \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used - * \param alphaPtr Alpha parameters of the billboards if null, 1.f is used - * - * \remark Produces a NazaraAssert if material is invalid - */ - - void BasicRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr positionPtr, SparsePtr sizePtr, SparsePtr sinCosPtr, SparsePtr alphaPtr) - { - NazaraAssert(material, "Invalid material"); - - RegisterLayer(renderOrder); - - Vector2f defaultSinCos(0.f, 1.f); // sin(0) = 0, cos(0) = 1 - - if (!sinCosPtr) - sinCosPtr.Reset(&defaultSinCos, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile - - float defaultAlpha = 1.f; - - if (!alphaPtr) - alphaPtr.Reset(&defaultAlpha, 0); // Same - - if (material->IsDepthSortingEnabled()) - { - for (std::size_t i = 0; i < billboardCount; ++i) - { - depthSortedBillboards.Insert({ - renderOrder, - material, - scissorRect, - { - ComputeColor(*alphaPtr++), - *positionPtr++, - ComputeSize(*sizePtr++), - *sinCosPtr++ - } - }); - } - } - else - { - std::size_t billboardIndex = m_billboards.size(); - m_billboards.resize(billboardIndex + billboardCount); - BillboardData* data = &m_billboards[billboardIndex]; - - for (std::size_t i = 0; i < billboardCount; ++i) - { - data->center = *positionPtr++; - data->color = ComputeColor(*alphaPtr++); - data->sinCos = *sinCosPtr++; - data->size = ComputeSize(*sizePtr++); - data++; - } - - billboards.Insert({ - renderOrder, - material, - scissorRect, - billboardCount, - billboardIndex - }); - } - } - - /*! - * \brief Adds multiple billboards to the queue - * - * \param renderOrder Order of rendering - * \param material Material of the billboards - * \param count Number of billboards - * \param positionPtr Position of the billboards - * \param sizePtr Size of the billboards - * \param anglePtr Rotation of the billboards if null, 0.f is used - * \param colorPtr Color of the billboards if null, Color::White is used - * - * \remark Produces a NazaraAssert if material is invalid - */ - - void BasicRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr positionPtr, SparsePtr sizePtr, SparsePtr anglePtr, SparsePtr colorPtr) - { - NazaraAssert(material, "Invalid material"); - - RegisterLayer(renderOrder); - - float defaultRotation = 0.f; - - if (!anglePtr) - anglePtr.Reset(&defaultRotation, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile - - if (!colorPtr) - colorPtr.Reset(&Color::White, 0); // Same - - if (material->IsDepthSortingEnabled()) - { - for (std::size_t i = 0; i < billboardCount; ++i) - { - depthSortedBillboards.Insert({ - renderOrder, - material, - scissorRect, - { - *colorPtr++, - *positionPtr++, - ComputeSize(*sizePtr++), - ComputeSinCos(*anglePtr++) - } - }); - } - } - else - { - std::size_t billboardIndex = m_billboards.size(); - m_billboards.resize(billboardIndex + billboardCount); - BillboardData* data = &m_billboards[billboardIndex]; - - for (std::size_t i = 0; i < billboardCount; ++i) - { - data->center = *positionPtr++; - data->color = *colorPtr++; - data->sinCos = ComputeSinCos(*anglePtr++); - data->size = ComputeSize(*sizePtr++); - data++; - } - - billboards.Insert({ - renderOrder, - material, - scissorRect, - billboardCount, - billboardIndex - }); - } - } - - /*! - * \brief Adds multiple billboards to the queue - * - * \param renderOrder Order of rendering - * \param material Material of the billboards - * \param count Number of billboards - * \param positionPtr Position of the billboards - * \param sizePtr Size of the billboards - * \param anglePtr Rotation of the billboards if null, 0.f is used - * \param alphaPtr Alpha parameters of the billboards if null, 1.f is used - * - * \remark Produces a NazaraAssert if material is invalid - */ - - void BasicRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr positionPtr, SparsePtr sizePtr, SparsePtr anglePtr, SparsePtr alphaPtr) - { - NazaraAssert(material, "Invalid material"); - - RegisterLayer(renderOrder); - - float defaultRotation = 0.f; - - if (!anglePtr) - anglePtr.Reset(&defaultRotation, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile - - float defaultAlpha = 1.f; - - if (!alphaPtr) - alphaPtr.Reset(&defaultAlpha, 0); // Same - - if (material->IsDepthSortingEnabled()) - { - for (std::size_t i = 0; i < billboardCount; ++i) - { - depthSortedBillboards.Insert({ - renderOrder, - material, - scissorRect, - { - ComputeColor(*alphaPtr++), - *positionPtr++, - ComputeSize(*sizePtr++), - ComputeSinCos(*anglePtr++) - } - }); - } - } - else - { - std::size_t billboardIndex = m_billboards.size(); - m_billboards.resize(billboardIndex + billboardCount); - BillboardData* data = &m_billboards[billboardIndex]; - - for (std::size_t i = 0; i < billboardCount; ++i) - { - data->center = *positionPtr++; - data->color = ComputeColor(*alphaPtr++); - data->sinCos = ComputeSinCos(*anglePtr++); - data->size = ComputeSize(*sizePtr++); - data++; - } - - billboards.Insert({ - renderOrder, - material, - scissorRect, - billboardCount, - billboardIndex - }); - } - } - - /*! - * \brief Adds drawable to the queue - * - * \param renderOrder Order of rendering - * \param drawable Drawable user defined - * - * \remark Produces a NazaraError if drawable is invalid - */ - void BasicRenderQueue::AddDrawable(int renderOrder, const Drawable* drawable) - { - NazaraAssert(drawable, "Invalid material"); - - RegisterLayer(renderOrder); - - customDrawables.Insert({ - renderOrder, - drawable - }); - } - - /*! - * \brief Adds mesh to the queue - * - * \param renderOrder Order of rendering - * \param material Material of the mesh - * \param meshData Data of the mesh - * \param meshAABB Box of the mesh - * \param transformMatrix Matrix of the mesh - * - * \remark Produces a NazaraAssert if material is invalid - */ - void BasicRenderQueue::AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Nz::Matrix4f& transformMatrix, std::size_t instanceIndex, const Recti& scissorRect) - { - NazaraAssert(material, "Invalid material"); - - RegisterLayer(renderOrder); - - Spheref obbSphere(transformMatrix.GetTranslation() + meshAABB.GetCenter(), meshAABB.GetSquaredRadius()); - - if (material->IsDepthSortingEnabled()) - { - depthSortedModels.Insert({ - renderOrder, - instanceIndex, - meshData, - material, - scissorRect, - obbSphere - }); - } - else - { - models.Insert({ - renderOrder, - instanceIndex, - meshData, - material, - scissorRect, - obbSphere - }); - } - } - - /*! - * \brief Adds sprites to the queue - * - * \param renderOrder Order of rendering - * \param material Material of the sprites - * \param vertices Buffer of data for the sprites - * \param spriteCount Number of sprites - * \param overlay Texture of the sprites - * - * \remark Produces a NazaraAssert if material is invalid - */ - void BasicRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Recti& scissorRect, const Texture* overlay /*= nullptr*/) - { - NazaraAssert(material, "Invalid material"); - - RegisterLayer(renderOrder); - - if (material->IsDepthSortingEnabled()) - { - depthSortedSprites.Insert({ - renderOrder, - spriteCount, - material, - overlay, - vertices, - scissorRect - }); - } - else - { - basicSprites.Insert({ - renderOrder, - spriteCount, - material, - overlay, - vertices, - scissorRect - }); - } - } - - /*! - * \brief Clears the queue - * - * \param fully Should everything be cleared or we can keep layers - */ - - void BasicRenderQueue::Clear(bool fully) - { - AbstractRenderQueue::Clear(fully); - - basicSprites.Clear(); - billboards.Clear(); - depthSortedBillboards.Clear(); - depthSortedModels.Clear(); - depthSortedSprites.Clear(); - models.Clear(); - - m_pipelineCache.clear(); - m_materialCache.clear(); - m_overlayCache.clear(); - m_shaderCache.clear(); - m_textureCache.clear(); - m_vertexBufferCache.clear(); - - m_billboards.clear(); - m_renderLayers.clear(); - } - - /*! - * \brief Sorts the object according to the viewer position, furthest to nearest - * - * \param viewer Viewer of the scene - */ - void BasicRenderQueue::Sort(const AbstractViewer* viewer) - { - m_layerCache.clear(); - for (int layer : m_renderLayers) - m_layerCache.emplace(layer, m_layerCache.size()); - - auto GetOrInsert = [](auto& container, auto&& value) - { - auto it = container.find(value); - if (it == container.end()) - it = container.emplace(value, container.size()).first; - - return it->second; - }; - - basicSprites.Sort([&](const SpriteChain& vertices) - { - // RQ index: - // - Layer (16bits) - // - Pipeline (8bits) - // - Material (8bits) - // - Shader? (8bits) - // - Textures (8bits) - // - Overlay (8bits) - // - Scissor (4bits) - // - ??? (4bits) - - UInt64 layerIndex = m_layerCache[vertices.layerIndex]; - UInt64 pipelineIndex = GetOrInsert(m_pipelineCache, vertices.material->GetPipeline()); - UInt64 materialIndex = GetOrInsert(m_materialCache, vertices.material); - UInt64 shaderIndex = GetOrInsert(m_shaderCache, vertices.material->GetShader()); - UInt64 textureIndex = 0;/* GetOrInsert(m_textureCache, vertices.material->GetDiffuseMap());*/ - UInt64 overlayIndex = GetOrInsert(m_overlayCache, vertices.overlay); - UInt64 scissorIndex = 0; //< TODO - - UInt64 index = (layerIndex & 0xFFFF) << 48 | - (pipelineIndex & 0xFF) << 40 | - (materialIndex & 0xFF) << 32 | - (shaderIndex & 0xFF) << 24 | - (textureIndex & 0xFF) << 16 | - (overlayIndex & 0xFF) << 8 | - (scissorIndex & 0x0F) << 4; - - return index; - }); - - billboards.Sort([&](const BillboardChain& billboard) - { - // RQ index: - // - Layer (16bits) - // - Pipeline (8bits) - // - Material (8bits) - // - Shader? (8bits) - // - Textures (8bits) - // - Scissor (4bits) - // - ??? (12bits) - - UInt64 layerIndex = m_layerCache[billboard.layerIndex]; - UInt64 pipelineIndex = GetOrInsert(m_pipelineCache, billboard.material->GetPipeline()); - UInt64 materialIndex = GetOrInsert(m_materialCache, billboard.material); - UInt64 shaderIndex = GetOrInsert(m_shaderCache, billboard.material->GetShader()); - UInt64 textureIndex = 0; /*GetOrInsert(m_textureCache, billboard.material->GetDiffuseMap())*/; - UInt64 unknownIndex = 0; //< ??? - UInt64 scissorIndex = 0; //< TODO - - UInt64 index = (layerIndex & 0xFFFF) << 48 | - (pipelineIndex & 0xFF) << 40 | - (materialIndex & 0xFF) << 32 | - (shaderIndex & 0xFF) << 24 | - (textureIndex & 0xFF) << 16 | - (scissorIndex & 0x0F) << 12 | - (unknownIndex & 0xFF) << 0; - - return index; - }); - - customDrawables.Sort([&](const CustomDrawable& drawable) - { - // RQ index: - // - Layer (16bits) - - UInt64 layerIndex = m_layerCache[drawable.layerIndex]; - - UInt64 index = (layerIndex & 0xFFFF) << 48; - - return index; - - }); - - models.Sort([&](const Model& renderData) - { - // RQ index: - // - Layer (16bits) - // - Pipeline (8bits) - // - Material (8bits) - // - Shader? (8bits) - // - Textures (8bits) - // - Buffers (8bits) - // - Scissor (4bits) - // - ??? (4bits) - - UInt64 layerIndex = m_layerCache[renderData.layerIndex]; - UInt64 pipelineIndex = GetOrInsert(m_pipelineCache, renderData.material->GetPipeline()); - UInt64 materialIndex = GetOrInsert(m_materialCache, renderData.material); - UInt64 shaderIndex = GetOrInsert(m_shaderCache, renderData.material->GetShader()); - UInt64 textureIndex = 0;/* GetOrInsert(m_textureCache, renderData.material->GetDiffuseMap()) */; - UInt64 bufferIndex = GetOrInsert(m_vertexBufferCache, renderData.meshData.vertexBuffer); - UInt64 scissorIndex = 0; //< TODO - UInt64 depthIndex = 0; //< TODO - - UInt64 index = (layerIndex & 0xFFFF) << 48 | - (pipelineIndex & 0xFF) << 40 | - (materialIndex & 0xFF) << 32 | - (shaderIndex & 0xFF) << 24 | - (textureIndex & 0xFF) << 16 | - (bufferIndex & 0xFF) << 8 | - (scissorIndex & 0x0F) << 4; - - return index; - }); - - static_assert(std::numeric_limits::is_iec559, "The following sorting functions relies on IEEE 754 floatings-points"); - -#if defined(arm) && \ - ((defined(__MAVERICK__) && defined(NAZARA_BIG_ENDIAN)) || \ - (!defined(__SOFTFP__) && !defined(__VFP_FP__) && !defined(__MAVERICK__))) - #error The following code relies on native-endian IEEE-754 representation, which your platform does not guarantee -#endif - - Planef nearPlane = viewer->GetFrustum().GetPlane(FrustumPlane_Near); - - depthSortedBillboards.Sort([&](const Billboard& billboard) - { - // RQ index: - // - Layer (16bits) - // - Depth (32bits) - // - ?? (16bits) - - // Reinterpret depth as UInt32 (this will work as long as they're all either positive or negative, - // a negative distance may happen with billboard behind the camera which we don't care about since they'll not be rendered) - float depth = nearPlane.Distance(billboard.data.center); - - UInt64 layerIndex = m_layerCache[billboard.layerIndex]; - UInt64 depthIndex = ~reinterpret_cast(depth); - - UInt64 index = (layerIndex & 0xFFFF) << 48 | - (depthIndex & 0xFFFFFFFF) << 16; - - return index; - }); - - if (viewer->GetProjectionType() == ProjectionType_Orthogonal) - { - depthSortedModels.Sort([&](const Model& model) - { - // RQ index: - // - Layer (16bits) - // - Depth (32bits) - // - ?? (16bits) - - float depth = nearPlane.Distance(model.obbSphere.GetPosition()); - - UInt64 layerIndex = m_layerCache[model.layerIndex]; - UInt64 depthIndex = ~reinterpret_cast(depth); - - UInt64 index = (layerIndex & 0xFFFF) << 48 | - (depthIndex & 0xFFFFFFFF) << 16; - - return index; - }); - - depthSortedSprites.Sort([&](const SpriteChain& spriteChain) - { - // RQ index: - // - Layer (16bits) - // - Depth (32bits) - // - ?? (16bits) - - float depth = nearPlane.Distance(spriteChain.vertices[0].position); - - UInt64 layerIndex = m_layerCache[spriteChain.layerIndex]; - UInt64 depthIndex = ~reinterpret_cast(depth); - - UInt64 index = (layerIndex & 0xFFFF) << 48 | - (depthIndex & 0xFFFFFFFF) << 16; - - return index; - }); - } - else - { - Vector3f viewerPos = viewer->GetEyePosition(); - - depthSortedModels.Sort([&](const Model& model) - { - // RQ index: - // - Layer (16bits) - // - Depth (32bits) - // - ?? (16bits) - - float depth = viewerPos.SquaredDistance(model.obbSphere.GetPosition()); - - UInt64 layerIndex = m_layerCache[model.layerIndex]; - UInt64 depthIndex = ~reinterpret_cast(depth); - - UInt64 index = (layerIndex & 0x0F) << 48 | - (depthIndex & 0xFFFFFFFF) << 16; - - return index; - }); - - depthSortedSprites.Sort([&](const SpriteChain& sprites) - { - // RQ index: - // - Layer (16bits) - // - Depth (32bits) - // - ?? (16bits) - - float depth = viewerPos.SquaredDistance(sprites.vertices[0].position); - - UInt64 layerIndex = m_layerCache[sprites.layerIndex]; - UInt64 depthIndex = ~reinterpret_cast(depth); - - UInt64 index = (layerIndex & 0xFFFF) << 48 | - (depthIndex & 0xFFFFFFFF) << 16; - - return index; - }); - } - } -} diff --git a/src/Nazara/Graphics/Graphics.cpp b/src/Nazara/Graphics/Graphics.cpp index 0ae24e7c6..05d56f911 100644 --- a/src/Nazara/Graphics/Graphics.cpp +++ b/src/Nazara/Graphics/Graphics.cpp @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include #include @@ -11,9 +12,8 @@ namespace Nz /*! * \ingroup graphics * \class Nz::Graphics - * \brief Audio class that represents the module initializer of Graphics + * \brief Graphics class that represents the module initializer of Graphics */ - Graphics::Graphics(Config config) : ModuleBase("Graphics", this) { @@ -37,6 +37,13 @@ namespace Nz m_renderDevice = rendererImpl->InstanciateRenderDevice(bestRenderDeviceIndex); if (!m_renderDevice) throw std::runtime_error("failed to instantiate render device"); + + MaterialPipeline::Initialize(); + } + + Graphics::~Graphics() + { + MaterialPipeline::Uninitialize(); } Graphics* Graphics::s_instance = nullptr; diff --git a/src/Nazara/Graphics/Material.cpp b/src/Nazara/Graphics/Material.cpp index 8b8fafaf5..952402cb5 100644 --- a/src/Nazara/Graphics/Material.cpp +++ b/src/Nazara/Graphics/Material.cpp @@ -17,18 +17,6 @@ namespace Nz * \brief Graphics class that represents a material */ - /*! - * \brief Checks whether the parameters for the material are correct - * \return true If parameters are valid - */ - bool MaterialParams::IsValid() const - { - if (!UberShaderLibrary::Has(shaderName)) - return false; - - return true; - } - /*! * \brief Constructs a Material object with default states * @@ -36,13 +24,11 @@ namespace Nz */ Material::Material(std::shared_ptr settings) : m_settings(std::move(settings)), - m_reflectionMode(ReflectionMode_Skybox), m_pipelineUpdated(false), - m_shadowCastingEnabled(true), - m_reflectionSize(256) + m_shadowCastingEnabled(true) { m_pipelineInfo.settings = m_settings; - SetShader("Basic"); + m_pipelineInfo.shaders = m_settings->GetDefaultShaders(); m_textures.resize(m_settings->GetTextures().size()); @@ -56,432 +42,4 @@ namespace Nz m_uniformBuffers.emplace_back(std::move(ubo)); } } - - /*! - * \brief Applies shader to the material - * - * \param instance Pipeline instance to update - * \param textureUnit Unit for the texture GL_TEXTURE"i" - * \param lastUsedUnit Optional argument to get the last texture unit - */ - void Material::Apply(const MaterialPipeline::Instance& instance) const - { - const Shader* shader = instance.renderPipeline.GetInfo().shader; - - unsigned int bindingIndex = 0; - - for (const MaterialTexture& textureData : m_textures) - { - auto it = instance.bindings.find(bindingIndex++); - assert(it != instance.bindings.end()); - - unsigned int textureIndex = it->second; - - Renderer::SetTexture(textureIndex, textureData.texture); - Renderer::SetTextureSampler(textureIndex, textureData.sampler); - } - - for (const UniformBufferRef& ubo : m_uniformBuffers) - { - auto it = instance.bindings.find(bindingIndex++); - assert(it != instance.bindings.end()); - - unsigned int uniformBufferIndex = it->second; - - Renderer::SetUniformBuffer(uniformBufferIndex, ubo); - } - - /*if (instance.uniforms[MaterialUniform_AlphaThreshold] != -1) - shader->SendFloat(instance.uniforms[MaterialUniform_AlphaThreshold], m_alphaThreshold); - - if (instance.uniforms[MaterialUniform_Ambient] != -1) - shader->SendColor(instance.uniforms[MaterialUniform_Ambient], m_ambientColor); - - if (instance.uniforms[MaterialUniform_Diffuse] != -1) - shader->SendColor(instance.uniforms[MaterialUniform_Diffuse], m_diffuseColor); - - if (instance.uniforms[MaterialUniform_Shininess] != -1) - shader->SendFloat(instance.uniforms[MaterialUniform_Shininess], m_shininess); - - if (instance.uniforms[MaterialUniform_Specular] != -1) - shader->SendColor(instance.uniforms[MaterialUniform_Specular], m_specularColor);*/ - - /*if (m_alphaMap && instance.uniforms[MaterialUniform_AlphaMap] != -1) - { - unsigned int textureUnit = s_textureUnits[TextureMap_Alpha]; - - Renderer::SetTexture(textureUnit, m_alphaMap); - Renderer::SetTextureSampler(textureUnit, m_diffuseSampler); - } - - if (m_diffuseMap && instance.uniforms[MaterialUniform_DiffuseMap] != -1) - { - unsigned int textureUnit = s_textureUnits[TextureMap_Diffuse]; - - Renderer::SetTexture(textureUnit, m_diffuseMap); - Renderer::SetTextureSampler(textureUnit, m_diffuseSampler); - } - - if (m_emissiveMap && instance.uniforms[MaterialUniform_EmissiveMap] != -1) - { - unsigned int textureUnit = s_textureUnits[TextureMap_Emissive]; - - Renderer::SetTexture(textureUnit, m_emissiveMap); - Renderer::SetTextureSampler(textureUnit, m_diffuseSampler); - } - - if (m_heightMap && instance.uniforms[MaterialUniform_HeightMap] != -1) - { - unsigned int textureUnit = s_textureUnits[TextureMap_Height]; - - Renderer::SetTexture(textureUnit, m_heightMap); - Renderer::SetTextureSampler(textureUnit, m_diffuseSampler); - } - - if (m_normalMap && instance.uniforms[MaterialUniform_NormalMap] != -1) - { - unsigned int textureUnit = s_textureUnits[TextureMap_Normal]; - - Renderer::SetTexture(textureUnit, m_normalMap); - Renderer::SetTextureSampler(textureUnit, m_diffuseSampler); - } - - if (m_specularMap && instance.uniforms[MaterialUniform_SpecularMap] != -1) - { - unsigned int textureUnit = s_textureUnits[TextureMap_Specular]; - - Renderer::SetTexture(textureUnit, m_specularMap); - Renderer::SetTextureSampler(textureUnit, m_specularSampler); - }*/ - } - - /*! - * \brief Builds the material from a parameter list - * - * \param matData Data information for the material - * \param matParams Additional parameters for the material - */ - void Material::BuildFromParameters(const ParameterList& matData, const MaterialParams& matParams) - { - Color color; - bool isEnabled; - double dValue; - long long iValue; - String path; - - ErrorFlags errFlags(ErrorFlag_Silent | ErrorFlag_ThrowExceptionDisabled, true); - - /*if (matData.GetDoubleParameter(MaterialData::AlphaThreshold, &dValue)) - SetAlphaThreshold(float(dValue));*/ - - if (matData.GetBooleanParameter(MaterialData::AlphaTest, &isEnabled)) - EnableAlphaTest(isEnabled); - - /*if (matData.GetColorParameter(MaterialData::AmbientColor, &color)) - SetAmbientColor(color);*/ - - if (matData.GetIntegerParameter(MaterialData::CullingSide, &iValue)) - SetFaceCulling(static_cast(iValue)); - - if (matData.GetIntegerParameter(MaterialData::DepthFunc, &iValue)) - SetDepthFunc(static_cast(iValue)); - - if (matData.GetBooleanParameter(MaterialData::DepthSorting, &isEnabled)) - EnableDepthSorting(isEnabled); - - /*if (matData.GetColorParameter(MaterialData::DiffuseColor, &color)) - SetDiffuseColor(color);*/ - - if (matData.GetIntegerParameter(MaterialData::DstBlend, &iValue)) - SetDstBlend(static_cast(iValue)); - - if (matData.GetIntegerParameter(MaterialData::FaceFilling, &iValue)) - SetFaceFilling(static_cast(iValue)); - - if (matData.GetDoubleParameter(MaterialData::LineWidth, &dValue)) - SetLineWidth(float(dValue)); - - if (matData.GetDoubleParameter(MaterialData::PointSize, &dValue)) - SetPointSize(float(dValue)); - - /*if (matData.GetColorParameter(MaterialData::SpecularColor, &color)) - SetSpecularColor(color); - - if (matData.GetDoubleParameter(MaterialData::Shininess, &dValue)) - SetShininess(float(dValue));*/ - - if (matData.GetIntegerParameter(MaterialData::SrcBlend, &iValue)) - SetSrcBlend(static_cast(iValue)); - - // RendererParameter - if (matData.GetBooleanParameter(MaterialData::Blending, &isEnabled)) - EnableBlending(isEnabled); - - if (matData.GetBooleanParameter(MaterialData::ColorWrite, &isEnabled)) - EnableColorWrite(isEnabled); - - if (matData.GetBooleanParameter(MaterialData::DepthBuffer, &isEnabled)) - EnableDepthBuffer(isEnabled); - - if (matData.GetBooleanParameter(MaterialData::DepthWrite, &isEnabled)) - EnableDepthWrite(isEnabled); - - if (matData.GetBooleanParameter(MaterialData::FaceCulling, &isEnabled)) - EnableFaceCulling(isEnabled); - - if (matData.GetBooleanParameter(MaterialData::ScissorTest, &isEnabled)) - EnableScissorTest(isEnabled); - - if (matData.GetBooleanParameter(MaterialData::StencilTest, &isEnabled)) - EnableStencilTest(isEnabled); - - if (matData.GetBooleanParameter(MaterialData::VertexColor, &isEnabled)) - EnableVertexColor(isEnabled); - - // Samplers - /*if (matData.GetIntegerParameter(MaterialData::DiffuseAnisotropyLevel, &iValue)) - m_diffuseSampler.SetAnisotropyLevel(static_cast(iValue)); - - if (matData.GetIntegerParameter(MaterialData::DiffuseFilter, &iValue)) - m_diffuseSampler.SetFilterMode(static_cast(iValue)); - - if (matData.GetIntegerParameter(MaterialData::DiffuseWrap, &iValue)) - m_diffuseSampler.SetWrapMode(static_cast(iValue)); - - if (matData.GetIntegerParameter(MaterialData::SpecularAnisotropyLevel, &iValue)) - m_specularSampler.SetAnisotropyLevel(static_cast(iValue)); - - if (matData.GetIntegerParameter(MaterialData::SpecularFilter, &iValue)) - m_specularSampler.SetFilterMode(static_cast(iValue)); - - if (matData.GetIntegerParameter(MaterialData::SpecularWrap, &iValue)) - m_specularSampler.SetWrapMode(static_cast(iValue));*/ - - // Stencil - if (matData.GetIntegerParameter(MaterialData::StencilCompare, &iValue)) - m_pipelineInfo.stencilCompare.front = static_cast(iValue); - - if (matData.GetIntegerParameter(MaterialData::StencilFail, &iValue)) - m_pipelineInfo.stencilFail.front = static_cast(iValue); - - if (matData.GetIntegerParameter(MaterialData::StencilPass, &iValue)) - m_pipelineInfo.stencilPass.front = static_cast(iValue); - - if (matData.GetIntegerParameter(MaterialData::StencilZFail, &iValue)) - m_pipelineInfo.stencilDepthFail.front = static_cast(iValue); - - if (matData.GetIntegerParameter(MaterialData::StencilMask, &iValue)) - m_pipelineInfo.stencilWriteMask.front = static_cast(iValue); - - if (matData.GetIntegerParameter(MaterialData::StencilReference, &iValue)) - m_pipelineInfo.stencilReference.front = static_cast(iValue); - - // Stencil (back) - if (matData.GetIntegerParameter(MaterialData::BackFaceStencilCompare, &iValue)) - m_pipelineInfo.stencilCompare.back = static_cast(iValue); - - if (matData.GetIntegerParameter(MaterialData::BackFaceStencilFail, &iValue)) - m_pipelineInfo.stencilFail.back = static_cast(iValue); - - if (matData.GetIntegerParameter(MaterialData::BackFaceStencilPass, &iValue)) - m_pipelineInfo.stencilPass.back = static_cast(iValue); - - if (matData.GetIntegerParameter(MaterialData::BackFaceStencilZFail, &iValue)) - m_pipelineInfo.stencilDepthFail.back = static_cast(iValue); - - if (matData.GetIntegerParameter(MaterialData::BackFaceStencilMask, &iValue)) - m_pipelineInfo.stencilWriteMask.back = static_cast(iValue); - - if (matData.GetIntegerParameter(MaterialData::BackFaceStencilReference, &iValue)) - m_pipelineInfo.stencilReference.back = static_cast(iValue); - - InvalidatePipeline(); - - // Textures - /*if (matParams.loadAlphaMap && matData.GetStringParameter(MaterialData::AlphaTexturePath, &path)) - SetAlphaMap(path); - - if (matParams.loadDiffuseMap && matData.GetStringParameter(MaterialData::DiffuseTexturePath, &path)) - SetDiffuseMap(path); - - if (matParams.loadEmissiveMap && matData.GetStringParameter(MaterialData::EmissiveTexturePath, &path)) - SetEmissiveMap(path); - - if (matParams.loadHeightMap && matData.GetStringParameter(MaterialData::HeightTexturePath, &path)) - SetHeightMap(path); - - if (matParams.loadNormalMap && matData.GetStringParameter(MaterialData::NormalTexturePath, &path)) - SetNormalMap(path); - - if (matParams.loadSpecularMap && matData.GetStringParameter(MaterialData::SpecularTexturePath, &path)) - SetSpecularMap(path);*/ - - SetShader(matParams.shaderName); - } - - /*! - * \brief Builds a ParameterList with material data - * - * \param matData Destination parameter list which will receive material data - */ - void Material::SaveToParameters(ParameterList* matData) - { - NazaraAssert(matData, "Invalid ParameterList"); - - matData->SetParameter(MaterialData::AlphaTest, IsAlphaTestEnabled()); - //matData->SetParameter(MaterialData::AlphaThreshold, GetAlphaThreshold()); - //matData->SetParameter(MaterialData::AmbientColor, GetAmbientColor()); - matData->SetParameter(MaterialData::CullingSide, static_cast(GetFaceCulling())); - matData->SetParameter(MaterialData::DepthFunc, static_cast(GetDepthFunc())); - matData->SetParameter(MaterialData::DepthSorting, IsDepthSortingEnabled()); - //matData->SetParameter(MaterialData::DiffuseColor, GetDiffuseColor()); - matData->SetParameter(MaterialData::DstBlend, static_cast(GetDstBlend())); - matData->SetParameter(MaterialData::FaceFilling, static_cast(GetFaceFilling())); - matData->SetParameter(MaterialData::LineWidth, GetLineWidth()); - matData->SetParameter(MaterialData::PointSize, GetPointSize()); - //matData->SetParameter(MaterialData::Shininess, GetShininess()); - //matData->SetParameter(MaterialData::SpecularColor, GetSpecularColor()); - matData->SetParameter(MaterialData::SrcBlend, static_cast(GetSrcBlend())); - - // RendererParameter - matData->SetParameter(MaterialData::Blending, IsBlendingEnabled()); - matData->SetParameter(MaterialData::ColorWrite, IsColorWriteEnabled()); - matData->SetParameter(MaterialData::DepthBuffer, IsDepthBufferEnabled()); - matData->SetParameter(MaterialData::DepthWrite, IsDepthWriteEnabled()); - matData->SetParameter(MaterialData::FaceCulling, IsFaceCullingEnabled()); - matData->SetParameter(MaterialData::ScissorTest, IsScissorTestEnabled()); - matData->SetParameter(MaterialData::StencilTest, IsStencilTestEnabled()); - matData->SetParameter(MaterialData::VertexColor, HasVertexColor()); - - // Samplers - /*matData->SetParameter(MaterialData::DiffuseAnisotropyLevel, static_cast(GetDiffuseSampler().GetAnisotropicLevel())); - matData->SetParameter(MaterialData::DiffuseFilter, static_cast(GetDiffuseSampler().GetFilterMode())); - matData->SetParameter(MaterialData::DiffuseWrap, static_cast(GetDiffuseSampler().GetWrapMode())); - - matData->SetParameter(MaterialData::SpecularAnisotropyLevel, static_cast(GetSpecularSampler().GetAnisotropicLevel())); - matData->SetParameter(MaterialData::SpecularFilter, static_cast(GetSpecularSampler().GetFilterMode())); - matData->SetParameter(MaterialData::SpecularWrap, static_cast(GetSpecularSampler().GetWrapMode()));*/ - - // Stencil - matData->SetParameter(MaterialData::StencilCompare, static_cast(GetPipelineInfo().stencilCompare.front)); - matData->SetParameter(MaterialData::StencilFail, static_cast(GetPipelineInfo().stencilFail.front)); - matData->SetParameter(MaterialData::StencilPass, static_cast(GetPipelineInfo().stencilPass.front)); - matData->SetParameter(MaterialData::StencilZFail, static_cast(GetPipelineInfo().stencilDepthFail.front)); - matData->SetParameter(MaterialData::StencilMask, static_cast(GetPipelineInfo().stencilWriteMask.front)); - matData->SetParameter(MaterialData::StencilReference, static_cast(GetPipelineInfo().stencilReference.front)); - - // Stencil (back) - matData->SetParameter(MaterialData::BackFaceStencilCompare, static_cast(GetPipelineInfo().stencilCompare.back)); - matData->SetParameter(MaterialData::BackFaceStencilFail, static_cast(GetPipelineInfo().stencilFail.back)); - matData->SetParameter(MaterialData::BackFaceStencilPass, static_cast(GetPipelineInfo().stencilPass.back)); - matData->SetParameter(MaterialData::BackFaceStencilZFail, static_cast(GetPipelineInfo().stencilDepthFail.back)); - matData->SetParameter(MaterialData::BackFaceStencilMask, static_cast(GetPipelineInfo().stencilWriteMask.back)); - matData->SetParameter(MaterialData::BackFaceStencilReference, static_cast(GetPipelineInfo().stencilReference.back)); - - // Textures - /*if (HasAlphaMap()) - { - const String& path = GetAlphaMap()->GetFilePath(); - if (!path.IsEmpty()) - matData->SetParameter(MaterialData::AlphaTexturePath, path); - } - - if (HasDiffuseMap()) - { - const String& path = GetDiffuseMap()->GetFilePath(); - if (!path.IsEmpty()) - matData->SetParameter(MaterialData::DiffuseTexturePath, path); - } - - if (HasEmissiveMap()) - { - const String& path = GetEmissiveMap()->GetFilePath(); - if (!path.IsEmpty()) - matData->SetParameter(MaterialData::EmissiveTexturePath, path); - } - - if (HasHeightMap()) - { - const String& path = GetHeightMap()->GetFilePath(); - if (!path.IsEmpty()) - matData->SetParameter(MaterialData::HeightTexturePath, path); - } - - if (HasNormalMap()) - { - const String& path = GetNormalMap()->GetFilePath(); - if (!path.IsEmpty()) - matData->SetParameter(MaterialData::NormalTexturePath, path); - } - - if (HasSpecularMap()) - { - const String& path = GetSpecularMap()->GetFilePath(); - if (!path.IsEmpty()) - matData->SetParameter(MaterialData::SpecularTexturePath, path); - }*/ - } - - /*! - * \brief Initializes the material librairies - * \return true If successful - * - * \remark Produces a NazaraError if the material library failed to be initialized - */ - bool Material::Initialize() - { - if (!MaterialLibrary::Initialize()) - { - NazaraError("Failed to initialise library"); - return false; - } - - if (!MaterialManager::Initialize()) - { - NazaraError("Failed to initialise manager"); - return false; - } - - s_defaultMaterial = New(BasicMaterial::GetSettings()); - s_defaultMaterial->EnableFaceCulling(false); - s_defaultMaterial->SetFaceFilling(FaceFilling_Line); - MaterialLibrary::Register("Default", s_defaultMaterial); - - unsigned int textureUnit = 0; - - s_textureUnits[TextureMap_Diffuse] = textureUnit++; - s_textureUnits[TextureMap_Alpha] = textureUnit++; - s_textureUnits[TextureMap_Specular] = textureUnit++; - s_textureUnits[TextureMap_Normal] = textureUnit++; - s_textureUnits[TextureMap_Emissive] = textureUnit++; - s_textureUnits[TextureMap_Overlay] = textureUnit++; - s_textureUnits[TextureMap_ReflectionCube] = textureUnit++; - s_textureUnits[TextureMap_Height] = textureUnit++; - s_textureUnits[TextureMap_Shadow2D_1] = textureUnit++; - s_textureUnits[TextureMap_ShadowCube_1] = textureUnit++; - s_textureUnits[TextureMap_Shadow2D_2] = textureUnit++; - s_textureUnits[TextureMap_ShadowCube_2] = textureUnit++; - s_textureUnits[TextureMap_Shadow2D_3] = textureUnit++; - s_textureUnits[TextureMap_ShadowCube_3] = textureUnit++; - - return true; - } - - /*! - * \brief Uninitializes the material librairies - */ - void Material::Uninitialize() - { - s_defaultMaterial.Reset(); - - MaterialManager::Uninitialize(); - MaterialLibrary::Uninitialize(); - } - - std::array Material::s_textureUnits; - MaterialLibrary::LibraryMap Material::s_library; - MaterialLoader::LoaderList Material::s_loaders; - MaterialManager::ManagerMap Material::s_managerMap; - MaterialManager::ManagerParams Material::s_managerParameters; - MaterialRef Material::s_defaultMaterial = nullptr; } diff --git a/src/Nazara/Graphics/MaterialPipeline.cpp b/src/Nazara/Graphics/MaterialPipeline.cpp index 7cd4b808c..c22e21d1e 100644 --- a/src/Nazara/Graphics/MaterialPipeline.cpp +++ b/src/Nazara/Graphics/MaterialPipeline.cpp @@ -8,50 +8,11 @@ #include #include #include +#include #include namespace Nz { - namespace - { - const UInt8 r_basicFragmentShader[] = { - #include - }; - - const UInt8 r_basicVertexShader[] = { - #include - }; - - const UInt8 r_phongLightingFragmentShader[] = { - #include - }; - - const UInt8 r_phongLightingVertexShader[] = { - #include - }; - - void OverrideShader(const String& path, String* source) - { - ErrorFlags errFlags(ErrorFlag_Silent | ErrorFlag_ThrowExceptionDisabled); - - File shaderFile(path, Nz::OpenMode_ReadOnly | Nz::OpenMode_Text); - if (shaderFile.IsOpen()) - { - StringStream shaderSource; - - while (!shaderFile.EndOfFile()) - { - shaderSource << shaderFile.ReadLine(); - shaderSource << '\n'; - } - - *source = shaderSource; - - NazaraNotice(path + " will be used to override built-in shader"); - } - } - } - /*! * \ingroup graphics * \class Nz::MaterialPipeline @@ -59,6 +20,41 @@ namespace Nz * \brief Graphics class used to contains all rendering states that are not allowed to change individually on rendering devices */ + /*! + * \brief Retrieve (and generate if required) a pipeline instance using shader flags without applying it + * + * \param flags Shader flags + * + * \return Pipeline instance + */ + const std::shared_ptr& MaterialPipeline::GetRenderPipeline(const std::vector& vertexBuffers) const + { + for (const auto& pipeline : m_renderPipelines) + { + const auto& pipelineInfo = pipeline->GetPipelineInfo(); + + bool isEqual = std::equal(pipelineInfo.vertexBuffers.begin(), pipelineInfo.vertexBuffers.end(), vertexBuffers.begin(), [](const auto& v1, const auto& v2) + { + return v1.binding == v2.binding && v1.declaration == v2.declaration; + }); + + if (isEqual) + return pipeline; + } + + RenderPipelineInfo renderPipelineInfo; + static_cast(renderPipelineInfo).operator=(m_pipelineInfo); // Not my proudest line + + renderPipelineInfo.pipelineLayout = m_pipelineInfo.settings->GetRenderPipelineLayout(); + + for (const auto& shaderStage : m_pipelineInfo.shaders) + { + if (shaderStage) + renderPipelineInfo.shaderStages.push_back(shaderStage); + } + + return m_renderPipelines.emplace_back(Graphics::Instance()->GetRenderDevice().InstantiateRenderPipeline(std::move(renderPipelineInfo))); + } /*! * \brief Returns a reference to a MaterialPipeline built with MaterialPipelineInfo * @@ -66,156 +62,19 @@ namespace Nz * * \param pipelineInfo Pipeline informations used to build/retrieve a MaterialPipeline object */ - MaterialPipelineRef MaterialPipeline::GetPipeline(const MaterialPipelineInfo& pipelineInfo) + const std::shared_ptr& MaterialPipeline::Get(const MaterialPipelineInfo& pipelineInfo) { auto it = s_pipelineCache.find(pipelineInfo); if (it == s_pipelineCache.end()) - it = s_pipelineCache.insert(it, PipelineCache::value_type(pipelineInfo, New(pipelineInfo))); + it = s_pipelineCache.insert(it, PipelineCache::value_type(pipelineInfo, std::make_shared(pipelineInfo, Token{}))); return it->second; } - void MaterialPipeline::GenerateRenderPipeline(UInt32 flags) const - { - NazaraAssert(m_pipelineInfo.settings, "Material pipeline has no settings"); - NazaraAssert(m_pipelineInfo.uberShader, "Material pipeline has no uber shader"); - - const auto& textures = m_pipelineInfo.settings->GetTextures(); - - ParameterList list; - for (std::size_t i = 0, texCount = textures.size(); i < texCount; ++i) - { - const auto& texture = textures[i]; - String parameterName = "HAS_" + texture.name.ToUpper() + "_TEXTURE"; - - list.SetParameter(parameterName, (m_pipelineInfo.textures & (1 << i)) != 0); - } - - list.SetParameter("ALPHA_TEST", m_pipelineInfo.alphaTest); - list.SetParameter("REFLECTION_MAPPING", m_pipelineInfo.reflectionMapping); - list.SetParameter("SHADOW_MAPPING", m_pipelineInfo.shadowReceive); - list.SetParameter("TEXTURE_MAPPING", m_pipelineInfo.textures != 0 || - m_pipelineInfo.reflectionMapping || flags & ShaderFlags_TextureOverlay); - list.SetParameter("TRANSFORM", true); - - list.SetParameter("FLAG_BILLBOARD", static_cast((flags & ShaderFlags_Billboard) != 0)); - list.SetParameter("FLAG_DEFERRED", static_cast((flags & ShaderFlags_Deferred) != 0)); - list.SetParameter("FLAG_INSTANCING", static_cast((flags & ShaderFlags_Instancing) != 0)); - list.SetParameter("FLAG_TEXTUREOVERLAY", static_cast((flags & ShaderFlags_TextureOverlay) != 0)); - list.SetParameter("FLAG_VERTEXCOLOR", m_pipelineInfo.hasVertexColor || static_cast((flags & ShaderFlags_VertexColor) != 0)); - - Instance& instance = m_instances[flags]; - instance.uberInstance = m_pipelineInfo.uberShader->Get(list); - - RenderPipelineInfo renderPipelineInfo; - static_cast(renderPipelineInfo).operator=(m_pipelineInfo); // Not my proudest line - - renderPipelineInfo.shader = instance.uberInstance->GetShader(); - - instance.renderPipeline.Create(renderPipelineInfo); - - // Send texture units (those never changes) - const RenderPipelineLayout* pipelineLayout = m_pipelineInfo.pipelineLayout; - if (!pipelineLayout) - pipelineLayout = m_pipelineInfo.settings->GetRenderPipelineLayout(); - - instance.bindings = renderPipelineInfo.shader->ApplyLayout(pipelineLayout); - - renderPipelineInfo.shader->SendInteger(renderPipelineInfo.shader->GetUniformLocation("ReflectionMap"), Material::GetTextureUnit(TextureMap_ReflectionCube)); - - renderPipelineInfo.shader->SendInteger(renderPipelineInfo.shader->GetUniformLocation("DirectionalSpotLightShadowMap[0]"), Material::GetTextureUnit(TextureMap_Shadow2D_1)); - renderPipelineInfo.shader->SendInteger(renderPipelineInfo.shader->GetUniformLocation("DirectionalSpotLightShadowMap[1]"), Material::GetTextureUnit(TextureMap_Shadow2D_2)); - renderPipelineInfo.shader->SendInteger(renderPipelineInfo.shader->GetUniformLocation("DirectionalSpotLightShadowMap[2]"), Material::GetTextureUnit(TextureMap_Shadow2D_3)); - - renderPipelineInfo.shader->SendInteger(renderPipelineInfo.shader->GetUniformLocation("PointLightShadowMap[0]"), Material::GetTextureUnit(TextureMap_ShadowCube_1)); - renderPipelineInfo.shader->SendInteger(renderPipelineInfo.shader->GetUniformLocation("PointLightShadowMap[1]"), Material::GetTextureUnit(TextureMap_ShadowCube_2)); - renderPipelineInfo.shader->SendInteger(renderPipelineInfo.shader->GetUniformLocation("PointLightShadowMap[2]"), Material::GetTextureUnit(TextureMap_ShadowCube_3)); - } - bool MaterialPipeline::Initialize() { - // Basic shader - { - UberShaderPreprocessorRef uberShader = UberShaderPreprocessor::New(); - - String fragmentShader(reinterpret_cast(r_basicFragmentShader), sizeof(r_basicFragmentShader)); - String vertexShader(reinterpret_cast(r_basicVertexShader), sizeof(r_basicVertexShader)); - - #ifdef NAZARA_DEBUG - OverrideShader("Shaders/Basic/core.frag", &fragmentShader); - OverrideShader("Shaders/Basic/core.vert", &vertexShader); - #endif - - uberShader->SetShader(ShaderStageType_Fragment, fragmentShader, "FLAG_TEXTUREOVERLAY AUTO_TEXCOORDS HAS_ALPHA_TEXTURE HAS_DIFFUSE_TEXTURE TEXTURE_MAPPING"); - uberShader->SetShader(ShaderStageType_Vertex, vertexShader, "FLAG_BILLBOARD FLAG_INSTANCING FLAG_VERTEXCOLOR TEXTURE_MAPPING TRANSFORM UNIFORM_VERTEX_DEPTH"); - - UberShaderLibrary::Register("Basic", uberShader); - } - - if (!BasicMaterial::Initialize()) - { - NazaraError("Failed to initialize phong lighting materials"); - return false; - } - - // PhongLighting shader - { - UberShaderPreprocessorRef uberShader = UberShaderPreprocessor::New(); - - String fragmentShader(reinterpret_cast(r_phongLightingFragmentShader), sizeof(r_phongLightingFragmentShader)); - String vertexShader(reinterpret_cast(r_phongLightingVertexShader), sizeof(r_phongLightingVertexShader)); - - #ifdef NAZARA_DEBUG - OverrideShader("Shaders/PhongLighting/core.frag", &fragmentShader); - OverrideShader("Shaders/PhongLighting/core.vert", &vertexShader); - #endif - - uberShader->SetShader(ShaderStageType_Fragment, fragmentShader, "FLAG_DEFERRED FLAG_TEXTUREOVERLAY ALPHA_TEST AUTO_TEXCOORDS HAS_ALPHA_TEXTURE HAS_DIFFUSE_TEXTURE HAS_EMISSIVE_TEXTURE HAS_NORMAL_TEXTURE HAS_HEIGHT_TEXTURE HAS_SPECULAR_TEXTURE REFLECTION_MAPPING SHADOW_MAPPING"); - uberShader->SetShader(ShaderStageType_Vertex, vertexShader, "FLAG_BILLBOARD FLAG_DEFERRED FLAG_INSTANCING FLAG_VERTEXCOLOR HAS_NORMAL_TEXTURE SHADOW_MAPPING TEXTURE_MAPPING TRANSFORM UNIFORM_VERTEX_DEPTH"); - - UberShaderLibrary::Register("PhongLighting", uberShader); - } - - if (!PhongLightingMaterial::Initialize()) - { - NazaraError("Failed to initialize phong lighting materials"); - return false; - } - - // Once the base shaders are registered, we can now set some default materials - MaterialPipelineInfo pipelineInfo; - pipelineInfo.settings = BasicMaterial::GetSettings(); - pipelineInfo.uberShader = UberShaderLibrary::Get("Basic"); - - // Basic 2D - No depth write/face culling with scissoring - pipelineInfo.depthWrite = false; - pipelineInfo.faceCulling = false; - pipelineInfo.scissorTest = true; - - MaterialPipelineLibrary::Register("Basic2D", GetPipeline(pipelineInfo)); - - // Translucent 2D - Alpha blending with no depth write/face culling and scissoring - pipelineInfo.blending = true; - pipelineInfo.depthWrite = false; - pipelineInfo.faceCulling = false; - pipelineInfo.depthSorting = false; - pipelineInfo.scissorTest = true; - pipelineInfo.dstBlend = BlendFunc_InvSrcAlpha; - pipelineInfo.srcBlend = BlendFunc_SrcAlpha; - - MaterialPipelineLibrary::Register("Translucent2D", GetPipeline(pipelineInfo)); - - // Translucent 3D - Alpha blending with depth buffer and no depth write/face culling - pipelineInfo.blending = true; - pipelineInfo.depthBuffer = true; - pipelineInfo.depthWrite = false; - pipelineInfo.faceCulling = false; - pipelineInfo.depthSorting = true; - pipelineInfo.scissorTest = false; - pipelineInfo.dstBlend = BlendFunc_InvSrcAlpha; - pipelineInfo.srcBlend = BlendFunc_SrcAlpha; - - MaterialPipelineLibrary::Register("Translucent3D", GetPipeline(pipelineInfo)); + BasicMaterial::Initialize(); + PhongLightingMaterial::Initialize(); return true; } @@ -223,13 +82,9 @@ namespace Nz void MaterialPipeline::Uninitialize() { s_pipelineCache.clear(); - UberShaderLibrary::Unregister("PhongLighting"); PhongLightingMaterial::Uninitialize(); - UberShaderLibrary::Unregister("Basic"); BasicMaterial::Uninitialize(); - MaterialPipelineLibrary::Uninitialize(); } - MaterialPipelineLibrary::LibraryMap MaterialPipeline::s_library; MaterialPipeline::PipelineCache MaterialPipeline::s_pipelineCache; } diff --git a/src/Nazara/Graphics/PhongLightingMaterial.cpp b/src/Nazara/Graphics/PhongLightingMaterial.cpp index 53b5a61c1..c08e711d9 100644 --- a/src/Nazara/Graphics/PhongLightingMaterial.cpp +++ b/src/Nazara/Graphics/PhongLightingMaterial.cpp @@ -15,24 +15,11 @@ namespace Nz { - namespace - { - constexpr std::size_t AlphaMapBinding = 0; - constexpr std::size_t DiffuseMapBinding = 1; - constexpr std::size_t EmissiveMapBinding = 2; - constexpr std::size_t HeightMapBinding = 3; - constexpr std::size_t NormalMapBinding = 4; - constexpr std::size_t SpecularMapBinding = 5; - constexpr std::size_t TextureOverlayBinding = 6; - } - - PhongLightingMaterial::PhongLightingMaterial(Material* material) : + PhongLightingMaterial::PhongLightingMaterial(Material& material) : m_material(material) { - NazaraAssert(material, "Invalid material"); - // Most common case: don't fetch texture indexes as a little optimization - const std::shared_ptr& materialSettings = material->GetSettings(); + const std::shared_ptr& materialSettings = m_material.GetSettings(); if (materialSettings == s_materialSettings) { m_textureIndexes = s_textureIndexes; @@ -62,17 +49,17 @@ namespace Nz { NazaraAssert(HasAlphaThreshold(), "Material has no alpha threshold uniform"); - BufferMapper mapper(m_material->GetUniformBuffer(m_phongUniformIndex), BufferAccess_ReadOnly); - return *AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.alphaThreshold); + BufferMapper mapper(m_material.GetUniformBuffer(m_phongUniformIndex), BufferAccess_ReadOnly); + return AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.alphaThreshold); } Color PhongLightingMaterial::GetAmbientColor() const { NazaraAssert(HasAmbientColor(), "Material has no ambient color uniform"); - BufferMapper mapper(m_material->GetUniformBuffer(m_phongUniformIndex), BufferAccess_ReadOnly); + BufferMapper mapper(m_material.GetUniformBuffer(m_phongUniformIndex), BufferAccess_ReadOnly); - const float* colorPtr = AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.ambientColor); + const float* colorPtr = AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.ambientColor); return Color(colorPtr[0] * 255, colorPtr[1] * 255, colorPtr[2] * 255, colorPtr[3] * 255); //< TODO: Make color able to use float } @@ -80,9 +67,9 @@ namespace Nz { NazaraAssert(HasDiffuseColor(), "Material has no diffuse color uniform"); - BufferMapper mapper(m_material->GetUniformBuffer(m_phongUniformIndex), BufferAccess_ReadOnly); + BufferMapper mapper(m_material.GetUniformBuffer(m_phongUniformIndex), BufferAccess_ReadOnly); - const float* colorPtr = AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.diffuseColor); + const float* colorPtr = AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.diffuseColor); return Color(colorPtr[0] * 255, colorPtr[1] * 255, colorPtr[2] * 255, colorPtr[3] * 255); //< TODO: Make color able to use float } @@ -90,17 +77,17 @@ namespace Nz { NazaraAssert(HasShininess(), "Material has no shininess uniform"); - BufferMapper mapper(m_material->GetUniformBuffer(m_phongUniformIndex), BufferAccess_ReadOnly); - return *AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.shininess); + BufferMapper mapper(m_material.GetUniformBuffer(m_phongUniformIndex), BufferAccess_ReadOnly); + return AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.shininess); } Color PhongLightingMaterial::GetSpecularColor() const { NazaraAssert(HasSpecularColor(), "Material has no specular color uniform"); - BufferMapper mapper(m_material->GetUniformBuffer(m_phongUniformIndex), BufferAccess_ReadOnly); + BufferMapper mapper(m_material.GetUniformBuffer(m_phongUniformIndex), BufferAccess_ReadOnly); - const float* colorPtr = AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.specularColor); + const float* colorPtr = AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.specularColor); return Color(colorPtr[0] * 255, colorPtr[1] * 255, colorPtr[2] * 255, colorPtr[3] * 255); //< TODO: Make color able to use float } @@ -108,16 +95,16 @@ namespace Nz { NazaraAssert(HasAlphaThreshold(), "Material has no alpha threshold uniform"); - BufferMapper mapper(m_material->GetUniformBuffer(m_phongUniformIndex), BufferAccess_WriteOnly); - *AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.alphaThreshold) = alphaThreshold; + BufferMapper mapper(m_material.GetUniformBuffer(m_phongUniformIndex), BufferAccess_WriteOnly); + AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.alphaThreshold) = alphaThreshold; } void PhongLightingMaterial::SetAmbientColor(const Color& ambient) { NazaraAssert(HasAmbientColor(), "Material has no ambient color uniform"); - BufferMapper mapper(m_material->GetUniformBuffer(m_phongUniformIndex), BufferAccess_WriteOnly); - float* colorPtr = AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.ambientColor); + BufferMapper mapper(m_material.GetUniformBuffer(m_phongUniformIndex), BufferAccess_WriteOnly); + float* colorPtr = AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.ambientColor); colorPtr[0] = ambient.r / 255.f; colorPtr[1] = ambient.g / 255.f; colorPtr[2] = ambient.b / 255.f; @@ -128,8 +115,8 @@ namespace Nz { NazaraAssert(HasDiffuseColor(), "Material has no diffuse color uniform"); - BufferMapper mapper(m_material->GetUniformBuffer(m_phongUniformIndex), BufferAccess_WriteOnly); - float* colorPtr = AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.diffuseColor); + BufferMapper mapper(m_material.GetUniformBuffer(m_phongUniformIndex), BufferAccess_WriteOnly); + float* colorPtr = AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.diffuseColor); colorPtr[0] = diffuse.r / 255.f; colorPtr[1] = diffuse.g / 255.f; colorPtr[2] = diffuse.b / 255.f; @@ -140,8 +127,8 @@ namespace Nz { NazaraAssert(HasSpecularColor(), "Material has no specular color uniform"); - BufferMapper mapper(m_material->GetUniformBuffer(m_phongUniformIndex), BufferAccess_WriteOnly); - float* colorPtr = AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.specularColor); + BufferMapper mapper(m_material.GetUniformBuffer(m_phongUniformIndex), BufferAccess_WriteOnly); + float* colorPtr = AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.specularColor); colorPtr[0] = diffuse.r / 255.f; colorPtr[1] = diffuse.g / 255.f; colorPtr[2] = diffuse.b / 255.f; @@ -155,51 +142,6 @@ namespace Nz bool PhongLightingMaterial::Initialize() { - RenderPipelineLayoutInfo info; - info.bindings.assign({ - { - "MaterialAlphaMap", - ShaderBindingType_Texture, - ShaderStageType_Fragment, - AlphaMapBinding - }, - { - "MaterialDiffuseMap", - ShaderBindingType_Texture, - ShaderStageType_Fragment, - DiffuseMapBinding - }, - { - "MaterialEmissiveMap", - ShaderBindingType_Texture, - ShaderStageType_Fragment, - EmissiveMapBinding - }, - { - "MaterialHeightMap", - ShaderBindingType_Texture, - ShaderStageType_Fragment, - HeightMapBinding - }, - { - "MaterialNormalMap", - ShaderBindingType_Texture, - ShaderStageType_Fragment, - NormalMapBinding - }, - { - "MaterialSpecularMap", - ShaderBindingType_Texture, - ShaderStageType_Fragment, - SpecularMapBinding - } - }); - - s_renderPipelineLayout = RenderPipelineLayout::New(); - s_renderPipelineLayout->Create(info); - - std::vector uniformBlocks; - // MaterialPhongSettings FieldOffsets phongUniformStruct(StructLayout_Std140); @@ -239,16 +181,18 @@ namespace Nz static_assert(sizeof(Vector4f) == 4 * sizeof(float), "Vector4f is expected to be exactly 4 floats wide"); std::vector defaultValues(phongUniformStruct.GetSize()); - *AccessByOffset(defaultValues.data(), s_phongUniformOffsets.ambientColor) = Vector4f(0.5f, 0.5f, 0.5f, 1.f); - *AccessByOffset(defaultValues.data(), s_phongUniformOffsets.diffuseColor) = Vector4f(1.f, 1.f, 1.f, 1.f); - *AccessByOffset(defaultValues.data(), s_phongUniformOffsets.specularColor) = Vector4f(1.f, 1.f, 1.f, 1.f); - *AccessByOffset(defaultValues.data(), s_phongUniformOffsets.alphaThreshold) = 0.2f; - *AccessByOffset(defaultValues.data(), s_phongUniformOffsets.shininess) = 50.f; + AccessByOffset(defaultValues.data(), s_phongUniformOffsets.ambientColor) = Vector4f(0.5f, 0.5f, 0.5f, 1.f); + AccessByOffset(defaultValues.data(), s_phongUniformOffsets.diffuseColor) = Vector4f(1.f, 1.f, 1.f, 1.f); + AccessByOffset(defaultValues.data(), s_phongUniformOffsets.specularColor) = Vector4f(1.f, 1.f, 1.f, 1.f); + AccessByOffset(defaultValues.data(), s_phongUniformOffsets.alphaThreshold) = 0.2f; + AccessByOffset(defaultValues.data(), s_phongUniformOffsets.shininess) = 50.f; + + std::vector uniformBlocks; s_phongUniformBlockIndex = uniformBlocks.size(); uniformBlocks.push_back({ - "PhongSettings", phongUniformStruct.GetSize(), + "PhongSettings", "MaterialPhongSettings", std::move(phongVariables), std::move(defaultValues) @@ -265,67 +209,65 @@ namespace Nz std::vector textures; s_textureIndexes.alpha = textures.size(); textures.push_back({ + "MaterialAlphaMap", "Alpha", - ImageType_2D, - "MaterialAlphaMap" + ImageType_2D }); s_textureIndexes.diffuse = textures.size(); textures.push_back({ + "MaterialDiffuseMap", "Diffuse", - ImageType_2D, - "MaterialDiffuseMap" + ImageType_2D }); s_textureIndexes.emissive = textures.size(); textures.push_back({ + "MaterialEmissiveMap", "Emissive", - ImageType_2D, - "MaterialEmissiveMap" + ImageType_2D }); s_textureIndexes.height = textures.size(); textures.push_back({ + "MaterialHeightMap", "Height", - ImageType_2D, - "MaterialHeightMap" + ImageType_2D }); s_textureIndexes.normal = textures.size(); textures.push_back({ + "MaterialNormalMap", "Normal", - ImageType_2D, - "MaterialNormalMap" + ImageType_2D }); s_textureIndexes.specular = textures.size(); textures.push_back({ + "MaterialSpecularMap", "Specular", - ImageType_2D, - "MaterialSpecularMap" + ImageType_2D }); predefinedBinding[PredefinedShaderBinding_TexOverlay] = textures.size(); textures.push_back({ + "TextureOverlay", "Overlay", ImageType_2D, - "TextureOverlay" }); - s_materialSettings = std::make_shared(std::move(textures), std::move(uniformBlocks), std::move(sharedUniformBlock), predefinedBinding); + s_materialSettings = std::make_shared(std::move(textures), std::move(uniformBlocks), std::move(sharedUniformBlock), predefinedBinding, MaterialSettings::DefaultShaders{}); return true; } void PhongLightingMaterial::Uninitialize() { - s_renderPipelineLayout.Reset(); s_materialSettings.reset(); } std::shared_ptr PhongLightingMaterial::s_materialSettings; std::size_t PhongLightingMaterial::s_phongUniformBlockIndex; - RenderPipelineLayoutRef PhongLightingMaterial::s_renderPipelineLayout; PhongLightingMaterial::TextureIndexes PhongLightingMaterial::s_textureIndexes; PhongLightingMaterial::PhongUniformOffsets PhongLightingMaterial::s_phongUniformOffsets; } diff --git a/src/Nazara/Graphics/PredefinedShaderStructs.cpp b/src/Nazara/Graphics/PredefinedShaderStructs.cpp index feb8f590b..d8b81a249 100644 --- a/src/Nazara/Graphics/PredefinedShaderStructs.cpp +++ b/src/Nazara/Graphics/PredefinedShaderStructs.cpp @@ -54,7 +54,7 @@ namespace Nz return uniformBlock; } - PredefinedInstanceData PredefinedInstanceData::GetOffset() + PredefinedInstanceData PredefinedInstanceData::GetOffsets() { FieldOffsets viewerStruct(StructLayout_Std140); @@ -69,7 +69,7 @@ namespace Nz MaterialSettings::SharedUniformBlock PredefinedInstanceData::GetUniformBlock() { - PredefinedInstanceData instanceData = GetOffset(); + PredefinedInstanceData instanceData = GetOffsets(); std::vector instanceDataVariables; instanceDataVariables.assign({ @@ -92,7 +92,7 @@ namespace Nz return uniformBlock; } - PredefinedViewerData PredefinedViewerData::GetOffset() + PredefinedViewerData PredefinedViewerData::GetOffsets() { FieldOffsets viewerStruct(StructLayout_Std140); @@ -114,7 +114,7 @@ namespace Nz MaterialSettings::SharedUniformBlock PredefinedViewerData::GetUniformBlock() { - PredefinedViewerData viewerData = GetOffset(); + PredefinedViewerData viewerData = GetOffsets(); std::vector viewerDataVariables; viewerDataVariables.assign({ diff --git a/src/Nazara/Graphics/Resources/Shaders/basicmaterial.frag.shader b/src/Nazara/Graphics/Resources/Shaders/basicmaterial.frag.shader new file mode 100644 index 0000000000000000000000000000000000000000..de1e590c453324d531d93dd1a59942a62bb8cccd GIT binary patch literal 1126 zcmcIkO;5r=5Um1=EhVUb#DjOE5~Bx@0OEO52D+xSWV?L%=loM%O`NywHm$(XO@?LP zy!jsJkDiB)A0|Fo~v&7@JmC&StBW9+N0h z0O6qZ5~o_k0d<8I{D!@^NmMlL39aOopUwqKTgL16eb}8y+K|ePLF_D5@=c+4zZ~EO>Uv?q4^ws4Jiw)1;@Pm&mMo13U}a_i z3a`yH-vpr5-2hU<2Tq6EM@ovwY)Vfo0lHS}Tv>I#F=c`wwa2v8D@CtdcqDd(HJW6q zuP=l|>pTE_d=_-^oCTz2B-%3=>23__f*+n?_{7XE6&|h7y910(HqB0Fr@PY* z#!n+5L@A95@9jtF)ND-NE4_3KlsP&N@n$6_D@$%=;yEKpO{=dKiw{RV6B`Q<0BA`*sdTQ$;(nX)%c1jWzEy^UCPF!W}CNubf3& zmdVrGOowX=t3n5a7coL``Xi z69kWd)lhn1>{`Yr7)O!P6WaHTv5EapLog?Vs-GOB%;1n<@ zMKc(>R9*BXqfl`9f&fE@Rpl)>UEIMyQ#Fq3t_D_^F695O!oAt5zn>;B!+n?l5$wzS PI!4h&>Hb@YpLG2Kx6{2b literal 0 HcmV?d00001 diff --git a/src/Nazara/Graphics/Resources/Shaders/basicmaterial.vert.shader.h b/src/Nazara/Graphics/Resources/Shaders/basicmaterial.vert.shader.h new file mode 100644 index 000000000..3417de538 --- /dev/null +++ b/src/Nazara/Graphics/Resources/Shaders/basicmaterial.vert.shader.h @@ -0,0 +1 @@ +78,83,72,82,0,0,0,1,0,0,0,1,0,0,0,3,0,0,0,13,66,97,115,105,99,83,101,116,116,105,110,103,115,0,0,0,2,0,0,0,14,65,108,112,104,97,84,104,114,101,115,104,111,108,100,0,0,0,0,1,0,0,0,12,68,105,102,102,117,115,101,67,111,108,111,114,0,0,0,0,3,0,0,0,12,73,110,115,116,97,110,99,101,68,97,116,97,0,0,0,2,0,0,0,11,119,111,114,108,100,77,97,116,114,105,120,0,0,0,0,9,0,0,0,14,105,110,118,87,111,114,108,100,77,97,116,114,105,120,0,0,0,0,9,0,0,0,10,86,105,101,119,101,114,68,97,116,97,0,0,0,9,0,0,0,16,112,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,0,0,0,0,9,0,0,0,19,105,110,118,80,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,0,0,0,0,9,0,0,0,10,118,105,101,119,77,97,116,114,105,120,0,0,0,0,9,0,0,0,13,105,110,118,86,105,101,119,77,97,116,114,105,120,0,0,0,0,9,0,0,0,14,118,105,101,119,80,114,111,106,77,97,116,114,105,120,0,0,0,0,9,0,0,0,17,105,110,118,86,105,101,119,80,114,111,106,77,97,116,114,105,120,0,0,0,0,9,0,0,0,16,114,101,110,100,101,114,84,97,114,103,101,116,83,105,122,101,0,0,0,0,2,0,0,0,19,105,110,118,82,101,110,100,101,114,84,97,114,103,101,116,83,105,122,101,0,0,0,0,2,0,0,0,11,101,121,101,80,111,115,105,116,105,111,110,0,0,0,0,3,0,0,0,3,0,0,0,5,105,110,80,111,115,0,0,0,0,3,1,0,0,0,0,0,0,0,9,105,110,78,111,114,109,97,108,115,0,0,0,0,3,1,0,0,0,1,0,0,0,10,105,110,84,101,120,67,111,111,114,100,0,0,0,0,2,1,0,0,0,2,0,0,0,2,0,0,0,10,118,101,114,116,78,111,114,109,97,108,0,0,0,0,3,1,0,0,0,0,0,0,0,6,118,101,114,116,85,86,0,0,0,0,2,1,0,0,0,1,0,0,0,3,0,0,0,10,118,105,101,119,101,114,68,97,116,97,1,0,0,0,10,86,105,101,119,101,114,68,97,116,97,1,0,0,0,5,1,0,0,0,0,0,0,0,12,105,110,115,116,97,110,99,101,68,97,116,97,1,0,0,0,12,73,110,115,116,97,110,99,101,68,97,116,97,1,0,0,0,4,1,0,0,0,0,0,0,0,8,115,101,116,116,105,110,103,115,1,0,0,0,13,66,97,115,105,99,83,101,116,116,105,110,103,115,1,0,0,0,3,1,0,0,0,0,0,0,0,1,0,0,0,4,109,97,105,110,0,0,0,11,0,0,0,0,0,0,0,13,0,0,0,3,0,0,0,8,0,0,0,1,0,0,0,0,0,0,0,9,0,0,0,3,0,0,0,6,118,101,114,116,85,86,0,0,0,0,2,0,0,0,9,0,0,0,1,0,0,0,10,105,110,84,101,120,67,111,111,114,100,0,0,0,0,2,0,0,0,8,0,0,0,1,0,0,0,0,0,0,0,9,0,0,0,3,0,0,0,10,118,101,114,116,78,111,114,109,97,108,0,0,0,0,3,0,0,0,9,0,0,0,1,0,0,0,9,105,110,78,111,114,109,97,108,115,0,0,0,0,3,0,0,0,8,0,0,0,1,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,9,0,0,0,5,0,0,0,10,118,105,101,119,101,114,68,97,116,97,1,0,0,0,10,86,105,101,119,101,114,68,97,116,97,0,0,0,0,9,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,5,0,0,0,10,118,105,101,119,101,114,68,97,116,97,1,0,0,0,10,86,105,101,119,101,114,68,97,116,97,0,0,0,0,9,0,0,0,1,0,0,0,2,0,0,0,0,0,0,0,9,0,0,0,5,0,0,0,12,105,110,115,116,97,110,99,101,68,97,116,97,1,0,0,0,12,73,110,115,116,97,110,99,101,68,97,116,97,0,0,0,0,9,0,0,0,1,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,9,0,0,0,1,0,0,0,5,105,110,80,111,115,0,0,0,0,3,0,0,0,5,0,0,0,1,63,128,0,0,255,255,255,255,255,255,255,255, \ No newline at end of file From a02c300c0c6a9bccb323657e5c71d4c347c142b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 30 Oct 2020 23:08:55 +0100 Subject: [PATCH 010/278] Add GraphicsTest demo --- examples/GraphicsTest/build.lua | 16 ++ examples/GraphicsTest/main.cpp | 395 ++++++++++++++++++++++++++++++++ 2 files changed, 411 insertions(+) create mode 100644 examples/GraphicsTest/build.lua create mode 100644 examples/GraphicsTest/main.cpp diff --git a/examples/GraphicsTest/build.lua b/examples/GraphicsTest/build.lua new file mode 100644 index 000000000..170d65770 --- /dev/null +++ b/examples/GraphicsTest/build.lua @@ -0,0 +1,16 @@ +EXAMPLE.Name = "GraphicsTest" + +EXAMPLE.EnableConsole = true + +EXAMPLE.Files = { + "main.cpp" +} + +EXAMPLE.Libraries = { + "NazaraCore", + "NazaraGraphics", + "NazaraPlatform", + "NazaraRenderer", + "NazaraShader", + "NazaraUtility" +} diff --git a/examples/GraphicsTest/main.cpp b/examples/GraphicsTest/main.cpp new file mode 100644 index 000000000..23f7ca17d --- /dev/null +++ b/examples/GraphicsTest/main.cpp @@ -0,0 +1,395 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main() +{ + Nz::Renderer::Config rendererConfig; + std::cout << "Run using Vulkan? (y/n)" << std::endl; + if (std::getchar() == 'y') + rendererConfig.preferredAPI = Nz::RenderAPI::Vulkan; + else + rendererConfig.preferredAPI = Nz::RenderAPI::OpenGL; + + Nz::Modules nazara(rendererConfig); + + Nz::RenderWindow window; + + Nz::MeshParams meshParams; + meshParams.matrix = Nz::Matrix4f::Rotate(Nz::EulerAnglesf(0.f, 90.f, 180.f)) * Nz::Matrix4f::Scale(Nz::Vector3f(0.002f)); + meshParams.vertexDeclaration = Nz::VertexDeclaration::Get(Nz::VertexLayout_XYZ_Normal_UV); + + std::string windowTitle = "Graphics Test"; + if (!window.Create(Nz::VideoMode(800, 600, 32), windowTitle)) + { + std::cout << "Failed to create Window" << std::endl; + return __LINE__; + } + + std::shared_ptr device = window.GetRenderDevice(); + + /*auto fragmentShader = device->InstantiateShaderStage(Nz::ShaderStageType::Fragment, Nz::ShaderLanguage::NazaraBinary, "frag.shader"); + if (!fragmentShader) + { + std::cout << "Failed to instantiate fragment shader" << std::endl; + return __LINE__; + } + + auto vertexShader = device->InstantiateShaderStage(Nz::ShaderStageType::Vertex, Nz::ShaderLanguage::NazaraBinary, "vert.shader"); + if (!vertexShader) + { + std::cout << "Failed to instantiate fragment shader" << std::endl; + return __LINE__; + }*/ + + Nz::MeshRef drfreak = Nz::Mesh::LoadFromFile("resources/Spaceship/spaceship.obj", meshParams); + if (!drfreak) + { + NazaraError("Failed to load model"); + return __LINE__; + } + + Nz::StaticMesh* drfreakMesh = static_cast(drfreak->GetSubMesh(0)); + + const Nz::VertexBuffer* drfreakVB = drfreakMesh->GetVertexBuffer(); + const Nz::IndexBuffer* drfreakIB = drfreakMesh->GetIndexBuffer(); + + // Index buffer + std::cout << "Index count: " << drfreakIB->GetIndexCount() << std::endl; + + // Vertex buffer + std::cout << "Vertex count: " << drfreakVB->GetVertexCount() << std::endl; + + // Texture + Nz::ImageRef drfreakImage = Nz::Image::LoadFromFile("resources/Spaceship/Texture/diffuse.png"); + if (!drfreakImage || !drfreakImage->Convert(Nz::PixelFormat_RGBA8)) + { + NazaraError("Failed to load image"); + return __LINE__; + } + + Nz::TextureInfo texParams; + texParams.pixelFormat = drfreakImage->GetFormat(); + texParams.type = drfreakImage->GetType(); + texParams.width = drfreakImage->GetWidth(); + texParams.height = drfreakImage->GetHeight(); + texParams.depth = drfreakImage->GetDepth(); + + std::shared_ptr texture = device->InstantiateTexture(texParams); + if (!texture->Update(drfreakImage->GetConstPixels())) + { + NazaraError("Failed to update texture"); + return __LINE__; + } + + std::shared_ptr textureSampler = device->InstantiateTextureSampler({}); + + Nz::Material material(Nz::BasicMaterial::GetSettings()); + //material.SetShader(Nz::ShaderStageType::Fragment, fragmentShader); + //material.SetShader(Nz::ShaderStageType::Vertex, vertexShader); + material.SetTexture(0, texture); + material.SetTextureSampler(0, textureSampler); + + Nz::PredefinedInstanceData instanceUboOffsets = Nz::PredefinedInstanceData::GetOffsets(); + Nz::PredefinedViewerData viewerUboOffsets = Nz::PredefinedViewerData::GetOffsets(); + + std::vector instanceDataBuffer(instanceUboOffsets.totalSize); + std::vector viewerDataBuffer(viewerUboOffsets.totalSize); + + Nz::Vector2ui windowSize = window.GetSize(); + + Nz::AccessByOffset(instanceDataBuffer.data(), instanceUboOffsets.worldMatrixOffset) = Nz::Matrix4f::Translate(Nz::Vector3f::Forward() * 2 + Nz::Vector3f::Right()); + Nz::AccessByOffset(viewerDataBuffer.data(), viewerUboOffsets.viewMatrixOffset) = Nz::Matrix4f::Translate(Nz::Vector3f::Backward() * 1); + Nz::AccessByOffset(viewerDataBuffer.data(), viewerUboOffsets.projMatrixOffset) = Nz::Matrix4f::Perspective(70.f, float(windowSize.x) / windowSize.y, 0.1f, 1000.f); + + Nz::RenderPipelineLayoutInfo pipelineLayoutInfo; + { + auto& uboBinding = pipelineLayoutInfo.bindings.emplace_back(); + uboBinding.index = 0; + uboBinding.shaderStageFlags = Nz::ShaderStageType::Vertex; + uboBinding.type = Nz::ShaderBindingType::UniformBuffer; + } + + { + auto& uboBinding = pipelineLayoutInfo.bindings.emplace_back(); + uboBinding.index = 1; + uboBinding.shaderStageFlags = Nz::ShaderStageType::Vertex; + uboBinding.type = Nz::ShaderBindingType::UniformBuffer; + } + + { + auto& textureBinding = pipelineLayoutInfo.bindings.emplace_back(); + textureBinding.index = 2; + textureBinding.shaderStageFlags = Nz::ShaderStageType::Fragment; + textureBinding.type = Nz::ShaderBindingType::Texture; + } + + //std::shared_ptr renderPipelineLayout = device->InstantiateRenderPipelineLayout(std::move(pipelineLayoutInfo)); + std::shared_ptr renderPipelineLayout = material.GetSettings()->GetRenderPipelineLayout(); + + Nz::ShaderBindingPtr shaderBinding = renderPipelineLayout->AllocateShaderBinding(); + + std::shared_ptr instanceDataUbo = device->InstantiateBuffer(Nz::BufferType_Uniform); + if (!instanceDataUbo->Initialize(instanceDataBuffer.size(), Nz::BufferUsage_DeviceLocal | Nz::BufferUsage_Dynamic)) + { + NazaraError("Failed to create instance UBO"); + return __LINE__; + } + + instanceDataUbo->Fill(instanceDataBuffer.data(), 0, instanceDataBuffer.size()); + + std::shared_ptr viewerDataUbo = device->InstantiateBuffer(Nz::BufferType_Uniform); + if (!viewerDataUbo->Initialize(viewerDataBuffer.size(), Nz::BufferUsage_DeviceLocal | Nz::BufferUsage_Dynamic)) + { + NazaraError("Failed to create viewer UBO"); + return __LINE__; + } + + shaderBinding->Update({ + { + 5, + Nz::ShaderBinding::UniformBufferBinding { + viewerDataUbo.get(), 0, viewerDataBuffer.size() + } + }, + { + 4, + Nz::ShaderBinding::UniformBufferBinding { + instanceDataUbo.get(), 0, instanceDataBuffer.size() + } + }, + { + 1, + Nz::ShaderBinding::TextureBinding { + texture.get(), textureSampler.get() + } + } + }); + + Nz::RenderPipelineInfo pipelineInfo; + pipelineInfo.pipelineLayout = renderPipelineLayout; + + pipelineInfo.depthBuffer = true; + pipelineInfo.shaderStages.emplace_back(material.GetShader(Nz::ShaderStageType::Fragment)); + pipelineInfo.shaderStages.emplace_back(material.GetShader(Nz::ShaderStageType::Vertex)); + + auto& vertexBuffer = pipelineInfo.vertexBuffers.emplace_back(); + vertexBuffer.binding = 0; + vertexBuffer.declaration = drfreakVB->GetVertexDeclaration(); + + //std::shared_ptr pipeline = material.GetPipeline()->GetRenderPipeline(pipelineInfo.vertexBuffers); + + std::shared_ptr pipeline = device->InstantiateRenderPipeline(pipelineInfo); + + Nz::RenderDevice* renderDevice = window.GetRenderDevice().get(); + + Nz::RenderWindowImpl* windowImpl = window.GetImpl(); + std::shared_ptr commandPool = windowImpl->CreateCommandPool(Nz::QueueType::Graphics); + + Nz::RenderBuffer* renderBufferIB = static_cast(drfreakIB->GetBuffer()->GetImpl()); + Nz::RenderBuffer* renderBufferVB = static_cast(drfreakVB->GetBuffer()->GetImpl()); + + if (!renderBufferIB->Synchronize(renderDevice)) + { + NazaraError("Failed to synchronize render buffer"); + return __LINE__; + } + + if (!renderBufferVB->Synchronize(renderDevice)) + { + NazaraError("Failed to synchronize render buffer"); + return __LINE__; + } + + Nz::AbstractBuffer* indexBufferImpl = renderBufferIB->GetHardwareBuffer(renderDevice); + Nz::AbstractBuffer* vertexBufferImpl = renderBufferVB->GetHardwareBuffer(renderDevice); + + Nz::CommandBufferPtr drawCommandBuffer; + auto RebuildCommandBuffer = [&] + { + Nz::Vector2ui windowSize = window.GetSize(); + + drawCommandBuffer = commandPool->BuildCommandBuffer([&](Nz::CommandBufferBuilder& builder) + { + Nz::Recti renderRect(0, 0, window.GetSize().x, window.GetSize().y); + + Nz::CommandBufferBuilder::ClearValues clearValues[2]; + clearValues[0].color = Nz::Color::Black; + clearValues[1].depth = 1.f; + clearValues[1].stencil = 0; + + builder.BeginDebugRegion("Main window rendering", Nz::Color::Green); + { + builder.BeginRenderPass(windowImpl->GetFramebuffer(), windowImpl->GetRenderPass(), renderRect, { clearValues[0], clearValues[1] }); + { + builder.BindIndexBuffer(indexBufferImpl); + builder.BindPipeline(*pipeline); + builder.BindVertexBuffer(0, vertexBufferImpl); + builder.BindShaderBinding(*shaderBinding); + + builder.SetScissor(Nz::Recti{ 0, 0, int(windowSize.x), int(windowSize.y) }); + builder.SetViewport(Nz::Recti{ 0, 0, int(windowSize.x), int(windowSize.y) }); + + builder.DrawIndexed(drfreakIB->GetIndexCount()); + } + builder.EndRenderPass(); + } + builder.EndDebugRegion(); + }); + }; + RebuildCommandBuffer(); + + + Nz::Vector3f viewerPos = Nz::Vector3f::Zero(); + + Nz::EulerAnglesf camAngles(0.f, 0.f, 0.f); + Nz::Quaternionf camQuat(camAngles); + + window.EnableEventPolling(true); + + Nz::Clock updateClock; + Nz::Clock secondClock; + unsigned int fps = 0; + bool viewerUboUpdate = true; + + Nz::Mouse::SetRelativeMouseMode(true); + + while (window.IsOpen()) + { + Nz::WindowEvent event; + while (window.PollEvent(&event)) + { + switch (event.type) + { + case Nz::WindowEventType_Quit: + window.Close(); + break; + + case Nz::WindowEventType_MouseMoved: // La souris a bougé + { + // Gestion de la caméra free-fly (Rotation) + float sensitivity = 0.3f; // Sensibilité de la souris + + // On modifie l'angle de la caméra grâce au déplacement relatif sur X de la souris + camAngles.yaw = Nz::NormalizeAngle(camAngles.yaw - event.mouseMove.deltaX*sensitivity); + + // Idem, mais pour éviter les problèmes de calcul de la matrice de vue, on restreint les angles + camAngles.pitch = Nz::Clamp(camAngles.pitch + event.mouseMove.deltaY*sensitivity, -89.f, 89.f); + + camQuat = camAngles; + + viewerUboUpdate = true; + break; + } + + case Nz::WindowEventType_Resized: + { + Nz::Vector2ui windowSize = window.GetSize(); + Nz::AccessByOffset(viewerDataBuffer.data(), viewerUboOffsets.projMatrixOffset) = Nz::Matrix4f::Perspective(70.f, float(windowSize.x) / windowSize.y, 0.1f, 1000.f); + viewerUboUpdate = true; + break; + } + + default: + break; + } + } + + if (updateClock.GetMilliseconds() > 1000 / 60) + { + float cameraSpeed = 2.f * updateClock.GetSeconds(); + updateClock.Restart(); + + if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Up) || Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Z)) + viewerPos += camQuat * Nz::Vector3f::Forward() * cameraSpeed; + + // Si la flèche du bas ou la touche S est pressée, on recule + if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Down) || Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::S)) + viewerPos += camQuat * Nz::Vector3f::Backward() * cameraSpeed; + + // Etc... + if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Left) || Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Q)) + viewerPos += camQuat * Nz::Vector3f::Left() * cameraSpeed; + + // Etc... + if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Right) || Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::D)) + viewerPos += camQuat * Nz::Vector3f::Right() * cameraSpeed; + + // Majuscule pour monter, notez l'utilisation d'une direction globale (Non-affectée par la rotation) + if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::LShift) || Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::RShift)) + viewerPos += Nz::Vector3f::Up() * cameraSpeed; + + // Contrôle (Gauche ou droite) pour descendre dans l'espace global, etc... + if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::LControl) || Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::RControl)) + viewerPos += Nz::Vector3f::Down() * cameraSpeed; + + viewerUboUpdate = true; + } + + Nz::RenderFrame frame = windowImpl->Acquire(); + if (!frame) + continue; + + if (frame.IsFramebufferInvalidated()) + RebuildCommandBuffer(); + + Nz::AccessByOffset(viewerDataBuffer.data(), viewerUboOffsets.viewMatrixOffset) = Nz::Matrix4f::ViewMatrix(viewerPos, camAngles); + + if (viewerUboUpdate) + { + auto& allocation = frame.GetUploadPool().Allocate(viewerDataBuffer.size()); + + std::memcpy(allocation.mappedPtr, viewerDataBuffer.data(), viewerDataBuffer.size()); + + frame.Execute([&](Nz::CommandBufferBuilder& builder) + { + builder.BeginDebugRegion("UBO Update", Nz::Color::Yellow); + { + builder.PreTransferBarrier(); + builder.CopyBuffer(allocation, viewerDataUbo.get()); + builder.PostTransferBarrier(); + } + builder.EndDebugRegion(); + }, Nz::QueueType::Transfer); + + viewerUboUpdate = false; + } + + frame.SubmitCommandBuffer(drawCommandBuffer.get(), Nz::QueueType::Graphics); + + frame.Present(); + + window.Display(); + + // On incrémente le compteur de FPS improvisé + fps++; + + if (secondClock.GetMilliseconds() >= 1000) // Toutes les secondes + { + // Et on insère ces données dans le titre de la fenêtre + window.SetTitle(windowTitle + " - " + Nz::NumberToString(fps) + " FPS"); + + /* + Note: En C++11 il est possible d'insérer de l'Unicode de façon standard, quel que soit l'encodage du fichier, + via quelque chose de similaire à u8"Cha\u00CEne de caract\u00E8res". + Cependant, si le code source est encodé en UTF-8 (Comme c'est le cas dans ce fichier), + cela fonctionnera aussi comme ceci : "Chaîne de caractères". + */ + + // Et on réinitialise le compteur de FPS + fps = 0; + + // Et on relance l'horloge pour refaire ça dans une seconde + secondClock.Restart(); + } + } + + return EXIT_SUCCESS; +} From 8027ae9abe000deb7cc3541d4daed744f866248d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sat, 31 Oct 2020 16:27:35 +0100 Subject: [PATCH 011/278] Graphics: Fix PredefinedShaderBinding enum --- include/Nazara/Graphics/Enums.hpp | 13 +++++++------ include/Nazara/Graphics/MaterialSettings.hpp | 2 +- src/Nazara/Graphics/BasicMaterial.cpp | 6 +++--- src/Nazara/Graphics/PhongLightingMaterial.cpp | 8 ++++---- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/include/Nazara/Graphics/Enums.hpp b/include/Nazara/Graphics/Enums.hpp index ca7288e87..5c9a41952 100644 --- a/include/Nazara/Graphics/Enums.hpp +++ b/include/Nazara/Graphics/Enums.hpp @@ -17,16 +17,17 @@ namespace Nz Volume }; - enum PredefinedShaderBinding + enum class PredefinedShaderBinding { - PredefinedShaderBinding_TexOverlay, - PredefinedShaderBinding_UboInstanceData, - PredefinedShaderBinding_UboLighData, - PredefinedShaderBinding_UboViewerData, + TexOverlay, + UboInstanceData, + UboLighData, + UboViewerData, - PredefinedShaderBinding_Max = PredefinedShaderBinding_UboViewerData + Max = UboViewerData }; + constexpr std::size_t PredefinedShaderBindingCount = static_cast(PredefinedShaderBinding::Max) + 1; } #endif // NAZARA_ENUMS_GRAPHICS_HPP diff --git a/include/Nazara/Graphics/MaterialSettings.hpp b/include/Nazara/Graphics/MaterialSettings.hpp index 47aaef153..e2aec4257 100644 --- a/include/Nazara/Graphics/MaterialSettings.hpp +++ b/include/Nazara/Graphics/MaterialSettings.hpp @@ -23,7 +23,7 @@ namespace Nz { public: using DefaultShaders = std::array, ShaderStageTypeCount>; - using PredefinedBinding = std::array; + using PredefinedBinding = std::array; struct SharedUniformBlock; struct Texture; diff --git a/src/Nazara/Graphics/BasicMaterial.cpp b/src/Nazara/Graphics/BasicMaterial.cpp index 96f13a05b..59798a086 100644 --- a/src/Nazara/Graphics/BasicMaterial.cpp +++ b/src/Nazara/Graphics/BasicMaterial.cpp @@ -135,7 +135,7 @@ namespace Nz ImageType_2D }); - predefinedBinding[PredefinedShaderBinding_TexOverlay] = textures.size(); + predefinedBinding[UnderlyingCast(PredefinedShaderBinding::TexOverlay)] = textures.size(); textures.push_back({ "TextureOverlay", "Overlay", @@ -156,9 +156,9 @@ namespace Nz std::vector sharedUniformBlock; - predefinedBinding[PredefinedShaderBinding_UboInstanceData] = textures.size() + uniformBlocks.size() + sharedUniformBlock.size(); + predefinedBinding[UnderlyingCast(PredefinedShaderBinding::UboInstanceData)] = textures.size() + uniformBlocks.size() + sharedUniformBlock.size(); sharedUniformBlock.push_back(PredefinedInstanceData::GetUniformBlock()); - predefinedBinding[PredefinedShaderBinding_UboViewerData] = textures.size() + uniformBlocks.size() + sharedUniformBlock.size(); + predefinedBinding[UnderlyingCast(PredefinedShaderBinding::UboViewerData)] = textures.size() + uniformBlocks.size() + sharedUniformBlock.size(); sharedUniformBlock.push_back(PredefinedViewerData::GetUniformBlock()); // Shaders diff --git a/src/Nazara/Graphics/PhongLightingMaterial.cpp b/src/Nazara/Graphics/PhongLightingMaterial.cpp index c08e711d9..903c34d97 100644 --- a/src/Nazara/Graphics/PhongLightingMaterial.cpp +++ b/src/Nazara/Graphics/PhongLightingMaterial.cpp @@ -199,11 +199,11 @@ namespace Nz }); std::vector sharedUniformBlock; - predefinedBinding[PredefinedShaderBinding_UboInstanceData] = sharedUniformBlock.size(); + predefinedBinding[UnderlyingCast(PredefinedShaderBinding::UboInstanceData)] = sharedUniformBlock.size(); sharedUniformBlock.push_back(PredefinedInstanceData::GetUniformBlock()); - predefinedBinding[PredefinedShaderBinding_UboLighData] = sharedUniformBlock.size(); + predefinedBinding[UnderlyingCast(PredefinedShaderBinding::UboLighData)] = sharedUniformBlock.size(); sharedUniformBlock.push_back(PredefinedLightData::GetUniformBlock()); - predefinedBinding[PredefinedShaderBinding_UboViewerData] = sharedUniformBlock.size(); + predefinedBinding[UnderlyingCast(PredefinedShaderBinding::UboViewerData)] = sharedUniformBlock.size(); sharedUniformBlock.push_back(PredefinedViewerData::GetUniformBlock()); std::vector textures; @@ -249,7 +249,7 @@ namespace Nz ImageType_2D }); - predefinedBinding[PredefinedShaderBinding_TexOverlay] = textures.size(); + predefinedBinding[UnderlyingCast(PredefinedShaderBinding::TexOverlay)] = textures.size(); textures.push_back({ "TextureOverlay", "Overlay", From ad88561245fee7f50bc760a6f6ba5bf91fff691a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sat, 31 Oct 2020 16:29:02 +0100 Subject: [PATCH 012/278] Graphics: Fix MaterialPipeline::GetRenderPipeline --- examples/GraphicsTest/main.cpp | 51 +++++------------------- src/Nazara/Graphics/MaterialPipeline.cpp | 2 + 2 files changed, 13 insertions(+), 40 deletions(-) diff --git a/examples/GraphicsTest/main.cpp b/examples/GraphicsTest/main.cpp index 23f7ca17d..946d6bc28 100644 --- a/examples/GraphicsTest/main.cpp +++ b/examples/GraphicsTest/main.cpp @@ -94,6 +94,7 @@ int main() Nz::Material material(Nz::BasicMaterial::GetSettings()); //material.SetShader(Nz::ShaderStageType::Fragment, fragmentShader); //material.SetShader(Nz::ShaderStageType::Vertex, vertexShader); + material.EnableDepthBuffer(true); material.SetTexture(0, texture); material.SetTextureSampler(0, textureSampler); @@ -109,33 +110,8 @@ int main() Nz::AccessByOffset(viewerDataBuffer.data(), viewerUboOffsets.viewMatrixOffset) = Nz::Matrix4f::Translate(Nz::Vector3f::Backward() * 1); Nz::AccessByOffset(viewerDataBuffer.data(), viewerUboOffsets.projMatrixOffset) = Nz::Matrix4f::Perspective(70.f, float(windowSize.x) / windowSize.y, 0.1f, 1000.f); - Nz::RenderPipelineLayoutInfo pipelineLayoutInfo; - { - auto& uboBinding = pipelineLayoutInfo.bindings.emplace_back(); - uboBinding.index = 0; - uboBinding.shaderStageFlags = Nz::ShaderStageType::Vertex; - uboBinding.type = Nz::ShaderBindingType::UniformBuffer; - } - - { - auto& uboBinding = pipelineLayoutInfo.bindings.emplace_back(); - uboBinding.index = 1; - uboBinding.shaderStageFlags = Nz::ShaderStageType::Vertex; - uboBinding.type = Nz::ShaderBindingType::UniformBuffer; - } - - { - auto& textureBinding = pipelineLayoutInfo.bindings.emplace_back(); - textureBinding.index = 2; - textureBinding.shaderStageFlags = Nz::ShaderStageType::Fragment; - textureBinding.type = Nz::ShaderBindingType::Texture; - } - - //std::shared_ptr renderPipelineLayout = device->InstantiateRenderPipelineLayout(std::move(pipelineLayoutInfo)); std::shared_ptr renderPipelineLayout = material.GetSettings()->GetRenderPipelineLayout(); - Nz::ShaderBindingPtr shaderBinding = renderPipelineLayout->AllocateShaderBinding(); - std::shared_ptr instanceDataUbo = device->InstantiateBuffer(Nz::BufferType_Uniform); if (!instanceDataUbo->Initialize(instanceDataBuffer.size(), Nz::BufferUsage_DeviceLocal | Nz::BufferUsage_Dynamic)) { @@ -152,15 +128,16 @@ int main() return __LINE__; } + Nz::ShaderBindingPtr shaderBinding = renderPipelineLayout->AllocateShaderBinding(); shaderBinding->Update({ { - 5, + material.GetSettings()->GetPredefinedBindingIndex(Nz::PredefinedShaderBinding::UboViewerData), Nz::ShaderBinding::UniformBufferBinding { viewerDataUbo.get(), 0, viewerDataBuffer.size() } }, { - 4, + material.GetSettings()->GetPredefinedBindingIndex(Nz::PredefinedShaderBinding::UboInstanceData), Nz::ShaderBinding::UniformBufferBinding { instanceDataUbo.get(), 0, instanceDataBuffer.size() } @@ -173,20 +150,14 @@ int main() } }); - Nz::RenderPipelineInfo pipelineInfo; - pipelineInfo.pipelineLayout = renderPipelineLayout; + std::vector vertexBuffers = { + { + 0, + drfreakVB->GetVertexDeclaration() + } + }; - pipelineInfo.depthBuffer = true; - pipelineInfo.shaderStages.emplace_back(material.GetShader(Nz::ShaderStageType::Fragment)); - pipelineInfo.shaderStages.emplace_back(material.GetShader(Nz::ShaderStageType::Vertex)); - - auto& vertexBuffer = pipelineInfo.vertexBuffers.emplace_back(); - vertexBuffer.binding = 0; - vertexBuffer.declaration = drfreakVB->GetVertexDeclaration(); - - //std::shared_ptr pipeline = material.GetPipeline()->GetRenderPipeline(pipelineInfo.vertexBuffers); - - std::shared_ptr pipeline = device->InstantiateRenderPipeline(pipelineInfo); + std::shared_ptr pipeline = material.GetPipeline()->GetRenderPipeline(vertexBuffers); Nz::RenderDevice* renderDevice = window.GetRenderDevice().get(); diff --git a/src/Nazara/Graphics/MaterialPipeline.cpp b/src/Nazara/Graphics/MaterialPipeline.cpp index c22e21d1e..5996f64b0 100644 --- a/src/Nazara/Graphics/MaterialPipeline.cpp +++ b/src/Nazara/Graphics/MaterialPipeline.cpp @@ -53,6 +53,8 @@ namespace Nz renderPipelineInfo.shaderStages.push_back(shaderStage); } + renderPipelineInfo.vertexBuffers = vertexBuffers; + return m_renderPipelines.emplace_back(Graphics::Instance()->GetRenderDevice().InstantiateRenderPipeline(std::move(renderPipelineInfo))); } /*! From f52c43df49a469e9a206c6b55e6cc1e343c9a021 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sat, 31 Oct 2020 17:33:56 +0100 Subject: [PATCH 013/278] Network: Fix TcpClient::PollConnection on Linux --- src/Nazara/Network/Posix/SocketImpl.cpp | 52 +++++++++++------------- src/Nazara/Network/Win32/SocketImpl.cpp | 54 ++++++++++++------------- 2 files changed, 49 insertions(+), 57 deletions(-) diff --git a/src/Nazara/Network/Posix/SocketImpl.cpp b/src/Nazara/Network/Posix/SocketImpl.cpp index af0b5557f..d0386a891 100644 --- a/src/Nazara/Network/Posix/SocketImpl.cpp +++ b/src/Nazara/Network/Posix/SocketImpl.cpp @@ -411,32 +411,40 @@ namespace Nz SocketState SocketImpl::PollConnection(SocketHandle handle, const IpAddress& address, UInt64 msTimeout, SocketError* error) { - // http://developerweb.net/viewtopic.php?id=3196 - fd_set localSet; - FD_ZERO(&localSet); - FD_SET(handle, &localSet); + // Wait until socket is available for writing or an error occurs (ie when connection succeeds or fails) + pollfd descriptor; + descriptor.events = POLLOUT; + descriptor.fd = handle; + descriptor.revents = 0; - timeval tv; - tv.tv_sec = static_cast(msTimeout / 1000ULL); - tv.tv_usec = static_cast((msTimeout % 1000ULL) * 1000ULL); - - int ret = ::select(0, nullptr, &localSet, &localSet, (msTimeout != std::numeric_limits::max()) ? &tv : nullptr); - if (ret > 0) + int ret = ::poll(&descriptor, 1, (msTimeout != std::numeric_limits::max()) ? int(msTimeout) : -1); + if (ret == SOCKET_ERROR) { - int code = GetLastErrorCode(handle, error); - if (code < 0) //< GetLastErrorCode() failed - return SocketState_NotConnected; + if (error) + *error = TranslateErrnoToSocketError(GetLastErrorCode()); - if (code) + return SocketState_NotConnected; + } + else if (ret > 0) + { + if (descriptor.revents & (POLLERR | POLLHUP)) { if (error) - *error = TranslateErrnoToSocketError(code); + *error = GetLastError(handle); return SocketState_NotConnected; } + else if (descriptor.revents & POLLOUT) + return SocketState_Connected; + else + { + NazaraWarning("Socket " + String::Number(handle) + " was returned by poll without POLLOUT nor error events (events: 0x" + String::Number(descriptor.revents, 16) + ')'); + return SocketState_NotConnected; + } } - else if (ret == 0) + else { + // Still connecting if (error) { if (msTimeout > 0) @@ -447,18 +455,6 @@ namespace Nz return SocketState_Connecting; } - else - { - if (error) - *error = TranslateErrnoToSocketError(GetLastErrorCode()); - - return SocketState_NotConnected; - } - - if (error) - *error = SocketError_NoError; - - return SocketState_Connected; } bool SocketImpl::Receive(SocketHandle handle, void* buffer, int length, int* read, SocketError* error) diff --git a/src/Nazara/Network/Win32/SocketImpl.cpp b/src/Nazara/Network/Win32/SocketImpl.cpp index f9e4b42f5..157f14811 100644 --- a/src/Nazara/Network/Win32/SocketImpl.cpp +++ b/src/Nazara/Network/Win32/SocketImpl.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2018 Jérôme Leclercq +// Copyright (C) 2020 Jérôme Leclercq // This file is part of the "Nazara Engine - Network module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -452,32 +452,40 @@ namespace Nz SocketState SocketImpl::PollConnection(SocketHandle handle, const IpAddress& address, UInt64 msTimeout, SocketError* error) { - // http://developerweb.net/viewtopic.php?id=3196 - fd_set localSet; - FD_ZERO(&localSet); - FD_SET(handle, &localSet); + // Wait until socket is available for writing or an error occurs (ie when connection succeeds or fails) + WSAPOLLFD descriptor; + descriptor.events = POLLWRNORM; + descriptor.fd = handle; + descriptor.revents = 0; - timeval tv; - tv.tv_sec = static_cast(msTimeout / 1000ULL); - tv.tv_usec = static_cast((msTimeout % 1000ULL) * 1000ULL); - - int ret = ::select(0, nullptr, &localSet, &localSet, (msTimeout != std::numeric_limits::max()) ? &tv : nullptr); - if (ret > 0) + int ret = WSAPoll(&descriptor, 1, (msTimeout != std::numeric_limits::max()) ? INT(msTimeout) : INT(-1)); + if (ret == SOCKET_ERROR) { - int code = GetLastErrorCode(handle, error); - if (code < 0) //< GetLastErrorCode() failed - return SocketState_NotConnected; + if (error) + *error = TranslateWSAErrorToSocketError(WSAGetLastError()); - if (code) + return SocketState_NotConnected; + } + else if (ret > 0) + { + if (descriptor.revents & (POLLERR | POLLHUP)) { if (error) - *error = TranslateWSAErrorToSocketError(code); + *error = GetLastError(handle); return SocketState_NotConnected; } + else if (descriptor.revents & POLLWRNORM) + return SocketState_Connected; + else + { + NazaraWarning("Socket " + String::Number(handle) + " was returned by poll without POLLOUT nor error events (events: 0x" + String::Number(descriptor.revents, 16) + ')'); + return SocketState_NotConnected; + } } - else if (ret == 0) + else { + // Still connecting if (error) { if (msTimeout > 0) @@ -488,18 +496,6 @@ namespace Nz return SocketState_Connecting; } - else - { - if (error) - *error = TranslateWSAErrorToSocketError(WSAGetLastError()); - - return SocketState_NotConnected; - } - - if (error) - *error = SocketError_NoError; - - return SocketState_Connected; } bool SocketImpl::Receive(SocketHandle handle, void* buffer, int length, int* read, SocketError* error) From 8e6b4cc673b05801059fc3f0d9c33336cfa7cf8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sun, 1 Nov 2020 17:40:12 +0100 Subject: [PATCH 014/278] Graphics/Model: Fix copy constructor --- include/Nazara/Graphics/Model.inl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/Nazara/Graphics/Model.inl b/include/Nazara/Graphics/Model.inl index 9c1809368..482470caa 100644 --- a/include/Nazara/Graphics/Model.inl +++ b/include/Nazara/Graphics/Model.inl @@ -22,7 +22,8 @@ namespace Nz * \param model Model to copy */ inline Model::Model(const Model& model) : - InstancedRenderable(model) + InstancedRenderable(model), + Resource(model) { SetMesh(model.m_mesh); From af55ecc2a5bf97b2b876754135ff0189fe1b5a0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 12 Nov 2020 16:28:33 +0100 Subject: [PATCH 015/278] Fix SDL2 crash when creating cursor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enfoiré de REMqb --- src/Nazara/Platform/SDL2/CursorImpl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nazara/Platform/SDL2/CursorImpl.cpp b/src/Nazara/Platform/SDL2/CursorImpl.cpp index c9497a2e8..bd4f9ea21 100644 --- a/src/Nazara/Platform/SDL2/CursorImpl.cpp +++ b/src/Nazara/Platform/SDL2/CursorImpl.cpp @@ -24,9 +24,9 @@ namespace Nz m_iconImage.GetWidth(), m_iconImage.GetHeight(), 32, - 32 * m_iconImage.GetWidth(), + 4 * m_iconImage.GetWidth(), SDL_PIXELFORMAT_BGRA8888 - ); + ); if (!m_icon) { From 7526923a8d6bb5fab586e0c9a22fdd7f4087724a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Tue, 17 Nov 2020 17:43:42 +0100 Subject: [PATCH 016/278] Platform: Fix space not generating a text event --- src/Nazara/Platform/SDL2/WindowImpl.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Nazara/Platform/SDL2/WindowImpl.cpp b/src/Nazara/Platform/SDL2/WindowImpl.cpp index e2a71f27b..f17ce3c3c 100644 --- a/src/Nazara/Platform/SDL2/WindowImpl.cpp +++ b/src/Nazara/Platform/SDL2/WindowImpl.cpp @@ -2,8 +2,6 @@ // This file is part of the "Nazara Engine - Platform module" // For conditions of distribution and use, see copyright notice in Config.hpp -#include -#include #include #include #include @@ -19,6 +17,9 @@ #include #include #include +#include +#include +#include namespace Nz { @@ -488,23 +489,26 @@ namespace Nz break; case SDL_TEXTINPUT: + { if (SDL_GetWindowID(window->m_handle) != event->text.windowID) return 0; evt.type = WindowEventType_TextEntered; evt.text.repeated = false; - for (decltype(evt.text.character) codepoint : String::Unicode(event->text.text).Simplify().GetUtf32String()) + utf8::unchecked::iterator it(event->text.text); + do { - evt.text.character = codepoint; + evt.text.character = *it; window->m_parent->PushEvent(evt); - } + } while (*it++); // prevent post switch event evt.type = WindowEventType::WindowEventType_Max; break; + } case SDL_TEXTEDITING: if (SDL_GetWindowID(window->m_handle) != event->edit.windowID) From bd9d30407cfd151db2407d91f1735ffa9adf88f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Tue, 17 Nov 2020 17:44:31 +0100 Subject: [PATCH 017/278] Fix SDL2 cursor --- src/Nazara/Platform/SDL2/CursorImpl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nazara/Platform/SDL2/CursorImpl.cpp b/src/Nazara/Platform/SDL2/CursorImpl.cpp index bd4f9ea21..37638c412 100644 --- a/src/Nazara/Platform/SDL2/CursorImpl.cpp +++ b/src/Nazara/Platform/SDL2/CursorImpl.cpp @@ -25,7 +25,7 @@ namespace Nz m_iconImage.GetHeight(), 32, 4 * m_iconImage.GetWidth(), - SDL_PIXELFORMAT_BGRA8888 + SDL_PIXELFORMAT_BGRA32 ); if (!m_icon) From 960817a1f11d25d3a6834230f7ca344991be97ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 19 Nov 2020 13:56:54 +0100 Subject: [PATCH 018/278] Add conditional expression/statement support for shaders --- include/Nazara/Shader/GlslWriter.hpp | 6 +- include/Nazara/Shader/ShaderAst.hpp | 11 + include/Nazara/Shader/ShaderAst.inl | 16 ++ include/Nazara/Shader/ShaderAstCloner.hpp | 2 + .../Shader/ShaderAstRecursiveVisitor.hpp | 2 + include/Nazara/Shader/ShaderAstSerializer.hpp | 2 + include/Nazara/Shader/ShaderAstValidator.hpp | 2 + include/Nazara/Shader/ShaderAstVisitor.hpp | 11 +- .../Nazara/Shader/ShaderAstVisitorExcept.hpp | 2 + include/Nazara/Shader/ShaderBuilder.hpp | 1 + include/Nazara/Shader/ShaderEnums.hpp | 1 + include/Nazara/Shader/ShaderNodes.hpp | 14 + include/Nazara/Shader/ShaderNodes.inl | 14 + include/Nazara/Shader/ShaderWriter.hpp | 8 +- include/Nazara/Shader/SpirvAstVisitor.hpp | 2 + include/Nazara/Shader/SpirvWriter.hpp | 7 +- include/Nazara/Shader/SpirvWriter.inl | 4 + src/Nazara/Shader/GlslWriter.cpp | 18 +- src/Nazara/Shader/ShaderAst.cpp | 6 + src/Nazara/Shader/ShaderAstCloner.cpp | 10 + .../Shader/ShaderAstRecursiveVisitor.cpp | 11 + src/Nazara/Shader/ShaderAstSerializer.cpp | 49 ++++ src/Nazara/Shader/ShaderAstValidator.cpp | 29 +++ src/Nazara/Shader/ShaderAstVisitor.cpp | 13 - src/Nazara/Shader/ShaderAstVisitorExcept.cpp | 10 + src/Nazara/Shader/ShaderNodes.cpp | 15 +- src/Nazara/Shader/SpirvAstVisitor.cpp | 14 + src/Nazara/Shader/SpirvWriter.cpp | 25 +- .../DataModels/ConditionalExpression.cpp | 240 ++++++++++++++++++ .../DataModels/ConditionalExpression.hpp | 58 +++++ .../DataModels/ConditionalExpression.inl | 2 + src/ShaderNode/DataModels/OutputValue.cpp | 10 +- src/ShaderNode/DataModels/ShaderNode.cpp | 25 +- src/ShaderNode/DataModels/ShaderNode.hpp | 2 + src/ShaderNode/ShaderGraph.cpp | 69 ++++- src/ShaderNode/ShaderGraph.hpp | 21 +- src/ShaderNode/ShaderGraph.inl | 22 ++ .../Widgets/ConditionEditDialog.cpp | 55 ++++ .../Widgets/ConditionEditDialog.hpp | 35 +++ .../Widgets/ConditionEditDialog.inl | 1 + src/ShaderNode/Widgets/ConditionEditor.cpp | 117 +++++++++ src/ShaderNode/Widgets/ConditionEditor.hpp | 36 +++ src/ShaderNode/Widgets/ConditionEditor.inl | 1 + src/ShaderNode/Widgets/MainWindow.cpp | 48 +++- src/ShaderNode/Widgets/MainWindow.hpp | 5 +- 45 files changed, 996 insertions(+), 56 deletions(-) create mode 100644 src/ShaderNode/DataModels/ConditionalExpression.cpp create mode 100644 src/ShaderNode/DataModels/ConditionalExpression.hpp create mode 100644 src/ShaderNode/DataModels/ConditionalExpression.inl create mode 100644 src/ShaderNode/Widgets/ConditionEditDialog.cpp create mode 100644 src/ShaderNode/Widgets/ConditionEditDialog.hpp create mode 100644 src/ShaderNode/Widgets/ConditionEditDialog.inl create mode 100644 src/ShaderNode/Widgets/ConditionEditor.cpp create mode 100644 src/ShaderNode/Widgets/ConditionEditor.hpp create mode 100644 src/ShaderNode/Widgets/ConditionEditor.inl diff --git a/include/Nazara/Shader/GlslWriter.hpp b/include/Nazara/Shader/GlslWriter.hpp index ad76fbe18..e7b92505c 100644 --- a/include/Nazara/Shader/GlslWriter.hpp +++ b/include/Nazara/Shader/GlslWriter.hpp @@ -16,7 +16,6 @@ #include #include #include -#include namespace Nz { @@ -31,7 +30,7 @@ namespace Nz GlslWriter(GlslWriter&&) = delete; ~GlslWriter() = default; - std::string Generate(const ShaderAst& shader) override; + std::string Generate(const ShaderAst& shader, const States& conditions = {}); void SetEnv(Environment environment); @@ -70,6 +69,8 @@ namespace Nz void Visit(ShaderNodes::BinaryOp& node) override; void Visit(ShaderNodes::BuiltinVariable& var) override; void Visit(ShaderNodes::Cast& node) override; + void Visit(ShaderNodes::ConditionalExpression& node) override; + void Visit(ShaderNodes::ConditionalStatement& node) override; void Visit(ShaderNodes::Constant& node) override; void Visit(ShaderNodes::DeclareVariable& node) override; void Visit(ShaderNodes::ExpressionStatement& node) override; @@ -91,6 +92,7 @@ namespace Nz { const ShaderAst* shader = nullptr; const ShaderAst::Function* currentFunction = nullptr; + const States* states = nullptr; }; struct State diff --git a/include/Nazara/Shader/ShaderAst.hpp b/include/Nazara/Shader/ShaderAst.hpp index 30ed90fac..5b80a1380 100644 --- a/include/Nazara/Shader/ShaderAst.hpp +++ b/include/Nazara/Shader/ShaderAst.hpp @@ -20,6 +20,7 @@ namespace Nz class NAZARA_SHADER_API ShaderAst { public: + struct Condition; struct Function; struct FunctionParameter; struct InputOutput; @@ -33,12 +34,16 @@ namespace Nz ShaderAst(ShaderAst&&) noexcept = default; ~ShaderAst() = default; + void AddCondition(std::string name); void AddFunction(std::string name, ShaderNodes::StatementPtr statement, std::vector parameters = {}, ShaderNodes::BasicType returnType = ShaderNodes::BasicType::Void); void AddInput(std::string name, ShaderExpressionType type, std::optional locationIndex = {}); void AddOutput(std::string name, ShaderExpressionType type, std::optional locationIndex = {}); void AddStruct(std::string name, std::vector members); void AddUniform(std::string name, ShaderExpressionType type, std::optional bindingIndex = {}, std::optional memoryLayout = {}); + inline const Condition& GetCondition(std::size_t i) const; + inline std::size_t GetConditionCount() const; + inline const std::vector& GetConditions() const; inline const Function& GetFunction(std::size_t i) const; inline std::size_t GetFunctionCount() const; inline const std::vector& GetFunctions() const; @@ -59,6 +64,11 @@ namespace Nz ShaderAst& operator=(const ShaderAst&) = default; ShaderAst& operator=(ShaderAst&&) noexcept = default; + struct Condition + { + std::string name; + }; + struct VariableBase { std::string name; @@ -101,6 +111,7 @@ namespace Nz }; private: + std::vector m_conditions; std::vector m_functions; std::vector m_inputs; std::vector m_outputs; diff --git a/include/Nazara/Shader/ShaderAst.inl b/include/Nazara/Shader/ShaderAst.inl index 4c6c42833..f00517db5 100644 --- a/include/Nazara/Shader/ShaderAst.inl +++ b/include/Nazara/Shader/ShaderAst.inl @@ -12,6 +12,22 @@ namespace Nz { } + inline auto Nz::ShaderAst::GetCondition(std::size_t i) const -> const Condition& + { + assert(i < m_functions.size()); + return m_conditions[i]; + } + + inline std::size_t ShaderAst::GetConditionCount() const + { + return m_conditions.size(); + } + + inline auto ShaderAst::GetConditions() const -> const std::vector& + { + return m_conditions; + } + inline auto ShaderAst::GetFunction(std::size_t i) const -> const Function& { assert(i < m_functions.size()); diff --git a/include/Nazara/Shader/ShaderAstCloner.hpp b/include/Nazara/Shader/ShaderAstCloner.hpp index 34336e9ba..afa7cb5b2 100644 --- a/include/Nazara/Shader/ShaderAstCloner.hpp +++ b/include/Nazara/Shader/ShaderAstCloner.hpp @@ -38,6 +38,8 @@ namespace Nz void Visit(ShaderNodes::BinaryOp& node) override; void Visit(ShaderNodes::Branch& node) override; void Visit(ShaderNodes::Cast& node) override; + void Visit(ShaderNodes::ConditionalExpression& node) override; + void Visit(ShaderNodes::ConditionalStatement& node) override; void Visit(ShaderNodes::Constant& node) override; void Visit(ShaderNodes::DeclareVariable& node) override; void Visit(ShaderNodes::ExpressionStatement& node) override; diff --git a/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp b/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp index 367f9b4ca..5dd1bc5fe 100644 --- a/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp +++ b/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp @@ -26,6 +26,8 @@ namespace Nz void Visit(ShaderNodes::BinaryOp& node) override; void Visit(ShaderNodes::Branch& node) override; void Visit(ShaderNodes::Cast& node) override; + void Visit(ShaderNodes::ConditionalExpression& node) override; + void Visit(ShaderNodes::ConditionalStatement& node) override; void Visit(ShaderNodes::Constant& node) override; void Visit(ShaderNodes::DeclareVariable& node) override; void Visit(ShaderNodes::ExpressionStatement& node) override; diff --git a/include/Nazara/Shader/ShaderAstSerializer.hpp b/include/Nazara/Shader/ShaderAstSerializer.hpp index ac03cc66d..e2db77fdf 100644 --- a/include/Nazara/Shader/ShaderAstSerializer.hpp +++ b/include/Nazara/Shader/ShaderAstSerializer.hpp @@ -31,6 +31,8 @@ namespace Nz void Serialize(ShaderNodes::BuiltinVariable& var); void Serialize(ShaderNodes::Branch& node); void Serialize(ShaderNodes::Cast& node); + void Serialize(ShaderNodes::ConditionalExpression& node); + void Serialize(ShaderNodes::ConditionalStatement& node); void Serialize(ShaderNodes::Constant& node); void Serialize(ShaderNodes::DeclareVariable& node); void Serialize(ShaderNodes::ExpressionStatement& node); diff --git a/include/Nazara/Shader/ShaderAstValidator.hpp b/include/Nazara/Shader/ShaderAstValidator.hpp index 8195494b6..579893aa4 100644 --- a/include/Nazara/Shader/ShaderAstValidator.hpp +++ b/include/Nazara/Shader/ShaderAstValidator.hpp @@ -41,6 +41,8 @@ namespace Nz void Visit(ShaderNodes::BinaryOp& node) override; void Visit(ShaderNodes::Branch& node) override; void Visit(ShaderNodes::Cast& node) override; + void Visit(ShaderNodes::ConditionalExpression& node) override; + void Visit(ShaderNodes::ConditionalStatement& node) override; void Visit(ShaderNodes::Constant& node) override; void Visit(ShaderNodes::DeclareVariable& node) override; void Visit(ShaderNodes::ExpressionStatement& node) override; diff --git a/include/Nazara/Shader/ShaderAstVisitor.hpp b/include/Nazara/Shader/ShaderAstVisitor.hpp index decd3a2f9..9ac8d764c 100644 --- a/include/Nazara/Shader/ShaderAstVisitor.hpp +++ b/include/Nazara/Shader/ShaderAstVisitor.hpp @@ -10,8 +10,6 @@ #include #include #include -#include -#include namespace Nz { @@ -23,16 +21,14 @@ namespace Nz ShaderAstVisitor(ShaderAstVisitor&&) = delete; virtual ~ShaderAstVisitor(); - void EnableCondition(const std::string& name, bool cond); - - bool IsConditionEnabled(const std::string& name) const; - void Visit(const ShaderNodes::NodePtr& node); virtual void Visit(ShaderNodes::AccessMember& node) = 0; virtual void Visit(ShaderNodes::AssignOp& node) = 0; virtual void Visit(ShaderNodes::BinaryOp& node) = 0; virtual void Visit(ShaderNodes::Branch& node) = 0; virtual void Visit(ShaderNodes::Cast& node) = 0; + virtual void Visit(ShaderNodes::ConditionalExpression& node) = 0; + virtual void Visit(ShaderNodes::ConditionalStatement& node) = 0; virtual void Visit(ShaderNodes::Constant& node) = 0; virtual void Visit(ShaderNodes::DeclareVariable& node) = 0; virtual void Visit(ShaderNodes::ExpressionStatement& node) = 0; @@ -44,9 +40,6 @@ namespace Nz ShaderAstVisitor& operator=(const ShaderAstVisitor&) = delete; ShaderAstVisitor& operator=(ShaderAstVisitor&&) = delete; - - private: - std::unordered_set m_conditions; }; } diff --git a/include/Nazara/Shader/ShaderAstVisitorExcept.hpp b/include/Nazara/Shader/ShaderAstVisitorExcept.hpp index 40635477c..0c58c5472 100644 --- a/include/Nazara/Shader/ShaderAstVisitorExcept.hpp +++ b/include/Nazara/Shader/ShaderAstVisitorExcept.hpp @@ -22,6 +22,8 @@ namespace Nz void Visit(ShaderNodes::BinaryOp& node) override; void Visit(ShaderNodes::Branch& node) override; void Visit(ShaderNodes::Cast& node) override; + void Visit(ShaderNodes::ConditionalExpression& node) override; + void Visit(ShaderNodes::ConditionalStatement& node) override; void Visit(ShaderNodes::Constant& node) override; void Visit(ShaderNodes::DeclareVariable& node) override; void Visit(ShaderNodes::ExpressionStatement& node) override; diff --git a/include/Nazara/Shader/ShaderBuilder.hpp b/include/Nazara/Shader/ShaderBuilder.hpp index 074434a44..0965c7f0c 100644 --- a/include/Nazara/Shader/ShaderBuilder.hpp +++ b/include/Nazara/Shader/ShaderBuilder.hpp @@ -50,6 +50,7 @@ namespace Nz::ShaderBuilder constexpr BuiltinBuilder Builtin; constexpr GenBuilder Block; constexpr GenBuilder Branch; + constexpr GenBuilder ConditionalExpression; constexpr GenBuilder ConditionalStatement; constexpr GenBuilder Constant; constexpr GenBuilder DeclareVariable; diff --git a/include/Nazara/Shader/ShaderEnums.hpp b/include/Nazara/Shader/ShaderEnums.hpp index ed322e3e6..57f76d0f5 100644 --- a/include/Nazara/Shader/ShaderEnums.hpp +++ b/include/Nazara/Shader/ShaderEnums.hpp @@ -78,6 +78,7 @@ namespace Nz::ShaderNodes Branch, Cast, Constant, + ConditionalExpression, ConditionalStatement, DeclareVariable, ExpressionStatement, diff --git a/include/Nazara/Shader/ShaderNodes.hpp b/include/Nazara/Shader/ShaderNodes.hpp index b3af5f1aa..8639dbc99 100644 --- a/include/Nazara/Shader/ShaderNodes.hpp +++ b/include/Nazara/Shader/ShaderNodes.hpp @@ -217,6 +217,20 @@ namespace Nz static inline std::shared_ptr Build(BasicType castTo, ExpressionPtr* expressions, std::size_t expressionCount); }; + struct NAZARA_SHADER_API ConditionalExpression : public Expression + { + inline ConditionalExpression(); + + ShaderExpressionType GetExpressionType() const override; + void Visit(ShaderAstVisitor& visitor) override; + + std::string conditionName; + ExpressionPtr falsePath; + ExpressionPtr truePath; + + static inline std::shared_ptr Build(std::string condition, ExpressionPtr truePath, ExpressionPtr falsePath); + }; + struct NAZARA_SHADER_API Constant : public Expression { inline Constant(); diff --git a/include/Nazara/Shader/ShaderNodes.inl b/include/Nazara/Shader/ShaderNodes.inl index 1e0817b62..b61841430 100644 --- a/include/Nazara/Shader/ShaderNodes.inl +++ b/include/Nazara/Shader/ShaderNodes.inl @@ -263,6 +263,20 @@ namespace Nz::ShaderNodes return node; } + inline ConditionalExpression::ConditionalExpression() : + Expression(NodeType::ConditionalExpression) + { + } + + inline std::shared_ptr ShaderNodes::ConditionalExpression::Build(std::string condition, ExpressionPtr truePath, ExpressionPtr falsePath) + { + auto node = std::make_shared(); + node->conditionName = std::move(condition); + node->falsePath = std::move(falsePath); + node->truePath = std::move(truePath); + + return node; + } inline Constant::Constant() : Expression(NodeType::Constant) diff --git a/include/Nazara/Shader/ShaderWriter.hpp b/include/Nazara/Shader/ShaderWriter.hpp index 0e896fa40..3fd25d7ff 100644 --- a/include/Nazara/Shader/ShaderWriter.hpp +++ b/include/Nazara/Shader/ShaderWriter.hpp @@ -10,6 +10,7 @@ #include #include #include +#include namespace Nz { @@ -18,12 +19,17 @@ namespace Nz class NAZARA_SHADER_API ShaderWriter { public: + struct States; + ShaderWriter() = default; ShaderWriter(const ShaderWriter&) = default; ShaderWriter(ShaderWriter&&) = default; virtual ~ShaderWriter(); - virtual std::string Generate(const ShaderAst& shader) = 0; + struct States + { + std::unordered_set enabledConditions; + }; }; } diff --git a/include/Nazara/Shader/SpirvAstVisitor.hpp b/include/Nazara/Shader/SpirvAstVisitor.hpp index 743dd5130..d7196950f 100644 --- a/include/Nazara/Shader/SpirvAstVisitor.hpp +++ b/include/Nazara/Shader/SpirvAstVisitor.hpp @@ -32,6 +32,8 @@ namespace Nz void Visit(ShaderNodes::AssignOp& node) override; void Visit(ShaderNodes::BinaryOp& node) override; void Visit(ShaderNodes::Cast& node) override; + void Visit(ShaderNodes::ConditionalExpression& node) override; + void Visit(ShaderNodes::ConditionalStatement& node) override; void Visit(ShaderNodes::Constant& node) override; void Visit(ShaderNodes::DeclareVariable& node) override; void Visit(ShaderNodes::ExpressionStatement& node) override; diff --git a/include/Nazara/Shader/SpirvWriter.hpp b/include/Nazara/Shader/SpirvWriter.hpp index 6b21de0ba..86f3f156b 100644 --- a/include/Nazara/Shader/SpirvWriter.hpp +++ b/include/Nazara/Shader/SpirvWriter.hpp @@ -23,7 +23,7 @@ namespace Nz { class SpirvSection; - class NAZARA_SHADER_API SpirvWriter + class NAZARA_SHADER_API SpirvWriter : public ShaderWriter { friend class SpirvAstVisitor; friend class SpirvExpressionLoad; @@ -38,7 +38,7 @@ namespace Nz SpirvWriter(SpirvWriter&&) = delete; ~SpirvWriter() = default; - std::vector Generate(const ShaderAst& shader); + std::vector Generate(const ShaderAst& shader, const States& conditions = {}); void SetEnv(Environment environment); @@ -66,6 +66,8 @@ namespace Nz UInt32 GetPointerTypeId(const ShaderExpressionType& type, SpirvStorageClass storageClass) const; UInt32 GetTypeId(const ShaderExpressionType& type) const; + inline bool IsConditionEnabled(const std::string& condition) const; + UInt32 ReadInputVariable(const std::string& name); std::optional ReadInputVariable(const std::string& name, OnlyCache); UInt32 ReadLocalVariable(const std::string& name); @@ -88,6 +90,7 @@ namespace Nz { const ShaderAst* shader = nullptr; const ShaderAst::Function* currentFunction = nullptr; + const States* states = nullptr; }; struct ExtVar diff --git a/include/Nazara/Shader/SpirvWriter.inl b/include/Nazara/Shader/SpirvWriter.inl index 26012e0d1..44babe815 100644 --- a/include/Nazara/Shader/SpirvWriter.inl +++ b/include/Nazara/Shader/SpirvWriter.inl @@ -7,6 +7,10 @@ namespace Nz { + inline bool SpirvWriter::IsConditionEnabled(const std::string& condition) const + { + return m_context.states->enabledConditions.find(condition) != m_context.states->enabledConditions.end(); + } } #include diff --git a/src/Nazara/Shader/GlslWriter.cpp b/src/Nazara/Shader/GlslWriter.cpp index ccea40fe7..248c92bb7 100644 --- a/src/Nazara/Shader/GlslWriter.cpp +++ b/src/Nazara/Shader/GlslWriter.cpp @@ -48,12 +48,13 @@ namespace Nz { } - std::string GlslWriter::Generate(const ShaderAst& shader) + std::string GlslWriter::Generate(const ShaderAst& shader, const States& conditions) { std::string error; if (!ValidateShader(shader, &error)) throw std::runtime_error("Invalid shader AST: " + error); + m_context.states = &conditions; m_context.shader = &shader; State state; @@ -461,6 +462,21 @@ namespace Nz Append(")"); } + + void GlslWriter::Visit(ShaderNodes::ConditionalExpression& node) + { + if (m_context.states->enabledConditions.count(node.conditionName) != 0) + Visit(node.truePath); + else + Visit(node.falsePath); + } + + void GlslWriter::Visit(ShaderNodes::ConditionalStatement& node) + { + if (m_context.states->enabledConditions.count(node.conditionName) != 0) + Visit(node.statement); + } + void GlslWriter::Visit(ShaderNodes::Constant& node) { std::visit([&](auto&& arg) diff --git a/src/Nazara/Shader/ShaderAst.cpp b/src/Nazara/Shader/ShaderAst.cpp index 236a5e28f..2f43ee23b 100644 --- a/src/Nazara/Shader/ShaderAst.cpp +++ b/src/Nazara/Shader/ShaderAst.cpp @@ -7,6 +7,12 @@ namespace Nz { + void ShaderAst::AddCondition(std::string name) + { + auto& conditionEntry = m_conditions.emplace_back(); + conditionEntry.name = std::move(name); + } + void ShaderAst::AddFunction(std::string name, ShaderNodes::StatementPtr statement, std::vector parameters, ShaderNodes::BasicType returnType) { auto& functionEntry = m_functions.emplace_back(); diff --git a/src/Nazara/Shader/ShaderAstCloner.cpp b/src/Nazara/Shader/ShaderAstCloner.cpp index 90c7c909d..cef0ac694 100644 --- a/src/Nazara/Shader/ShaderAstCloner.cpp +++ b/src/Nazara/Shader/ShaderAstCloner.cpp @@ -91,6 +91,16 @@ namespace Nz PushExpression(ShaderNodes::Cast::Build(node.exprType, expressions.data(), expressionCount)); } + void ShaderAstCloner::Visit(ShaderNodes::ConditionalExpression& node) + { + PushExpression(ShaderNodes::ConditionalExpression::Build(node.conditionName, CloneExpression(node.truePath), CloneExpression(node.falsePath))); + } + + void ShaderAstCloner::Visit(ShaderNodes::ConditionalStatement& node) + { + PushStatement(ShaderNodes::ConditionalStatement::Build(node.conditionName, CloneStatement(node.statement))); + } + void ShaderAstCloner::Visit(ShaderNodes::Constant& node) { PushExpression(ShaderNodes::Constant::Build(node.value)); diff --git a/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp b/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp index 98fdbfee6..b68d5361a 100644 --- a/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp +++ b/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp @@ -47,6 +47,17 @@ namespace Nz } } + void ShaderAstRecursiveVisitor::Visit(ShaderNodes::ConditionalExpression& node) + { + Visit(node.truePath); + Visit(node.falsePath); + } + + void ShaderAstRecursiveVisitor::Visit(ShaderNodes::ConditionalStatement& node) + { + Visit(node.statement); + } + void ShaderAstRecursiveVisitor::Visit(ShaderNodes::Constant& /*node*/) { /* Nothing to do */ diff --git a/src/Nazara/Shader/ShaderAstSerializer.cpp b/src/Nazara/Shader/ShaderAstSerializer.cpp index 4f1c214d2..5184d980d 100644 --- a/src/Nazara/Shader/ShaderAstSerializer.cpp +++ b/src/Nazara/Shader/ShaderAstSerializer.cpp @@ -47,6 +47,16 @@ namespace Nz Serialize(node); } + void Visit(ShaderNodes::ConditionalExpression& node) override + { + Serialize(node); + } + + void Visit(ShaderNodes::ConditionalStatement& node) override + { + Serialize(node); + } + void Visit(ShaderNodes::Constant& node) override { Serialize(node); @@ -179,6 +189,19 @@ namespace Nz Node(expr); } + void ShaderAstSerializerBase::Serialize(ShaderNodes::ConditionalExpression& node) + { + Value(node.conditionName); + Node(node.truePath); + Node(node.falsePath); + } + + void ShaderAstSerializerBase::Serialize(ShaderNodes::ConditionalStatement& node) + { + Value(node.conditionName); + Node(node.statement); + } + void ShaderAstSerializerBase::Serialize(ShaderNodes::Constant& node) { UInt32 typeIndex; @@ -306,6 +329,12 @@ namespace Nz } }; + // Conditions + m_stream << UInt32(shader.GetConditionCount()); + for (const auto& cond : shader.GetConditions()) + m_stream << cond.name; + + // Structs m_stream << UInt32(shader.GetStructCount()); for (const auto& s : shader.GetStructs()) { @@ -318,9 +347,11 @@ namespace Nz } } + // Inputs / Outputs SerializeInputOutput(shader.GetInputs()); SerializeInputOutput(shader.GetOutputs()); + // Uniforms m_stream << UInt32(shader.GetUniformCount()); for (const auto& uniform : shader.GetUniforms()) { @@ -336,6 +367,7 @@ namespace Nz m_stream << UInt32(uniform.memoryLayout.value()); } + // Functions m_stream << UInt32(shader.GetFunctionCount()); for (const auto& func : shader.GetFunctions()) { @@ -495,6 +527,18 @@ namespace Nz ShaderAst shader(static_cast(shaderStage)); + // Conditions + UInt32 conditionCount; + m_stream >> conditionCount; + for (UInt32 i = 0; i < conditionCount; ++i) + { + std::string conditionName; + Value(conditionName); + + shader.AddCondition(std::move(conditionName)); + } + + // Structs UInt32 structCount; m_stream >> structCount; for (UInt32 i = 0; i < structCount; ++i) @@ -514,6 +558,7 @@ namespace Nz shader.AddStruct(std::move(structName), std::move(members)); } + // Inputs UInt32 inputCount; m_stream >> inputCount; for (UInt32 i = 0; i < inputCount; ++i) @@ -529,6 +574,7 @@ namespace Nz shader.AddInput(std::move(inputName), std::move(inputType), location); } + // Outputs UInt32 outputCount; m_stream >> outputCount; for (UInt32 i = 0; i < outputCount; ++i) @@ -544,6 +590,7 @@ namespace Nz shader.AddOutput(std::move(outputName), std::move(outputType), location); } + // Uniforms UInt32 uniformCount; m_stream >> uniformCount; for (UInt32 i = 0; i < uniformCount; ++i) @@ -561,6 +608,7 @@ namespace Nz shader.AddUniform(std::move(name), std::move(type), std::move(binding), std::move(memLayout)); } + // Functions UInt32 funcCount; m_stream >> funcCount; for (UInt32 i = 0; i < funcCount; ++i) @@ -614,6 +662,7 @@ namespace Nz HandleType(Branch); HandleType(Cast); HandleType(Constant); + HandleType(ConditionalExpression); HandleType(ConditionalStatement); HandleType(DeclareVariable); HandleType(ExpressionStatement); diff --git a/src/Nazara/Shader/ShaderAstValidator.cpp b/src/Nazara/Shader/ShaderAstValidator.cpp index 95ae20df0..643ff2d85 100644 --- a/src/Nazara/Shader/ShaderAstValidator.cpp +++ b/src/Nazara/Shader/ShaderAstValidator.cpp @@ -241,6 +241,35 @@ namespace Nz ShaderAstRecursiveVisitor::Visit(node); } + void ShaderAstValidator::Visit(ShaderNodes::ConditionalExpression& node) + { + MandatoryNode(node.truePath); + MandatoryNode(node.falsePath); + + for (std::size_t i = 0; i < m_shader.GetConditionCount(); ++i) + { + const auto& condition = m_shader.GetCondition(i); + if (condition.name == node.conditionName) + return; + } + + throw AstError{ "Condition not found" }; + } + + void ShaderAstValidator::Visit(ShaderNodes::ConditionalStatement& node) + { + MandatoryNode(node.statement); + + for (std::size_t i = 0; i < m_shader.GetConditionCount(); ++i) + { + const auto& condition = m_shader.GetCondition(i); + if (condition.name == node.conditionName) + return; + } + + throw AstError{ "Condition not found" }; + } + void ShaderAstValidator::Visit(ShaderNodes::Constant& /*node*/) { } diff --git a/src/Nazara/Shader/ShaderAstVisitor.cpp b/src/Nazara/Shader/ShaderAstVisitor.cpp index 53325c9ca..719e3ad99 100644 --- a/src/Nazara/Shader/ShaderAstVisitor.cpp +++ b/src/Nazara/Shader/ShaderAstVisitor.cpp @@ -9,19 +9,6 @@ namespace Nz { ShaderAstVisitor::~ShaderAstVisitor() = default; - void ShaderAstVisitor::EnableCondition(const std::string& name, bool cond) - { - if (cond) - m_conditions.insert(name); - else - m_conditions.erase(name); - } - - bool ShaderAstVisitor::IsConditionEnabled(const std::string& name) const - { - return m_conditions.count(name) != 0; - } - void ShaderAstVisitor::Visit(const ShaderNodes::NodePtr& node) { node->Visit(*this); diff --git a/src/Nazara/Shader/ShaderAstVisitorExcept.cpp b/src/Nazara/Shader/ShaderAstVisitorExcept.cpp index 419d073bb..85ae826d1 100644 --- a/src/Nazara/Shader/ShaderAstVisitorExcept.cpp +++ b/src/Nazara/Shader/ShaderAstVisitorExcept.cpp @@ -33,6 +33,16 @@ namespace Nz throw std::runtime_error("unhandled Cast node"); } + void ShaderAstVisitorExcept::Visit(ShaderNodes::ConditionalExpression& /*node*/) + { + throw std::runtime_error("unhandled ConditionalExpression node"); + } + + void ShaderAstVisitorExcept::Visit(ShaderNodes::ConditionalStatement& /*node*/) + { + throw std::runtime_error("unhandled ConditionalStatement node"); + } + void ShaderAstVisitorExcept::Visit(ShaderNodes::Constant& /*node*/) { throw std::runtime_error("unhandled Constant node"); diff --git a/src/Nazara/Shader/ShaderNodes.cpp b/src/Nazara/Shader/ShaderNodes.cpp index bdc2897db..6530c1713 100644 --- a/src/Nazara/Shader/ShaderNodes.cpp +++ b/src/Nazara/Shader/ShaderNodes.cpp @@ -26,8 +26,7 @@ namespace Nz::ShaderNodes void ConditionalStatement::Visit(ShaderAstVisitor& visitor) { - if (visitor.IsConditionEnabled(conditionName)) - statement->Visit(visitor); + visitor.Visit(*this); } @@ -204,6 +203,18 @@ namespace Nz::ShaderNodes } + ShaderExpressionType ConditionalExpression::GetExpressionType() const + { + assert(truePath->GetExpressionType() == falsePath->GetExpressionType()); + return truePath->GetExpressionType(); + } + + void ConditionalExpression::Visit(ShaderAstVisitor& visitor) + { + visitor.Visit(*this); + } + + ExpressionCategory SwizzleOp::GetExpressionCategory() const { return expression->GetExpressionCategory(); diff --git a/src/Nazara/Shader/SpirvAstVisitor.cpp b/src/Nazara/Shader/SpirvAstVisitor.cpp index 4c419f987..2cb244496 100644 --- a/src/Nazara/Shader/SpirvAstVisitor.cpp +++ b/src/Nazara/Shader/SpirvAstVisitor.cpp @@ -313,6 +313,20 @@ namespace Nz PushResultId(resultId); } + void SpirvAstVisitor::Visit(ShaderNodes::ConditionalExpression& node) + { + if (m_writer.IsConditionEnabled(node.conditionName)) + Visit(node.truePath); + else + Visit(node.falsePath); + } + + void SpirvAstVisitor::Visit(ShaderNodes::ConditionalStatement& node) + { + if (m_writer.IsConditionEnabled(node.conditionName)) + Visit(node.statement); + } + void SpirvAstVisitor::Visit(ShaderNodes::Constant& node) { std::visit([&] (const auto& value) diff --git a/src/Nazara/Shader/SpirvWriter.cpp b/src/Nazara/Shader/SpirvWriter.cpp index 45e1785b2..c8ad4d4b4 100644 --- a/src/Nazara/Shader/SpirvWriter.cpp +++ b/src/Nazara/Shader/SpirvWriter.cpp @@ -33,7 +33,8 @@ namespace Nz using LocalContainer = std::unordered_set>; using ParameterContainer = std::unordered_set< std::shared_ptr>; - PreVisitor(SpirvConstantCache& constantCache) : + PreVisitor(const SpirvWriter::States& conditions, SpirvConstantCache& constantCache) : + m_conditions(conditions), m_constantCache(constantCache) { } @@ -49,6 +50,20 @@ namespace Nz ShaderAstRecursiveVisitor::Visit(node); } + void Visit(ShaderNodes::ConditionalExpression& node) override + { + if (m_conditions.enabledConditions.count(node.conditionName) != 0) + Visit(node.truePath); + else + Visit(node.falsePath); + } + + void Visit(ShaderNodes::ConditionalStatement& node) override + { + if (m_conditions.enabledConditions.count(node.conditionName) != 0) + Visit(node.statement); + } + void Visit(ShaderNodes::Constant& node) override { std::visit([&](auto&& arg) @@ -126,6 +141,7 @@ namespace Nz ParameterContainer paramVars; private: + const SpirvWriter::States& m_conditions; SpirvConstantCache& m_constantCache; }; @@ -193,13 +209,14 @@ namespace Nz { } - std::vector SpirvWriter::Generate(const ShaderAst& shader) + std::vector SpirvWriter::Generate(const ShaderAst& shader, const States& conditions) { std::string error; if (!ValidateShader(shader, &error)) throw std::runtime_error("Invalid shader AST: " + error); m_context.shader = &shader; + m_context.states = &conditions; State state; m_currentState = &state; @@ -212,7 +229,7 @@ namespace Nz ShaderAstCloner cloner; - PreVisitor preVisitor(state.constantTypeCache); + PreVisitor preVisitor(conditions, state.constantTypeCache); for (const auto& func : shader.GetFunctions()) { functionStatements.emplace_back(cloner.Clone(func.statement)); @@ -450,7 +467,7 @@ namespace Nz m_environment = std::move(environment); } - UInt32 Nz::SpirvWriter::AllocateResultId() + UInt32 SpirvWriter::AllocateResultId() { return m_currentState->nextVarIndex++; } diff --git a/src/ShaderNode/DataModels/ConditionalExpression.cpp b/src/ShaderNode/DataModels/ConditionalExpression.cpp new file mode 100644 index 000000000..d034ada49 --- /dev/null +++ b/src/ShaderNode/DataModels/ConditionalExpression.cpp @@ -0,0 +1,240 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +ConditionalExpression::ConditionalExpression(ShaderGraph& graph) : +ShaderNode(graph) +{ + m_onConditionListUpdateSlot.Connect(GetGraph().OnConditionListUpdate, [&](ShaderGraph*) { OnConditionListUpdate(); }); + m_onConditionUpdateSlot.Connect(GetGraph().OnConditionUpdate, [&](ShaderGraph*, std::size_t conditionIndex) + { + if (m_currentConditionIndex == conditionIndex) + { + UpdatePreview(); + Q_EMIT dataUpdated(0); + } + }); + + if (graph.GetConditionCount() > 0) + { + m_currentConditionIndex = 0; + UpdateConditionText(); + } + + EnablePreview(); + SetPreviewSize({ 128, 128 }); + UpdatePreview(); +} + +Nz::ShaderNodes::ExpressionPtr ConditionalExpression::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const +{ + assert(count == 2); + + if (!m_currentConditionIndex) + throw std::runtime_error("no condition"); + + const ShaderGraph& graph = GetGraph(); + + const auto& conditionEntry = graph.GetCondition(*m_currentConditionIndex); + return Nz::ShaderBuilder::ConditionalExpression(conditionEntry.name, expressions[0], expressions[1]); +} + +QString ConditionalExpression::caption() const +{ + return "ConditionalExpression (" + QString::fromStdString(m_currentConditionText) + ")"; +} + +QString ConditionalExpression::name() const +{ + return "ConditionalExpression"; +} + +unsigned int ConditionalExpression::nPorts(QtNodes::PortType portType) const +{ + switch (portType) + { + case QtNodes::PortType::In: return 2; + case QtNodes::PortType::Out: return 1; + } + + return 0; +} + +void ConditionalExpression::BuildNodeEdition(QFormLayout* layout) +{ + ShaderNode::BuildNodeEdition(layout); + + QComboBox* conditionSelection = new QComboBox; + for (const auto& conditionEntry : GetGraph().GetConditions()) + conditionSelection->addItem(QString::fromStdString(conditionEntry.name)); + + if (m_currentConditionIndex) + conditionSelection->setCurrentIndex(int(*m_currentConditionIndex)); + else + conditionSelection->setCurrentIndex(-1); + + connect(conditionSelection, qOverload(&QComboBox::currentIndexChanged), [&](int index) + { + if (index >= 0) + m_currentConditionIndex = static_cast(index); + else + m_currentConditionIndex.reset(); + + UpdateConditionText(); + UpdatePreview(); + + Q_EMIT dataUpdated(0); + }); + + layout->addRow(tr("Condition"), conditionSelection); +} + +auto ConditionalExpression::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const -> QtNodes::NodeDataType +{ + return VecData::Type(); + + assert(portType == QtNodes::PortType::Out); + assert(portIndex == 0); + + if (!m_truePath && !m_falsePath) + return VecData::Type(); + + return (m_truePath) ? m_truePath->type() : m_falsePath->type(); +} + +QString ConditionalExpression::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const +{ + switch (portType) + { + case QtNodes::PortType::In: + { + switch (portIndex) + { + case 0: + return "True path"; + + case 1: + return "False path"; + + default: + break; + } + } + + default: + break; + } + + return QString{}; +} + +bool ConditionalExpression::portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex /*portIndex*/) const +{ + return portType == QtNodes::PortType::In; +} + +std::shared_ptr ConditionalExpression::outData(QtNodes::PortIndex port) +{ + if (!m_currentConditionIndex) + return nullptr; + + assert(port == 0); + return (GetGraph().IsConditionEnabled(*m_currentConditionIndex)) ? m_truePath : m_falsePath; +} + +void ConditionalExpression::restore(const QJsonObject& data) +{ + m_currentConditionText = data["condition_name"].toString().toStdString(); + OnConditionListUpdate(); + + ShaderNode::restore(data); +} + +QJsonObject ConditionalExpression::save() const +{ + QJsonObject data = ShaderNode::save(); + data["condition_name"] = QString::fromStdString(m_currentConditionText); + + return data; +} + +void ConditionalExpression::setInData(std::shared_ptr value, int index) +{ + assert(index == 0 || index == 1); + + if (index == 0) + m_truePath = std::move(value); + else + m_falsePath = std::move(value); + + UpdatePreview(); +} + +QtNodes::NodeValidationState ConditionalExpression::validationState() const +{ + if (!m_truePath || !m_falsePath) + return QtNodes::NodeValidationState::Error; + + return QtNodes::NodeValidationState::Valid; +} + +QString ConditionalExpression::validationMessage() const +{ + if (!m_truePath || !m_falsePath) + return "Missing input"; + + return QString(); +} + +bool ConditionalExpression::ComputePreview(QPixmap& pixmap) +{ + if (!m_currentConditionIndex) + return false; + + auto input = outData(0); + if (!input || input->type().id != VecData::Type().id) + return false; + + assert(dynamic_cast(input.get()) != nullptr); + const VecData& data = static_cast(*input); + + pixmap = QPixmap::fromImage(data.preview.GenerateImage()); + return true; +} + +void ConditionalExpression::OnConditionListUpdate() +{ + m_currentConditionIndex.reset(); + + std::size_t conditionIndex = 0; + for (const auto& conditionEntry : GetGraph().GetConditions()) + { + if (conditionEntry.name == m_currentConditionText) + { + m_currentConditionIndex = conditionIndex; + break; + } + + conditionIndex++; + } +} + +void ConditionalExpression::UpdateConditionText() +{ + if (m_currentConditionIndex) + { + auto& condition = GetGraph().GetCondition(*m_currentConditionIndex); + m_currentConditionText = condition.name; + } + else + m_currentConditionText.clear(); +} diff --git a/src/ShaderNode/DataModels/ConditionalExpression.hpp b/src/ShaderNode/DataModels/ConditionalExpression.hpp new file mode 100644 index 000000000..a89d6c40c --- /dev/null +++ b/src/ShaderNode/DataModels/ConditionalExpression.hpp @@ -0,0 +1,58 @@ +#pragma once + +#ifndef NAZARA_SHADERNODES_CONDITIONALEXPRESSION_HPP +#define NAZARA_SHADERNODES_CONDITIONALEXPRESSION_HPP + +#include +#include +#include +#include +#include + +class ConditionalExpression : public ShaderNode +{ + public: + ConditionalExpression(ShaderGraph& graph); + ~ConditionalExpression() = default; + + void BuildNodeEdition(QFormLayout* layout) override; + + Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const override; + + QString caption() const override; + QString name() const override; + + unsigned int nPorts(QtNodes::PortType portType) const override; + + QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; + + QString portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; + bool portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; + + std::shared_ptr outData(QtNodes::PortIndex port) override; + + void restore(const QJsonObject& data) override; + QJsonObject save() const override; + + void setInData(std::shared_ptr value, int index) override; + + QtNodes::NodeValidationState validationState() const override; + QString validationMessage() const override; + + private: + bool ComputePreview(QPixmap& pixmap) override; + void OnConditionListUpdate(); + void UpdateConditionText(); + + NazaraSlot(ShaderGraph, OnConditionListUpdate, m_onConditionListUpdateSlot); + NazaraSlot(ShaderGraph, OnConditionUpdate, m_onConditionUpdateSlot); + + std::optional m_currentConditionIndex; + std::shared_ptr m_falsePath; + std::shared_ptr m_truePath; + std::string m_currentConditionText; +}; + +#include + +#endif diff --git a/src/ShaderNode/DataModels/ConditionalExpression.inl b/src/ShaderNode/DataModels/ConditionalExpression.inl new file mode 100644 index 000000000..67cd1a5e7 --- /dev/null +++ b/src/ShaderNode/DataModels/ConditionalExpression.inl @@ -0,0 +1,2 @@ +#include +#include diff --git a/src/ShaderNode/DataModels/OutputValue.cpp b/src/ShaderNode/DataModels/OutputValue.cpp index 9a2cb7030..7ffb4df91 100644 --- a/src/ShaderNode/DataModels/OutputValue.cpp +++ b/src/ShaderNode/DataModels/OutputValue.cpp @@ -238,16 +238,16 @@ void OutputValue::OnOutputListUpdate() { m_currentOutputIndex.reset(); - std::size_t inputIndex = 0; - for (const auto& inputEntry : GetGraph().GetOutputs()) + std::size_t outputIndex = 0; + for (const auto& outputEntry : GetGraph().GetOutputs()) { - if (inputEntry.name == m_currentOutputText) + if (outputEntry.name == m_currentOutputText) { - m_currentOutputIndex = inputIndex; + m_currentOutputIndex = outputIndex; break; } - inputIndex++; + outputIndex++; } } diff --git a/src/ShaderNode/DataModels/ShaderNode.cpp b/src/ShaderNode/DataModels/ShaderNode.cpp index 7ed3bc84c..e596a6a6d 100644 --- a/src/ShaderNode/DataModels/ShaderNode.cpp +++ b/src/ShaderNode/DataModels/ShaderNode.cpp @@ -8,6 +8,7 @@ ShaderNode::ShaderNode(ShaderGraph& graph) : m_previewSize(64, 64), m_pixmapLabel(nullptr), +m_embeddedWidget(nullptr), m_graph(graph), m_enableCustomVariableName(true), m_isPreviewEnabled(false) @@ -86,7 +87,24 @@ void ShaderNode::EnablePreview(bool enable) QWidget* ShaderNode::embeddedWidget() { - return m_pixmapLabel; + if (!m_embeddedWidget) + { + QWidget* embedded = EmbeddedWidget(); + if (embedded) + { + QVBoxLayout* layout = new QVBoxLayout; + layout->addWidget(embedded); + layout->addWidget(m_pixmapLabel); + + m_embeddedWidget = new QWidget; + m_embeddedWidget->setStyleSheet("background-color: rgba(0,0,0,0)"); + m_embeddedWidget->setLayout(layout); + } + else + m_embeddedWidget = m_pixmapLabel; + } + + return m_embeddedWidget; } void ShaderNode::restore(const QJsonObject& data) @@ -121,6 +139,11 @@ bool ShaderNode::ComputePreview(QPixmap& /*pixmap*/) return false; } +QWidget* ShaderNode::EmbeddedWidget() +{ + return nullptr; +} + void ShaderNode::UpdatePreview() { if (!m_pixmap) diff --git a/src/ShaderNode/DataModels/ShaderNode.hpp b/src/ShaderNode/DataModels/ShaderNode.hpp index 6d3dd5cc1..874fce54f 100644 --- a/src/ShaderNode/DataModels/ShaderNode.hpp +++ b/src/ShaderNode/DataModels/ShaderNode.hpp @@ -41,6 +41,7 @@ class ShaderNode : public QtNodes::NodeDataModel protected: inline void DisableCustomVariableName(); inline void EnableCustomVariableName(bool enable = true); + virtual QWidget* EmbeddedWidget(); void UpdatePreview(); private: @@ -48,6 +49,7 @@ class ShaderNode : public QtNodes::NodeDataModel Nz::Vector2i m_previewSize; QLabel* m_pixmapLabel; + QWidget* m_embeddedWidget; std::optional m_pixmap; std::string m_variableName; ShaderGraph& m_graph; diff --git a/src/ShaderNode/ShaderGraph.cpp b/src/ShaderNode/ShaderGraph.cpp index a1799df3b..9a93dcf8f 100644 --- a/src/ShaderNode/ShaderGraph.cpp +++ b/src/ShaderNode/ShaderGraph.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -124,6 +125,17 @@ std::size_t ShaderGraph::AddBuffer(std::string name, BufferType bufferType, std: return index; } +std::size_t ShaderGraph::AddCondition(std::string name) +{ + std::size_t index = m_conditions.size(); + auto& conditionEntry = m_conditions.emplace_back(); + conditionEntry.name = std::move(name); + + OnConditionListUpdate(this); + + return index; +} + std::size_t ShaderGraph::AddInput(std::string name, PrimitiveType type, InputRole role, std::size_t roleIndex, std::size_t locationIndex) { std::size_t index = m_inputs.size(); @@ -185,6 +197,7 @@ void ShaderGraph::Clear() m_flowScene.clear(); m_buffers.clear(); + m_conditions.clear(); m_inputs.clear(); m_structs.clear(); m_outputs.clear(); @@ -197,6 +210,15 @@ void ShaderGraph::Clear() OnTextureListUpdate(this); } +void ShaderGraph::EnableCondition(std::size_t conditionIndex, bool enable) +{ + assert(conditionIndex < m_conditions.size()); + auto& conditionEntry = m_conditions[conditionIndex]; + conditionEntry.enabled = enable; + + OnConditionUpdate(this, conditionIndex); +} + void ShaderGraph::Load(const QJsonObject& data) { Clear(); @@ -218,6 +240,17 @@ void ShaderGraph::Load(const QJsonObject& data) OnBufferListUpdate(this); + QJsonArray conditionArray = data["conditions"].toArray(); + for (const auto& conditionDocRef : conditionArray) + { + QJsonObject conditionDoc = conditionDocRef.toObject(); + + ConditionEntry& condition = m_conditions.emplace_back(); + condition.name = conditionDoc["name"].toString().toStdString(); + } + + OnConditionListUpdate(this); + QJsonArray inputArray = data["inputs"].toArray(); for (const auto& inputDocRef : inputArray) { @@ -312,6 +345,18 @@ QJsonObject ShaderGraph::Save() } sceneJson["buffers"] = bufferArray; + QJsonArray conditionArray; + { + for (const auto& condition : m_conditions) + { + QJsonObject inputDoc; + inputDoc["name"] = QString::fromStdString(condition.name); + + conditionArray.append(inputDoc); + } + } + sceneJson["conditions"] = conditionArray; + QJsonArray inputArray; { for (const auto& input : m_inputs) @@ -436,10 +481,15 @@ Nz::ShaderNodes::StatementPtr ShaderGraph::ToAst() (*it)++; }; + std::vector outputNodes; + m_flowScene.iterateOverNodes([&](QtNodes::Node* node) { if (node->nodeDataModel()->nPorts(QtNodes::PortType::Out) == 0) + { DetectVariables(node); + outputNodes.push_back(node); + } }); QHash variableExpressions; @@ -510,13 +560,8 @@ Nz::ShaderNodes::StatementPtr ShaderGraph::ToAst() return expression; }; - m_flowScene.iterateOverNodes([&](QtNodes::Node* node) - { - if (node->nodeDataModel()->nPorts(QtNodes::PortType::Out) == 0) - { - statements.emplace_back(Nz::ShaderBuilder::ExprStatement(HandleNode(node))); - } - }); + for (QtNodes::Node* node : outputNodes) + statements.emplace_back(Nz::ShaderBuilder::ExprStatement(HandleNode(node))); return Nz::ShaderNodes::StatementBlock::Build(std::move(statements)); } @@ -551,6 +596,15 @@ void ShaderGraph::UpdateBuffer(std::size_t bufferIndex, std::string name, Buffer OnBufferUpdate(this, bufferIndex); } +void ShaderGraph::UpdateCondition(std::size_t conditionIndex, std::string condition) +{ + assert(conditionIndex < m_conditions.size()); + auto& conditionEntry = m_conditions[conditionIndex]; + conditionEntry.name = std::move(condition); + + OnConditionUpdate(this, conditionIndex); +} + void ShaderGraph::UpdateInput(std::size_t inputIndex, std::string name, PrimitiveType type, InputRole role, std::size_t roleIndex, std::size_t locationIndex) { assert(inputIndex < m_inputs.size()); @@ -687,6 +741,7 @@ std::shared_ptr ShaderGraph::BuildRegistry() RegisterShaderNode(*this, registry, "Casts"); RegisterShaderNode(*this, registry, "Casts"); RegisterShaderNode(*this, registry, "Casts"); + RegisterShaderNode(*this, registry, "Shader"); RegisterShaderNode(*this, registry, "Constants"); RegisterShaderNode(*this, registry, "Inputs"); RegisterShaderNode(*this, registry, "Outputs"); diff --git a/src/ShaderNode/ShaderGraph.hpp b/src/ShaderNode/ShaderGraph.hpp index 1df336ce6..44fb4bf77 100644 --- a/src/ShaderNode/ShaderGraph.hpp +++ b/src/ShaderNode/ShaderGraph.hpp @@ -18,6 +18,7 @@ class ShaderGraph { public: struct BufferEntry; + struct ConditionEntry; struct InputEntry; struct OutputEntry; struct StructEntry; @@ -28,6 +29,7 @@ class ShaderGraph ~ShaderGraph(); std::size_t AddBuffer(std::string name, BufferType bufferType, std::size_t structIndex, std::size_t bindingIndex); + std::size_t AddCondition(std::string name); std::size_t AddInput(std::string name, PrimitiveType type, InputRole role, std::size_t roleIndex, std::size_t locationIndex); std::size_t AddOutput(std::string name, PrimitiveType type, std::size_t locationIndex); std::size_t AddStruct(std::string name, std::vector members); @@ -35,9 +37,14 @@ class ShaderGraph void Clear(); + void EnableCondition(std::size_t conditionIndex, bool enable); + inline const BufferEntry& GetBuffer(std::size_t bufferIndex) const; inline std::size_t GetBufferCount() const; inline const std::vector& GetBuffers() const; + inline const ConditionEntry& GetCondition(std::size_t conditionIndex) const; + inline std::size_t GetConditionCount() const; + inline const std::vector& GetConditions() const; inline const InputEntry& GetInput(std::size_t bufferIndex) const; inline std::size_t GetInputCount() const; inline const std::vector& GetInputs() const; @@ -54,6 +61,8 @@ class ShaderGraph inline const std::vector& GetTextures() const; inline ShaderType GetType() const; + inline bool IsConditionEnabled(std::size_t conditionIndex) const; + void Load(const QJsonObject& data); QJsonObject Save(); @@ -61,6 +70,7 @@ class ShaderGraph Nz::ShaderExpressionType ToShaderExpressionType(const std::variant& type) const; void UpdateBuffer(std::size_t bufferIndex, std::string name, BufferType bufferType, std::size_t structIndex, std::size_t bindingIndex); + void UpdateCondition(std::size_t conditionIndex, std::string condition); void UpdateInput(std::size_t inputIndex, std::string name, PrimitiveType type, InputRole role, std::size_t roleIndex, std::size_t locationIndex); void UpdateOutput(std::size_t outputIndex, std::string name, PrimitiveType type, std::size_t locationIndex); void UpdateStruct(std::size_t structIndex, std::string name, std::vector members); @@ -76,6 +86,12 @@ class ShaderGraph BufferType type; }; + struct ConditionEntry + { + std::string name; + bool enabled = false; + }; + struct InputEntry { std::size_t locationIndex; @@ -113,7 +129,9 @@ class ShaderGraph }; NazaraSignal(OnBufferListUpdate, ShaderGraph*); - NazaraSignal(OnBufferUpdate, ShaderGraph*, std::size_t /*outputIndex*/); + NazaraSignal(OnBufferUpdate, ShaderGraph*, std::size_t /*bufferIndex*/); + NazaraSignal(OnConditionListUpdate, ShaderGraph*); + NazaraSignal(OnConditionUpdate, ShaderGraph*, std::size_t /*conditionIndex*/); NazaraSignal(OnInputListUpdate, ShaderGraph*); NazaraSignal(OnInputUpdate, ShaderGraph*, std::size_t /*inputIndex*/); NazaraSignal(OnOutputListUpdate, ShaderGraph*); @@ -136,6 +154,7 @@ class ShaderGraph QtNodes::FlowScene m_flowScene; std::vector m_buffers; + std::vector m_conditions; std::vector m_inputs; std::vector m_outputs; std::vector m_structs; diff --git a/src/ShaderNode/ShaderGraph.inl b/src/ShaderNode/ShaderGraph.inl index afa867dcd..11ba6f5dc 100644 --- a/src/ShaderNode/ShaderGraph.inl +++ b/src/ShaderNode/ShaderGraph.inl @@ -16,6 +16,22 @@ inline auto ShaderGraph::GetBuffers() const -> const std::vector& return m_buffers; } +inline auto ShaderGraph::GetCondition(std::size_t conditionIndex) const -> const ConditionEntry& +{ + assert(conditionIndex < m_conditions.size()); + return m_conditions[conditionIndex]; +} + +inline std::size_t ShaderGraph::GetConditionCount() const +{ + return m_conditions.size(); +} + +inline auto ShaderGraph::GetConditions() const -> const std::vector& +{ + return m_conditions; +} + inline auto ShaderGraph::GetInput(std::size_t inputIndex) const -> const InputEntry& { assert(inputIndex < m_inputs.size()); @@ -95,3 +111,9 @@ inline ShaderType ShaderGraph::GetType() const return m_type; } +inline bool ShaderGraph::IsConditionEnabled(std::size_t conditionIndex) const +{ + assert(conditionIndex < m_conditions.size()); + return m_conditions[conditionIndex].enabled; +} + diff --git a/src/ShaderNode/Widgets/ConditionEditDialog.cpp b/src/ShaderNode/Widgets/ConditionEditDialog.cpp new file mode 100644 index 000000000..4d04932a6 --- /dev/null +++ b/src/ShaderNode/Widgets/ConditionEditDialog.cpp @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +ConditionEditDialog::ConditionEditDialog(QWidget* parent) : +QDialog(parent) +{ + setWindowTitle(tr("Condition edit dialog")); + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + + m_conditionName = new QLineEdit; + + QFormLayout* formLayout = new QFormLayout; + formLayout->addRow(tr("Name"), m_conditionName); + + QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + connect(buttonBox, &QDialogButtonBox::accepted, this, &ConditionEditDialog::OnAccept); + connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + + QVBoxLayout* verticalLayout = new QVBoxLayout; + verticalLayout->addLayout(formLayout); + verticalLayout->addWidget(buttonBox); + + setLayout(verticalLayout); +} + +ConditionEditDialog::ConditionEditDialog(const ConditionInfo& condition, QWidget* parent) : +ConditionEditDialog(parent) +{ + m_conditionName->setText(QString::fromStdString(condition.name)); +} + +ConditionInfo ConditionEditDialog::GetConditionInfo() const +{ + ConditionInfo inputInfo; + inputInfo.name = m_conditionName->text().toStdString(); + + return inputInfo; +} + +void ConditionEditDialog::OnAccept() +{ + if (m_conditionName->text().isEmpty()) + { + QMessageBox::critical(this, tr("Empty name"), tr("Condition name must be set"), QMessageBox::Ok); + return; + } + + accept(); +} diff --git a/src/ShaderNode/Widgets/ConditionEditDialog.hpp b/src/ShaderNode/Widgets/ConditionEditDialog.hpp new file mode 100644 index 000000000..22cebb2f8 --- /dev/null +++ b/src/ShaderNode/Widgets/ConditionEditDialog.hpp @@ -0,0 +1,35 @@ +#pragma once + +#ifndef NAZARA_SHADERNODES_CONDITIONEDITDIALOG_HPP +#define NAZARA_SHADERNODES_CONDITIONEDITDIALOG_HPP + +#include +#include + +class QComboBox; +class QLineEdit; +class QSpinBox; + +struct ConditionInfo +{ + std::string name; +}; + +class ConditionEditDialog : public QDialog +{ + public: + ConditionEditDialog(QWidget* parent = nullptr); + ConditionEditDialog(const ConditionInfo& input, QWidget* parent = nullptr); + ~ConditionEditDialog() = default; + + ConditionInfo GetConditionInfo() const; + + private: + void OnAccept(); + + QLineEdit* m_conditionName; +}; + +#include + +#endif diff --git a/src/ShaderNode/Widgets/ConditionEditDialog.inl b/src/ShaderNode/Widgets/ConditionEditDialog.inl new file mode 100644 index 000000000..157a5289b --- /dev/null +++ b/src/ShaderNode/Widgets/ConditionEditDialog.inl @@ -0,0 +1 @@ +#include diff --git a/src/ShaderNode/Widgets/ConditionEditor.cpp b/src/ShaderNode/Widgets/ConditionEditor.cpp new file mode 100644 index 000000000..2b8c40ab8 --- /dev/null +++ b/src/ShaderNode/Widgets/ConditionEditor.cpp @@ -0,0 +1,117 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +ConditionEditor::ConditionEditor(ShaderGraph& graph) : +m_shaderGraph(graph) +{ + QTableView* tableView = new QTableView; + m_model = new QStandardItemModel(0, 2, tableView); + tableView->setModel(m_model); + + m_model->setHorizontalHeaderLabels({ tr("Condition"), tr("Enabled") }); + + connect(tableView, &QTableView::doubleClicked, [this](const QModelIndex& index) + { + if (index.column() == 0) + OnEditCondition(index.row()); + }); + + connect(m_model, &QStandardItemModel::itemChanged, [this](QStandardItem* item) + { + if (item->column() == 1) + { + std::size_t conditionIndex = static_cast(item->row()); + bool value = item->checkState() == Qt::Checked; + m_shaderGraph.EnableCondition(conditionIndex, value); + } + }); + + + QPushButton* addStructButton = new QPushButton(tr("Add condition...")); + connect(addStructButton, &QPushButton::released, this, &ConditionEditor::OnAddCondition); + + m_layout = new QVBoxLayout; + m_layout->addWidget(tableView); + m_layout->addWidget(addStructButton); + + setLayout(m_layout); + + m_onConditionListUpdateSlot.Connect(m_shaderGraph.OnConditionListUpdate, this, &ConditionEditor::OnConditionListUpdate); + m_onConditionUpdateSlot.Connect(m_shaderGraph.OnConditionUpdate, this, &ConditionEditor::OnConditionUpdate); + + RefreshConditions(); +} + +void ConditionEditor::OnAddCondition() +{ + ConditionEditDialog* dialog = new ConditionEditDialog(this); + dialog->setAttribute(Qt::WA_DeleteOnClose, true); + connect(dialog, &QDialog::accepted, [this, dialog] + { + ConditionInfo conditionInfo = dialog->GetConditionInfo(); + m_shaderGraph.AddCondition(std::move(conditionInfo.name)); + }); + + dialog->open(); +} + +void ConditionEditor::OnEditCondition(int conditionIndex) +{ + const auto& conditionInfo = m_shaderGraph.GetCondition(conditionIndex); + + ConditionInfo info; + info.name = conditionInfo.name; + + ConditionEditDialog* dialog = new ConditionEditDialog(info, this); + dialog->setAttribute(Qt::WA_DeleteOnClose, true); + connect(dialog, &QDialog::accepted, [this, dialog, conditionIndex] + { + ConditionInfo conditionInfo = dialog->GetConditionInfo(); + + m_shaderGraph.UpdateCondition(conditionIndex, std::move(conditionInfo.name)); + }); + + dialog->open(); +} + +void ConditionEditor::OnConditionListUpdate(ShaderGraph* /*graph*/) +{ + RefreshConditions(); +} + +void ConditionEditor::OnConditionUpdate(ShaderGraph* /*graph*/, std::size_t conditionIndex) +{ + const auto& conditionEntry = m_shaderGraph.GetCondition(conditionIndex); + + int row = int(conditionIndex); + m_model->item(row, 0)->setText(QString::fromStdString(conditionEntry.name)); + m_model->item(row, 1)->setCheckState((conditionEntry.enabled) ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); +} + +void ConditionEditor::RefreshConditions() +{ + m_model->setRowCount(int(m_shaderGraph.GetConditionCount())); + + int rowIndex = 0; + for (const auto& conditionEntry : m_shaderGraph.GetConditions()) + { + QStandardItem* label = new QStandardItem(1); + label->setEditable(false); + label->setText(QString::fromStdString(conditionEntry.name)); + + m_model->setItem(rowIndex, 0, label); + + QStandardItem* checkbox = new QStandardItem(1); + checkbox->setCheckable(true); + checkbox->setCheckState((conditionEntry.enabled) ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); + + m_model->setItem(rowIndex, 1, checkbox); + } +} diff --git a/src/ShaderNode/Widgets/ConditionEditor.hpp b/src/ShaderNode/Widgets/ConditionEditor.hpp new file mode 100644 index 000000000..b88b035fe --- /dev/null +++ b/src/ShaderNode/Widgets/ConditionEditor.hpp @@ -0,0 +1,36 @@ +#pragma once + +#ifndef NAZARA_SHADERNODES_CONDITIONEDITOR_HPP +#define NAZARA_SHADERNODES_CONDITIONEDITOR_HPP + +#include +#include +#include + +class QStandardItemModel; +class QVBoxLayout; + +class ConditionEditor : public QWidget +{ + public: + ConditionEditor(ShaderGraph& graph); + ~ConditionEditor() = default; + + private: + void OnAddCondition(); + void OnConditionListUpdate(ShaderGraph* graph); + void OnConditionUpdate(ShaderGraph* graph, std::size_t conditionIndex); + void OnEditCondition(int inputIndex); + void RefreshConditions(); + + NazaraSlot(ShaderGraph, OnStructListUpdate, m_onConditionListUpdateSlot); + NazaraSlot(ShaderGraph, OnStructUpdate, m_onConditionUpdateSlot); + + ShaderGraph& m_shaderGraph; + QStandardItemModel* m_model; + QVBoxLayout* m_layout; +}; + +#include + +#endif diff --git a/src/ShaderNode/Widgets/ConditionEditor.inl b/src/ShaderNode/Widgets/ConditionEditor.inl new file mode 100644 index 000000000..7367d2757 --- /dev/null +++ b/src/ShaderNode/Widgets/ConditionEditor.inl @@ -0,0 +1 @@ +#include diff --git a/src/ShaderNode/Widgets/MainWindow.cpp b/src/ShaderNode/Widgets/MainWindow.cpp index b88bef25f..a9bfcc59f 100644 --- a/src/ShaderNode/Widgets/MainWindow.cpp +++ b/src/ShaderNode/Widgets/MainWindow.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -84,6 +85,15 @@ m_shaderGraph(graph) addDockWidget(Qt::RightDockWidgetArea, structDock); + // Condition editor + ConditionEditor* conditionEditor = new ConditionEditor(m_shaderGraph); + + QDockWidget* conditionDock = new QDockWidget(tr("Conditions")); + conditionDock->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable); + conditionDock->setWidget(conditionEditor); + + addDockWidget(Qt::RightDockWidgetArea, conditionDock); + m_onSelectedNodeUpdate.Connect(m_shaderGraph.OnSelectedNodeUpdate, [&](ShaderGraph*, ShaderNode* node) { if (node) @@ -99,6 +109,21 @@ m_shaderGraph(graph) BuildMenu(); + + m_codeOutput = new QTextEdit; + m_codeOutput->setReadOnly(true); + m_codeOutput->setWindowTitle("GLSL Output"); + + m_onConditionUpdate.Connect(m_shaderGraph.OnConditionUpdate, [&](ShaderGraph*, std::size_t conditionIndex) + { + if (m_codeOutput->isVisible()) + OnGenerateGLSL(); + }); +} + +MainWindow::~MainWindow() +{ + delete m_codeOutput; } void MainWindow::BuildMenu() @@ -109,6 +134,7 @@ void MainWindow::BuildMenu() { 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); } @@ -117,6 +143,7 @@ void MainWindow::BuildMenu() { 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); } @@ -155,16 +182,20 @@ void MainWindow::OnGenerateGLSL() try { Nz::GlslWriter writer; - std::string glsl = writer.Generate(ToShader()); + + Nz::GlslWriter::States states; + for (const auto& condition : m_shaderGraph.GetConditions()) + { + if (condition.enabled) + states.enabledConditions.insert(condition.name); + } + + std::string glsl = writer.Generate(ToShader(), states); std::cout << glsl << std::endl; - QTextEdit* output = new QTextEdit; - output->setReadOnly(true); - output->setText(QString::fromStdString(glsl)); - output->setAttribute(Qt::WA_DeleteOnClose, true); - output->setWindowTitle("GLSL Output"); - output->show(); + m_codeOutput->setText(QString::fromStdString(glsl)); + m_codeOutput->show(); } catch (const std::exception& e) { @@ -238,6 +269,9 @@ Nz::ShaderAst MainWindow::ToShader() Nz::ShaderNodes::StatementPtr shaderAst = m_shaderGraph.ToAst(); Nz::ShaderAst shader(ShaderGraph::ToShaderStageType(m_shaderGraph.GetType())); //< FIXME + for (const auto& condition : m_shaderGraph.GetConditions()) + shader.AddCondition(condition.name); + for (const auto& input : m_shaderGraph.GetInputs()) shader.AddInput(input.name, m_shaderGraph.ToShaderExpressionType(input.type), input.locationIndex); diff --git a/src/ShaderNode/Widgets/MainWindow.hpp b/src/ShaderNode/Widgets/MainWindow.hpp index 76615bb98..10d925190 100644 --- a/src/ShaderNode/Widgets/MainWindow.hpp +++ b/src/ShaderNode/Widgets/MainWindow.hpp @@ -8,6 +8,7 @@ #include class NodeEditor; +class QTextEdit; namespace Nz { @@ -18,7 +19,7 @@ class MainWindow : public QMainWindow { public: MainWindow(ShaderGraph& graph); - ~MainWindow() = default; + ~MainWindow(); private: void BuildMenu(); @@ -29,10 +30,12 @@ class MainWindow : public QMainWindow void OnUpdateInfo(); Nz::ShaderAst ToShader(); + NazaraSlot(ShaderGraph, OnConditionUpdate, m_onConditionUpdate); NazaraSlot(ShaderGraph, OnSelectedNodeUpdate, m_onSelectedNodeUpdate); NodeEditor* m_nodeEditor; ShaderGraph& m_shaderGraph; + QTextEdit* m_codeOutput; }; #include From 386350b96c6f88ad3c8f74e2759f11190fef4268 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 19 Nov 2020 13:57:55 +0100 Subject: [PATCH 019/278] Build: Add support for external includes --- build/scripts/common.lua | 30 +++++++++++++++----------- build/scripts/tools/assimp.lua | 5 ++++- build/scripts/tools/openglrenderer.lua | 5 ++++- build/scripts/tools/shadernodes.lua | 5 ++++- build/scripts/tools/vulkanrenderer.lua | 5 ++++- 5 files changed, 33 insertions(+), 17 deletions(-) diff --git a/build/scripts/common.lua b/build/scripts/common.lua index 2e7e60207..d2e4a207c 100644 --- a/build/scripts/common.lua +++ b/build/scripts/common.lua @@ -104,8 +104,9 @@ function NazaraBuild:Execute() defines(libTable.Defines) flags(libTable.Flags) kind("StaticLib") -- Force them as static libs - includedirs("../thirdparty/include") + sysincludedirs("../thirdparty/include") includedirs(libTable.Includes) + sysincludedirs(libTable.ExtIncludes) links(libTable.Libraries) libdirs("../thirdparty/lib/common") @@ -155,9 +156,9 @@ function NazaraBuild:Execute() includedirs({ "../include", - "../src/", - "../thirdparty/include" + "../src/" }) + sysincludedirs("../thirdparty/include") files(moduleTable.Files) excludes(moduleTable.FilesExcluded) @@ -165,6 +166,7 @@ function NazaraBuild:Execute() defines(moduleTable.Defines) flags(moduleTable.Flags) includedirs(moduleTable.Includes) + sysincludedirs(moduleTable.ExtIncludes) links(moduleTable.Libraries) libdirs({ @@ -236,10 +238,8 @@ function NazaraBuild:Execute() assert(false, "Invalid tool kind") end - includedirs({ - "../include", - "../thirdparty/include" - }) + includedirs("../include") + sysincludedirs("../thirdparty/include") libdirs({ "../thirdparty/lib/common", @@ -252,6 +252,7 @@ function NazaraBuild:Execute() defines(toolTable.Defines) flags(toolTable.Flags) includedirs(toolTable.Includes) + sysincludedirs(toolTable.ExtIncludes) links(toolTable.Libraries) -- Output to lib/conf/arch @@ -308,11 +309,10 @@ function NazaraBuild:Execute() end debugdir(destPath) - includedirs({ - "../include", - "../thirdparty/include", - exampleTable.Includes - }) + includedirs("../include") + includedirs(exampleTable.Includes) + sysincludedirs("../thirdparty/include") + sysincludedirs(exampleTable.ExtIncludes) libdirs({ "../lib", exampleTable.LibDir @@ -784,6 +784,10 @@ function NazaraBuild:Process(infoTable) table.insert(infoTable.Includes, v) end + for k,v in ipairs(libraryTable.ExtIncludes) do + table.insert(infoTable.ExtIncludes, v) + end + -- And libraries for k, v in pairs(libraryTable.Libraries) do table.insert(infoTable.Libraries, v) @@ -1180,7 +1184,7 @@ function NazaraBuild:SetupInfoTable(infoTable) infoTable.LibraryPaths.x86 = {} infoTable.LibraryPaths.x64 = {} - local infos = {"Defines", "DynLib", "Files", "FilesExcluded", "Flags", "Includes", "Libraries"} + local infos = {"Defines", "DynLib", "Files", "FilesExcluded", "Flags", "Includes", "Libraries", "ExtIncludes"} for k,v in ipairs(infos) do infoTable[v] = {} infoTable["Os" .. v] = {} diff --git a/build/scripts/tools/assimp.lua b/build/scripts/tools/assimp.lua index 09374bca1..7410079e5 100644 --- a/build/scripts/tools/assimp.lua +++ b/build/scripts/tools/assimp.lua @@ -4,11 +4,14 @@ TOOL.Directory = "../plugins/Assimp" TOOL.Kind = "Plugin" TOOL.Includes = { - "../thirdparty/include", "../include", "../plugins/Assimp" } +TOOL.ExtIncludes = { + "../thirdparty/include" +} + TOOL.Files = { "../plugins/Assimp/**.hpp", "../plugins/Assimp/**.inl", diff --git a/build/scripts/tools/openglrenderer.lua b/build/scripts/tools/openglrenderer.lua index 48219fe80..1bdeb2ce6 100644 --- a/build/scripts/tools/openglrenderer.lua +++ b/build/scripts/tools/openglrenderer.lua @@ -12,7 +12,10 @@ TOOL.Defines = { TOOL.Includes = { "../include", - "../src/", + "../src/" +} + +TOOL.ExtIncludes = { "../extlibs/include" } diff --git a/build/scripts/tools/shadernodes.lua b/build/scripts/tools/shadernodes.lua index cc0b63cb3..d5a09677f 100644 --- a/build/scripts/tools/shadernodes.lua +++ b/build/scripts/tools/shadernodes.lua @@ -11,10 +11,13 @@ TOOL.Defines = { TOOL.Includes = { "../include", - "../extlibs/include", "../src" } +TOOL.ExtIncludes = { + "../extlibs/include" +} + TOOL.Files = { "../src/ShaderNode/**.hpp", "../src/ShaderNode/**.inl", diff --git a/build/scripts/tools/vulkanrenderer.lua b/build/scripts/tools/vulkanrenderer.lua index 4f4440899..63cdcf1c1 100644 --- a/build/scripts/tools/vulkanrenderer.lua +++ b/build/scripts/tools/vulkanrenderer.lua @@ -13,7 +13,10 @@ TOOL.Defines = { TOOL.Includes = { "../include", - "../src/", + "../src/" +} + +TOOL.ExtIncludes = { "../extlibs/include" } From fd0060a7e1a7eb23361c069e826f00f664e76773 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 19 Nov 2020 14:54:13 +0100 Subject: [PATCH 020/278] Sdk/BoxLayout: Fix widgets not taking up free space --- SDK/src/NDK/Widgets/BoxLayout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SDK/src/NDK/Widgets/BoxLayout.cpp b/SDK/src/NDK/Widgets/BoxLayout.cpp index caf4720a1..bcef8a3c3 100644 --- a/SDK/src/NDK/Widgets/BoxLayout.cpp +++ b/SDK/src/NDK/Widgets/BoxLayout.cpp @@ -81,7 +81,7 @@ namespace Ndk if (maximumSize < std::numeric_limits::infinity()) m_state->solver.addConstraint({ sizeVar <= maximumSize | kiwi::strength::required }); - m_state->solver.addConstraint({ sizeVar == perfectSpacePerWidget | kiwi::strength::medium }); + m_state->solver.addConstraint({ sizeVar >= perfectSpacePerWidget | kiwi::strength::medium }); sizeSum = sizeSum + sizeVar; }); From 420e87eb1acec619aec3f3289bd326100bfe5965 Mon Sep 17 00:00:00 2001 From: Antoine James Tournepiche Date: Sat, 12 Dec 2020 22:06:32 +0100 Subject: [PATCH 021/278] Fix typo in project readme Developer was spelled with 2 p instead of one --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 2eaabc09e..320c7fe7c 100644 --- a/readme.md +++ b/readme.md @@ -5,7 +5,7 @@ Linux | [![Travis CI Build Status](https://travis-ci.org/DigitalPulseSoftware/Na # Nazara Engine -Nazara Engine is a fast, complete, cross-platform, object-oriented API which can help you in your daily developper life. +Nazara Engine is a fast, complete, cross-platform, object-oriented API which can help you in your daily developer life. Its goal is to provide a set of useful classes : Its core provides unicode strings, filesystem access, hashs, threads, ... It also provide a set of libraries, such as audio, network, physics, renderer, 2D and 3D graphics engines, ... From a1c15a8c16ffa0c188b8376d640a66eed8141ac4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 30 Dec 2020 18:14:41 +0100 Subject: [PATCH 022/278] Math: Add SetBit and TestBit --- include/Nazara/Math/Algorithm.hpp | 2 ++ include/Nazara/Math/Algorithm.inl | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/include/Nazara/Math/Algorithm.hpp b/include/Nazara/Math/Algorithm.hpp index 7c22947b9..5109c68d5 100644 --- a/include/Nazara/Math/Algorithm.hpp +++ b/include/Nazara/Math/Algorithm.hpp @@ -61,7 +61,9 @@ namespace Nz template constexpr bool NumberEquals(T a, T b, T maxDifference); inline std::string NumberToString(long long number, UInt8 radix = 10); template constexpr T RadianToDegree(T radians); + template T SetBit(T number, T bit); inline long long StringToNumber(const std::string_view& str, UInt8 radix = 10, bool* ok = nullptr); + template bool TestBit(T number, T bit); template constexpr T ToDegrees(T angle); template constexpr T ToRadians(T angle); } diff --git a/include/Nazara/Math/Algorithm.inl b/include/Nazara/Math/Algorithm.inl index d480f60f8..f5ef47381 100644 --- a/include/Nazara/Math/Algorithm.inl +++ b/include/Nazara/Math/Algorithm.inl @@ -624,6 +624,13 @@ namespace Nz return radians * T(180.0/M_PI); } + template + T SetBit(T number, T bit) + { + NazaraAssert(bit < sizeof(number)* CHAR_BIT, "bit index out of range"); + return number |= (T(1) << bit); + } + /*! * \ingroup math * \brief Converts the string to number @@ -689,6 +696,13 @@ namespace Nz return (negative) ? -static_cast(total) : total; } + template + bool TestBit(T number, T bit) + { + NazaraAssert(bit < sizeof(number) * CHAR_BIT, "bit index out of range"); + return number & (T(1) << bit); + } + /*! * \ingroup math * \brief Gets the degree from unit and convert it according to NAZARA_MATH_ANGLE_RADIAN From ed72d668d96970f89f903478b2d9f7998673c887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 30 Dec 2020 20:05:16 +0100 Subject: [PATCH 023/278] Shader: Add Discard node --- include/Nazara/Shader/GlslWriter.hpp | 1 + include/Nazara/Shader/ShaderAstCloner.hpp | 1 + .../Shader/ShaderAstRecursiveVisitor.hpp | 1 + include/Nazara/Shader/ShaderAstSerializer.hpp | 1 + include/Nazara/Shader/ShaderAstVisitor.hpp | 1 + .../Nazara/Shader/ShaderAstVisitorExcept.hpp | 1 + include/Nazara/Shader/ShaderBuilder.hpp | 1 + include/Nazara/Shader/ShaderEnums.hpp | 1 + include/Nazara/Shader/ShaderNodes.hpp | 9 +++ include/Nazara/Shader/ShaderNodes.inl | 11 ++++ include/Nazara/Shader/SpirvAstVisitor.hpp | 1 + src/Nazara/Shader/GlslWriter.cpp | 5 ++ src/Nazara/Shader/ShaderAstCloner.cpp | 5 ++ .../Shader/ShaderAstRecursiveVisitor.cpp | 5 ++ src/Nazara/Shader/ShaderAstSerializer.cpp | 11 ++++ src/Nazara/Shader/ShaderAstVisitorExcept.cpp | 5 ++ src/Nazara/Shader/ShaderNodes.cpp | 6 ++ src/Nazara/Shader/SpirvAstVisitor.cpp | 5 ++ src/ShaderNode/DataModels/Discard.cpp | 56 +++++++++++++++++++ src/ShaderNode/DataModels/Discard.hpp | 32 +++++++++++ src/ShaderNode/DataModels/Discard.inl | 1 + src/ShaderNode/ShaderGraph.cpp | 2 + 22 files changed, 162 insertions(+) create mode 100644 src/ShaderNode/DataModels/Discard.cpp create mode 100644 src/ShaderNode/DataModels/Discard.hpp create mode 100644 src/ShaderNode/DataModels/Discard.inl diff --git a/include/Nazara/Shader/GlslWriter.hpp b/include/Nazara/Shader/GlslWriter.hpp index e7b92505c..d7fb7000a 100644 --- a/include/Nazara/Shader/GlslWriter.hpp +++ b/include/Nazara/Shader/GlslWriter.hpp @@ -73,6 +73,7 @@ namespace Nz void Visit(ShaderNodes::ConditionalStatement& node) override; void Visit(ShaderNodes::Constant& node) override; void Visit(ShaderNodes::DeclareVariable& node) override; + void Visit(ShaderNodes::Discard& node) override; void Visit(ShaderNodes::ExpressionStatement& node) override; void Visit(ShaderNodes::Identifier& node) override; void Visit(ShaderNodes::InputVariable& var) override; diff --git a/include/Nazara/Shader/ShaderAstCloner.hpp b/include/Nazara/Shader/ShaderAstCloner.hpp index afa7cb5b2..1f5259b51 100644 --- a/include/Nazara/Shader/ShaderAstCloner.hpp +++ b/include/Nazara/Shader/ShaderAstCloner.hpp @@ -42,6 +42,7 @@ namespace Nz void Visit(ShaderNodes::ConditionalStatement& node) override; void Visit(ShaderNodes::Constant& node) override; void Visit(ShaderNodes::DeclareVariable& node) override; + void Visit(ShaderNodes::Discard& node) override; void Visit(ShaderNodes::ExpressionStatement& node) override; void Visit(ShaderNodes::Identifier& node) override; void Visit(ShaderNodes::IntrinsicCall& node) override; diff --git a/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp b/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp index 5dd1bc5fe..9e780e340 100644 --- a/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp +++ b/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp @@ -30,6 +30,7 @@ namespace Nz void Visit(ShaderNodes::ConditionalStatement& node) override; void Visit(ShaderNodes::Constant& node) override; void Visit(ShaderNodes::DeclareVariable& node) override; + void Visit(ShaderNodes::Discard& node) override; void Visit(ShaderNodes::ExpressionStatement& node) override; void Visit(ShaderNodes::Identifier& node) override; void Visit(ShaderNodes::IntrinsicCall& node) override; diff --git a/include/Nazara/Shader/ShaderAstSerializer.hpp b/include/Nazara/Shader/ShaderAstSerializer.hpp index e2db77fdf..5155a702e 100644 --- a/include/Nazara/Shader/ShaderAstSerializer.hpp +++ b/include/Nazara/Shader/ShaderAstSerializer.hpp @@ -35,6 +35,7 @@ namespace Nz void Serialize(ShaderNodes::ConditionalStatement& node); void Serialize(ShaderNodes::Constant& node); void Serialize(ShaderNodes::DeclareVariable& node); + void Serialize(ShaderNodes::Discard& node); void Serialize(ShaderNodes::ExpressionStatement& node); void Serialize(ShaderNodes::Identifier& node); void Serialize(ShaderNodes::IntrinsicCall& node); diff --git a/include/Nazara/Shader/ShaderAstVisitor.hpp b/include/Nazara/Shader/ShaderAstVisitor.hpp index 9ac8d764c..f3b0c5bdc 100644 --- a/include/Nazara/Shader/ShaderAstVisitor.hpp +++ b/include/Nazara/Shader/ShaderAstVisitor.hpp @@ -31,6 +31,7 @@ namespace Nz virtual void Visit(ShaderNodes::ConditionalStatement& node) = 0; virtual void Visit(ShaderNodes::Constant& node) = 0; virtual void Visit(ShaderNodes::DeclareVariable& node) = 0; + virtual void Visit(ShaderNodes::Discard& node) = 0; virtual void Visit(ShaderNodes::ExpressionStatement& node) = 0; virtual void Visit(ShaderNodes::Identifier& node) = 0; virtual void Visit(ShaderNodes::IntrinsicCall& node) = 0; diff --git a/include/Nazara/Shader/ShaderAstVisitorExcept.hpp b/include/Nazara/Shader/ShaderAstVisitorExcept.hpp index 0c58c5472..3878d522d 100644 --- a/include/Nazara/Shader/ShaderAstVisitorExcept.hpp +++ b/include/Nazara/Shader/ShaderAstVisitorExcept.hpp @@ -26,6 +26,7 @@ namespace Nz void Visit(ShaderNodes::ConditionalStatement& node) override; void Visit(ShaderNodes::Constant& node) override; void Visit(ShaderNodes::DeclareVariable& node) override; + void Visit(ShaderNodes::Discard& node) override; void Visit(ShaderNodes::ExpressionStatement& node) override; void Visit(ShaderNodes::Identifier& node) override; void Visit(ShaderNodes::IntrinsicCall& node) override; diff --git a/include/Nazara/Shader/ShaderBuilder.hpp b/include/Nazara/Shader/ShaderBuilder.hpp index 0965c7f0c..d7c982eee 100644 --- a/include/Nazara/Shader/ShaderBuilder.hpp +++ b/include/Nazara/Shader/ShaderBuilder.hpp @@ -54,6 +54,7 @@ namespace Nz::ShaderBuilder constexpr GenBuilder ConditionalStatement; constexpr GenBuilder Constant; constexpr GenBuilder DeclareVariable; + constexpr GenBuilder Discard; constexpr BinOpBuilder Divide; constexpr BinOpBuilder Equal; constexpr GenBuilder ExprStatement; diff --git a/include/Nazara/Shader/ShaderEnums.hpp b/include/Nazara/Shader/ShaderEnums.hpp index 57f76d0f5..596292d9d 100644 --- a/include/Nazara/Shader/ShaderEnums.hpp +++ b/include/Nazara/Shader/ShaderEnums.hpp @@ -81,6 +81,7 @@ namespace Nz::ShaderNodes ConditionalExpression, ConditionalStatement, DeclareVariable, + Discard, ExpressionStatement, Identifier, IntrinsicCall, diff --git a/include/Nazara/Shader/ShaderNodes.hpp b/include/Nazara/Shader/ShaderNodes.hpp index 8639dbc99..e519a0b08 100644 --- a/include/Nazara/Shader/ShaderNodes.hpp +++ b/include/Nazara/Shader/ShaderNodes.hpp @@ -123,6 +123,15 @@ namespace Nz static inline std::shared_ptr Build(VariablePtr variable, ExpressionPtr expression = nullptr); }; + struct NAZARA_SHADER_API Discard : public Statement + { + inline Discard(); + + void Visit(ShaderAstVisitor& visitor) override; + + static inline std::shared_ptr Build(); + }; + struct NAZARA_SHADER_API Identifier : public Expression { inline Identifier(); diff --git a/include/Nazara/Shader/ShaderNodes.inl b/include/Nazara/Shader/ShaderNodes.inl index b61841430..fe0872a9d 100644 --- a/include/Nazara/Shader/ShaderNodes.inl +++ b/include/Nazara/Shader/ShaderNodes.inl @@ -148,6 +148,17 @@ namespace Nz::ShaderNodes } + inline Discard::Discard() : + Statement(NodeType::DeclareVariable) + { + } + + inline std::shared_ptr Discard::Build() + { + return std::make_shared(); + } + + inline Identifier::Identifier() : Expression(NodeType::Identifier) { diff --git a/include/Nazara/Shader/SpirvAstVisitor.hpp b/include/Nazara/Shader/SpirvAstVisitor.hpp index d7196950f..91ad031ad 100644 --- a/include/Nazara/Shader/SpirvAstVisitor.hpp +++ b/include/Nazara/Shader/SpirvAstVisitor.hpp @@ -36,6 +36,7 @@ namespace Nz void Visit(ShaderNodes::ConditionalStatement& node) override; void Visit(ShaderNodes::Constant& node) override; void Visit(ShaderNodes::DeclareVariable& node) override; + void Visit(ShaderNodes::Discard& node) override; void Visit(ShaderNodes::ExpressionStatement& node) override; void Visit(ShaderNodes::Identifier& node) override; void Visit(ShaderNodes::IntrinsicCall& node) override; diff --git a/src/Nazara/Shader/GlslWriter.cpp b/src/Nazara/Shader/GlslWriter.cpp index 248c92bb7..649f25072 100644 --- a/src/Nazara/Shader/GlslWriter.cpp +++ b/src/Nazara/Shader/GlslWriter.cpp @@ -519,6 +519,11 @@ namespace Nz AppendLine(";"); } + void GlslWriter::Visit(ShaderNodes::Discard& /*node*/) + { + Append("discard;"); + } + void GlslWriter::Visit(ShaderNodes::ExpressionStatement& node) { Visit(node.expression); diff --git a/src/Nazara/Shader/ShaderAstCloner.cpp b/src/Nazara/Shader/ShaderAstCloner.cpp index cef0ac694..8a07cf1a7 100644 --- a/src/Nazara/Shader/ShaderAstCloner.cpp +++ b/src/Nazara/Shader/ShaderAstCloner.cpp @@ -111,6 +111,11 @@ namespace Nz PushStatement(ShaderNodes::DeclareVariable::Build(CloneVariable(node.variable), CloneExpression(node.expression))); } + void ShaderAstCloner::Visit(ShaderNodes::Discard& /*node*/) + { + PushStatement(ShaderNodes::Discard::Build()); + } + void ShaderAstCloner::Visit(ShaderNodes::ExpressionStatement& node) { PushStatement(ShaderNodes::ExpressionStatement::Build(CloneExpression(node.expression))); diff --git a/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp b/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp index b68d5361a..bca595384 100644 --- a/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp +++ b/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp @@ -69,6 +69,11 @@ namespace Nz Visit(node.expression); } + void ShaderAstRecursiveVisitor::Visit(ShaderNodes::Discard& /*node*/) + { + /* Nothing to do */ + } + void ShaderAstRecursiveVisitor::Visit(ShaderNodes::ExpressionStatement& node) { Visit(node.expression); diff --git a/src/Nazara/Shader/ShaderAstSerializer.cpp b/src/Nazara/Shader/ShaderAstSerializer.cpp index 5184d980d..a5e870713 100644 --- a/src/Nazara/Shader/ShaderAstSerializer.cpp +++ b/src/Nazara/Shader/ShaderAstSerializer.cpp @@ -67,6 +67,11 @@ namespace Nz Serialize(node); } + void Visit(ShaderNodes::Discard& node) override + { + Serialize(node); + } + void Visit(ShaderNodes::ExpressionStatement& node) override { Serialize(node); @@ -242,6 +247,11 @@ namespace Nz Node(node.expression); } + void ShaderAstSerializerBase::Serialize(ShaderNodes::Discard& /*node*/) + { + /* Nothing to do */ + } + void ShaderAstSerializerBase::Serialize(ShaderNodes::ExpressionStatement& node) { Node(node.expression); @@ -665,6 +675,7 @@ namespace Nz HandleType(ConditionalExpression); HandleType(ConditionalStatement); HandleType(DeclareVariable); + HandleType(Discard); HandleType(ExpressionStatement); HandleType(Identifier); HandleType(IntrinsicCall); diff --git a/src/Nazara/Shader/ShaderAstVisitorExcept.cpp b/src/Nazara/Shader/ShaderAstVisitorExcept.cpp index 85ae826d1..17671a42c 100644 --- a/src/Nazara/Shader/ShaderAstVisitorExcept.cpp +++ b/src/Nazara/Shader/ShaderAstVisitorExcept.cpp @@ -53,6 +53,11 @@ namespace Nz throw std::runtime_error("unhandled DeclareVariable node"); } + void ShaderAstVisitorExcept::Visit(ShaderNodes::Discard& /*node*/) + { + throw std::runtime_error("unhandled Discard node"); + } + void ShaderAstVisitorExcept::Visit(ShaderNodes::ExpressionStatement& /*node*/) { throw std::runtime_error("unhandled ExpressionStatement node"); diff --git a/src/Nazara/Shader/ShaderNodes.cpp b/src/Nazara/Shader/ShaderNodes.cpp index 6530c1713..c6aa7874a 100644 --- a/src/Nazara/Shader/ShaderNodes.cpp +++ b/src/Nazara/Shader/ShaderNodes.cpp @@ -42,6 +42,12 @@ namespace Nz::ShaderNodes } + void Discard::Visit(ShaderAstVisitor& visitor) + { + visitor.Visit(*this); + } + + ExpressionCategory Identifier::GetExpressionCategory() const { return ExpressionCategory::LValue; diff --git a/src/Nazara/Shader/SpirvAstVisitor.cpp b/src/Nazara/Shader/SpirvAstVisitor.cpp index 2cb244496..871f41b41 100644 --- a/src/Nazara/Shader/SpirvAstVisitor.cpp +++ b/src/Nazara/Shader/SpirvAstVisitor.cpp @@ -346,6 +346,11 @@ namespace Nz } } + void SpirvAstVisitor::Visit(ShaderNodes::Discard& /*node*/) + { + m_writer.GetInstructions().Append(SpirvOp::OpKill); + } + void SpirvAstVisitor::Visit(ShaderNodes::ExpressionStatement& node) { Visit(node.expression); diff --git a/src/ShaderNode/DataModels/Discard.cpp b/src/ShaderNode/DataModels/Discard.cpp new file mode 100644 index 000000000..968e8d53c --- /dev/null +++ b/src/ShaderNode/DataModels/Discard.cpp @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +Discard::Discard(ShaderGraph& graph) : +ShaderNode(graph) +{ + DisablePreview(); + DisableCustomVariableName(); +} + +Nz::ShaderNodes::NodePtr Discard::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +{ + using namespace Nz::ShaderBuilder; + + assert(count == 1); + assert(outputIndex == 0); + + return Branch(Equal(expressions[0], Constant(true)), Nz::ShaderBuilder::Discard(), nullptr); +} + +int Discard::GetOutputOrder() const +{ + return std::numeric_limits::lowest(); +} + +QtNodes::NodeDataType Discard::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const +{ + assert(portType == QtNodes::PortType::In); + assert(portIndex == 0); + + return BoolData::Type(); +} + +unsigned int Discard::nPorts(QtNodes::PortType portType) const +{ + switch (portType) + { + case QtNodes::PortType::In: return 1; + case QtNodes::PortType::Out: return 0; + } + + return 0; +} + +std::shared_ptr Discard::outData(QtNodes::PortIndex port) +{ + return {}; +} diff --git a/src/ShaderNode/DataModels/Discard.hpp b/src/ShaderNode/DataModels/Discard.hpp new file mode 100644 index 000000000..55f6be153 --- /dev/null +++ b/src/ShaderNode/DataModels/Discard.hpp @@ -0,0 +1,32 @@ +#pragma once + +#ifndef NAZARA_SHADERNODES_DISCARD_HPP +#define NAZARA_SHADERNODES_DISCARD_HPP + +#include +#include +#include + +class QFormLayout; + +class Discard : public ShaderNode +{ + public: + Discard(ShaderGraph& graph); + + Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + int GetOutputOrder() const; + + QString caption() const override { return "Discard"; } + QString name() const override { return "Discard"; } + + QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; + + unsigned int nPorts(QtNodes::PortType portType) const override; + + std::shared_ptr outData(QtNodes::PortIndex port) override; +}; + +#include + +#endif diff --git a/src/ShaderNode/DataModels/Discard.inl b/src/ShaderNode/DataModels/Discard.inl new file mode 100644 index 000000000..61b5ba0de --- /dev/null +++ b/src/ShaderNode/DataModels/Discard.inl @@ -0,0 +1 @@ +#include diff --git a/src/ShaderNode/ShaderGraph.cpp b/src/ShaderNode/ShaderGraph.cpp index 9a93dcf8f..c0c575493 100644 --- a/src/ShaderNode/ShaderGraph.cpp +++ b/src/ShaderNode/ShaderGraph.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -742,6 +743,7 @@ std::shared_ptr ShaderGraph::BuildRegistry() RegisterShaderNode(*this, registry, "Casts"); RegisterShaderNode(*this, registry, "Casts"); RegisterShaderNode(*this, registry, "Shader"); + RegisterShaderNode(*this, registry, "Outputs"); RegisterShaderNode(*this, registry, "Constants"); RegisterShaderNode(*this, registry, "Inputs"); RegisterShaderNode(*this, registry, "Outputs"); From f32793273800c2f143a809c7d8f73d205f388a70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sat, 2 Jan 2021 21:15:59 +0100 Subject: [PATCH 024/278] Commit current work Reworked conditions, added uber-shaders, comparison nodes, fixed Discard --- build/scripts/modules/graphics.lua | 1 + examples/GraphicsTest/main.cpp | 75 ++- include/Nazara/Graphics/BasicMaterial.hpp | 30 +- include/Nazara/Graphics/BasicMaterial.inl | 59 ++- include/Nazara/Graphics/Material.hpp | 10 +- include/Nazara/Graphics/Material.inl | 47 +- include/Nazara/Graphics/MaterialPipeline.hpp | 10 +- include/Nazara/Graphics/MaterialPipeline.inl | 10 +- include/Nazara/Graphics/MaterialSettings.hpp | 38 +- include/Nazara/Graphics/MaterialSettings.inl | 76 +-- include/Nazara/Graphics/UberShader.hpp | 39 ++ include/Nazara/Graphics/UberShader.inl | 12 + .../Nazara/OpenGLRenderer/OpenGLDevice.hpp | 1 + .../OpenGLRenderPipelineLayout.hpp | 6 +- .../OpenGLRenderer/OpenGLShaderStage.hpp | 7 + .../OpenGLRenderer/Wrapper/WGL/WGLContext.inl | 3 +- include/Nazara/Renderer/RenderDevice.hpp | 3 + include/Nazara/Shader/ShaderAst.hpp | 4 + include/Nazara/Shader/ShaderAst.inl | 11 + include/Nazara/Shader/ShaderAstSerializer.hpp | 1 + include/Nazara/Shader/ShaderAstSerializer.inl | 6 + include/Nazara/Shader/ShaderBuilder.hpp | 7 +- include/Nazara/Shader/ShaderEnums.hpp | 13 +- include/Nazara/Shader/ShaderNodes.inl | 2 +- include/Nazara/Shader/ShaderWriter.hpp | 2 +- include/Nazara/Shader/SpirvWriter.inl | 6 +- .../Nazara/VulkanRenderer/VulkanDevice.hpp | 1 + .../VulkanRenderer/VulkanShaderStage.hpp | 2 + .../basicmaterial.frag.shaderflow | 459 +++++++++++++++--- src/Nazara/Core/Error.cpp | 5 +- src/Nazara/Graphics/BasicMaterial.cpp | 108 +++-- src/Nazara/Graphics/Material.cpp | 6 +- src/Nazara/Graphics/MaterialPipeline.cpp | 7 +- src/Nazara/Graphics/PhongLightingMaterial.cpp | 54 +-- .../Shaders/basicmaterial.frag.shader | Bin 1126 -> 1745 bytes .../Shaders/basicmaterial.frag.shader.h | 2 +- .../Shaders/basicmaterial.vert.shader | Bin 1046 -> 1050 bytes .../Shaders/basicmaterial.vert.shader.h | 2 +- src/Nazara/Graphics/UberShader.cpp | 54 +++ .../OpenGLRenderer/OpenGLCommandBuffer.cpp | 1 + src/Nazara/OpenGLRenderer/OpenGLDevice.cpp | 5 + .../OpenGLRenderer/OpenGLShaderBinding.cpp | 6 + .../OpenGLRenderer/OpenGLShaderStage.cpp | 65 ++- .../OpenGLRenderer/Wrapper/WGL/WGLContext.cpp | 18 +- src/Nazara/Physics2D/Arbiter2D.cpp | 2 +- src/Nazara/Shader/GlslWriter.cpp | 51 +- src/Nazara/Shader/ShaderAstSerializer.cpp | 3 + src/Nazara/Shader/ShaderAstValidator.cpp | 33 +- src/Nazara/Shader/ShaderNodes.cpp | 7 +- src/Nazara/Shader/SpirvAstVisitor.cpp | 162 ++++++- src/Nazara/Shader/SpirvWriter.cpp | 16 +- src/Nazara/VulkanRenderer/VulkanDevice.cpp | 9 + .../VulkanRenderer/VulkanShaderStage.cpp | 36 +- .../VulkanRenderer/Wrapper/Instance.cpp | 6 +- src/ShaderNode/DataModels/BinOp.hpp | 163 +++++++ src/ShaderNode/DataModels/BinOp.inl | 240 +++++++++ src/ShaderNode/DataModels/BoolValue.cpp | 126 +++++ src/ShaderNode/DataModels/BoolValue.hpp | 47 ++ src/ShaderNode/DataModels/BoolValue.inl | 1 + src/ShaderNode/DataModels/BufferField.cpp | 3 +- src/ShaderNode/DataModels/BufferField.hpp | 3 +- src/ShaderNode/DataModels/Cast.hpp | 3 +- src/ShaderNode/DataModels/Cast.inl | 75 +-- src/ShaderNode/DataModels/CompOp.hpp | 220 +++++++++ src/ShaderNode/DataModels/CompOp.inl | 293 +++++++++++ .../DataModels/ConditionalExpression.cpp | 59 ++- .../DataModels/ConditionalExpression.hpp | 3 +- src/ShaderNode/DataModels/FloatValue.cpp | 23 +- src/ShaderNode/DataModels/FloatValue.hpp | 8 +- src/ShaderNode/DataModels/InputValue.cpp | 32 +- src/ShaderNode/DataModels/InputValue.hpp | 5 +- src/ShaderNode/DataModels/Mat4BinOp.hpp | 4 +- src/ShaderNode/DataModels/Mat4BinOp.inl | 48 +- src/ShaderNode/DataModels/Mat4VecMul.cpp | 4 +- src/ShaderNode/DataModels/Mat4VecMul.hpp | 2 +- src/ShaderNode/DataModels/OutputValue.cpp | 40 +- src/ShaderNode/DataModels/OutputValue.hpp | 5 +- .../DataModels/PositionOutputValue.cpp | 3 +- .../DataModels/PositionOutputValue.hpp | 2 +- src/ShaderNode/DataModels/SampleTexture.cpp | 3 +- src/ShaderNode/DataModels/SampleTexture.hpp | 2 +- src/ShaderNode/DataModels/ShaderNode.cpp | 5 + src/ShaderNode/DataModels/ShaderNode.hpp | 3 +- src/ShaderNode/DataModels/TextureValue.cpp | 29 +- src/ShaderNode/DataModels/TextureValue.hpp | 5 +- src/ShaderNode/DataModels/VecBinOp.cpp | 75 --- src/ShaderNode/DataModels/VecBinOp.hpp | 86 ---- src/ShaderNode/DataModels/VecBinOp.inl | 131 ----- src/ShaderNode/DataModels/VecComposition.hpp | 49 ++ src/ShaderNode/DataModels/VecComposition.inl | 192 ++++++++ .../DataModels/VecDecomposition.cpp | 176 +++++++ .../DataModels/VecDecomposition.hpp | 48 ++ .../{Cast.cpp => VecDecomposition.inl} | 0 src/ShaderNode/DataModels/VecDot.cpp | 4 +- src/ShaderNode/DataModels/VecDot.hpp | 2 +- src/ShaderNode/DataModels/VecFloatMul.cpp | 4 +- src/ShaderNode/DataModels/VecFloatMul.hpp | 2 +- src/ShaderNode/DataModels/VecValue.cpp | 1 - src/ShaderNode/DataModels/VecValue.hpp | 8 +- src/ShaderNode/DataModels/VecValue.inl | 30 +- src/ShaderNode/ShaderGraph.cpp | 162 +++++-- src/ShaderNode/Widgets/ConditionEditor.cpp | 4 +- src/ShaderNode/Widgets/MainWindow.cpp | 6 +- 103 files changed, 3248 insertions(+), 790 deletions(-) create mode 100644 include/Nazara/Graphics/UberShader.hpp create mode 100644 include/Nazara/Graphics/UberShader.inl create mode 100644 src/Nazara/Graphics/UberShader.cpp create mode 100644 src/ShaderNode/DataModels/BinOp.hpp create mode 100644 src/ShaderNode/DataModels/BinOp.inl create mode 100644 src/ShaderNode/DataModels/BoolValue.cpp create mode 100644 src/ShaderNode/DataModels/BoolValue.hpp create mode 100644 src/ShaderNode/DataModels/BoolValue.inl create mode 100644 src/ShaderNode/DataModels/CompOp.hpp create mode 100644 src/ShaderNode/DataModels/CompOp.inl delete mode 100644 src/ShaderNode/DataModels/VecBinOp.cpp delete mode 100644 src/ShaderNode/DataModels/VecBinOp.hpp delete mode 100644 src/ShaderNode/DataModels/VecBinOp.inl create mode 100644 src/ShaderNode/DataModels/VecComposition.hpp create mode 100644 src/ShaderNode/DataModels/VecComposition.inl create mode 100644 src/ShaderNode/DataModels/VecDecomposition.cpp create mode 100644 src/ShaderNode/DataModels/VecDecomposition.hpp rename src/ShaderNode/DataModels/{Cast.cpp => VecDecomposition.inl} (100%) delete mode 100644 src/ShaderNode/DataModels/VecValue.cpp diff --git a/build/scripts/modules/graphics.lua b/build/scripts/modules/graphics.lua index 71b2738ce..92a087236 100644 --- a/build/scripts/modules/graphics.lua +++ b/build/scripts/modules/graphics.lua @@ -5,5 +5,6 @@ MODULE.ClientOnly = true MODULE.Libraries = { "NazaraCore", "NazaraRenderer", + "NazaraShader", "NazaraUtility" } diff --git a/examples/GraphicsTest/main.cpp b/examples/GraphicsTest/main.cpp index 946d6bc28..5e09b0b9f 100644 --- a/examples/GraphicsTest/main.cpp +++ b/examples/GraphicsTest/main.cpp @@ -35,20 +35,6 @@ int main() std::shared_ptr device = window.GetRenderDevice(); - /*auto fragmentShader = device->InstantiateShaderStage(Nz::ShaderStageType::Fragment, Nz::ShaderLanguage::NazaraBinary, "frag.shader"); - if (!fragmentShader) - { - std::cout << "Failed to instantiate fragment shader" << std::endl; - return __LINE__; - } - - auto vertexShader = device->InstantiateShaderStage(Nz::ShaderStageType::Vertex, Nz::ShaderLanguage::NazaraBinary, "vert.shader"); - if (!vertexShader) - { - std::cout << "Failed to instantiate fragment shader" << std::endl; - return __LINE__; - }*/ - Nz::MeshRef drfreak = Nz::Mesh::LoadFromFile("resources/Spaceship/spaceship.obj", meshParams); if (!drfreak) { @@ -89,20 +75,49 @@ int main() return __LINE__; } + // Texture (alpha-map) + Nz::ImageRef alphaImage = Nz::Image::LoadFromFile("alphatest.png"); + if (!alphaImage || !alphaImage->Convert(Nz::PixelFormat_RGBA8)) + { + NazaraError("Failed to load image"); + return __LINE__; + } + + Nz::TextureInfo alphaTexParams; + alphaTexParams.pixelFormat = alphaImage->GetFormat(); + alphaTexParams.type = alphaImage->GetType(); + alphaTexParams.width = alphaImage->GetWidth(); + alphaTexParams.height = alphaImage->GetHeight(); + alphaTexParams.depth = alphaImage->GetDepth(); + + std::shared_ptr alphaTexture = device->InstantiateTexture(alphaTexParams); + if (!alphaTexture->Update(alphaImage->GetConstPixels())) + { + NazaraError("Failed to update texture"); + return __LINE__; + } + + + std::shared_ptr textureSampler = device->InstantiateTextureSampler({}); Nz::Material material(Nz::BasicMaterial::GetSettings()); - //material.SetShader(Nz::ShaderStageType::Fragment, fragmentShader); - //material.SetShader(Nz::ShaderStageType::Vertex, vertexShader); material.EnableDepthBuffer(true); - material.SetTexture(0, texture); - material.SetTextureSampler(0, textureSampler); + + Nz::BasicMaterial basicMat(material); + basicMat.EnableAlphaTest(true); + basicMat.SetAlphaMap(alphaTexture); + basicMat.SetAlphaSampler(textureSampler); + basicMat.SetDiffuseMap(alphaTexture); + basicMat.SetDiffuseSampler(textureSampler); Nz::PredefinedInstanceData instanceUboOffsets = Nz::PredefinedInstanceData::GetOffsets(); Nz::PredefinedViewerData viewerUboOffsets = Nz::PredefinedViewerData::GetOffsets(); + const Nz::BasicMaterial::UniformOffsets& materialSettingOffsets = Nz::BasicMaterial::GetOffsets(); std::vector instanceDataBuffer(instanceUboOffsets.totalSize); std::vector viewerDataBuffer(viewerUboOffsets.totalSize); + std::vector materialSettings(materialSettingOffsets.totalSize); Nz::Vector2ui windowSize = window.GetSize(); @@ -110,6 +125,9 @@ int main() Nz::AccessByOffset(viewerDataBuffer.data(), viewerUboOffsets.viewMatrixOffset) = Nz::Matrix4f::Translate(Nz::Vector3f::Backward() * 1); Nz::AccessByOffset(viewerDataBuffer.data(), viewerUboOffsets.projMatrixOffset) = Nz::Matrix4f::Perspective(70.f, float(windowSize.x) / windowSize.y, 0.1f, 1000.f); + Nz::AccessByOffset(materialSettings.data(), materialSettingOffsets.alphaThreshold) = 0.5f; + Nz::AccessByOffset(materialSettings.data(), materialSettingOffsets.diffuseColor) = Nz::Vector4f(1.f, 1.f, 1.f, 1.f); + std::shared_ptr renderPipelineLayout = material.GetSettings()->GetRenderPipelineLayout(); std::shared_ptr instanceDataUbo = device->InstantiateBuffer(Nz::BufferType_Uniform); @@ -128,6 +146,15 @@ int main() return __LINE__; } + std::shared_ptr matSettingUBO = device->InstantiateBuffer(Nz::BufferType_Uniform); + if (!matSettingUBO->Initialize(materialSettings.size(), Nz::BufferUsage_DeviceLocal | Nz::BufferUsage_Dynamic)) + { + NazaraError("Failed to create mat setting UBO"); + return __LINE__; + } + + matSettingUBO->Fill(materialSettings.data(), 0, materialSettings.size()); + Nz::ShaderBindingPtr shaderBinding = renderPipelineLayout->AllocateShaderBinding(); shaderBinding->Update({ { @@ -142,6 +169,18 @@ int main() instanceDataUbo.get(), 0, instanceDataBuffer.size() } }, + { + 3, + Nz::ShaderBinding::UniformBufferBinding { + matSettingUBO.get(), 0, materialSettings.size() + } + }, + { + 0, + Nz::ShaderBinding::TextureBinding { + alphaTexture.get(), textureSampler.get() + } + }, { 1, Nz::ShaderBinding::TextureBinding { diff --git a/include/Nazara/Graphics/BasicMaterial.hpp b/include/Nazara/Graphics/BasicMaterial.hpp index ef7488a5e..ff4815732 100644 --- a/include/Nazara/Graphics/BasicMaterial.hpp +++ b/include/Nazara/Graphics/BasicMaterial.hpp @@ -17,30 +17,48 @@ namespace Nz friend class MaterialPipeline; public: + struct UniformOffsets; + BasicMaterial(Material& material); + inline void EnableAlphaTest(bool alphaTest); + inline const std::shared_ptr& GetAlphaMap() const; - float GetAlphaThreshold() const; + inline const std::shared_ptr& GetAlphaSampler() const; + float GetAlphaTestThreshold() const; Color GetDiffuseColor() const; inline const std::shared_ptr& GetDiffuseMap() const; + inline const std::shared_ptr& GetDiffuseSampler() const; inline bool HasAlphaMap() const; - inline bool HasAlphaThreshold() const; + inline bool HasAlphaTest() const; + inline bool HasAlphaTestThreshold() const; inline bool HasDiffuseColor() const; inline bool HasDiffuseMap() const; inline void SetAlphaMap(std::shared_ptr alphaMap); - void SetAlphaThreshold(float alphaThreshold); + inline void SetAlphaSampler(std::shared_ptr alphaSampler); + void SetAlphaTestThreshold(float alphaThreshold); void SetDiffuseColor(const Color& diffuse); inline void SetDiffuseMap(std::shared_ptr diffuseMap); + inline void SetDiffuseSampler(std::shared_ptr diffuseSampler); - static const std::shared_ptr& GetSettings(); + static inline const UniformOffsets& GetOffsets(); + static inline const std::shared_ptr& GetSettings(); - private: struct UniformOffsets { std::size_t alphaThreshold; std::size_t diffuseColor; + std::size_t totalSize; + }; + + private: + struct ConditionIndexes + { + std::size_t alphaTest; + std::size_t hasAlphaMap; + std::size_t hasDiffuseMap; }; struct TextureIndexes @@ -54,11 +72,13 @@ namespace Nz Material& m_material; std::size_t m_uniformBlockIndex; + ConditionIndexes m_conditionIndexes; TextureIndexes m_textureIndexes; UniformOffsets m_uniformOffsets; static std::shared_ptr s_materialSettings; static std::size_t s_uniformBlockIndex; + static ConditionIndexes s_conditionIndexes; static TextureIndexes s_textureIndexes; static UniformOffsets s_uniformOffsets; }; diff --git a/include/Nazara/Graphics/BasicMaterial.inl b/include/Nazara/Graphics/BasicMaterial.inl index 7a13539c8..875dc4b8e 100644 --- a/include/Nazara/Graphics/BasicMaterial.inl +++ b/include/Nazara/Graphics/BasicMaterial.inl @@ -9,24 +9,47 @@ namespace Nz { + inline void BasicMaterial::EnableAlphaTest(bool alphaTest) + { + NazaraAssert(HasAlphaTest(), "Material has no alpha test condition"); + m_material.EnableCondition(m_conditionIndexes.alphaTest, alphaTest); + } + inline const std::shared_ptr& BasicMaterial::GetAlphaMap() const { - NazaraAssert(HasAlphaMap(), "Material has no alpha map slot"); + NazaraAssert(HasAlphaMap(), "Material has no alpha texture slot"); return m_material.GetTexture(m_textureIndexes.alpha); } + inline const std::shared_ptr& BasicMaterial::GetAlphaSampler() const + { + NazaraAssert(HasAlphaMap(), "Material has no alpha texture slot"); + return m_material.GetTextureSampler(m_textureIndexes.alpha); + } + inline const std::shared_ptr& BasicMaterial::GetDiffuseMap() const { - NazaraAssert(HasDiffuseMap(), "Material has no alpha map slot"); + NazaraAssert(HasDiffuseMap(), "Material has no alpha texture slot"); return m_material.GetTexture(m_textureIndexes.diffuse); } + inline const std::shared_ptr& BasicMaterial::GetDiffuseSampler() const + { + NazaraAssert(HasDiffuseMap(), "Material has no alpha texture slot"); + return m_material.GetTextureSampler(m_textureIndexes.diffuse); + } + inline bool BasicMaterial::HasAlphaMap() const { return m_textureIndexes.alpha != MaterialSettings::InvalidIndex; } - inline bool BasicMaterial::HasAlphaThreshold() const + inline bool BasicMaterial::HasAlphaTest() const + { + return m_conditionIndexes.alphaTest != MaterialSettings::InvalidIndex; + } + + inline bool BasicMaterial::HasAlphaTestThreshold() const { return m_uniformOffsets.alphaThreshold != MaterialSettings::InvalidIndex; } @@ -44,13 +67,43 @@ namespace Nz inline void BasicMaterial::SetAlphaMap(std::shared_ptr alphaMap) { NazaraAssert(HasAlphaMap(), "Material has no alpha map slot"); + bool hasAlphaMap = (alphaMap != nullptr); m_material.SetTexture(m_textureIndexes.alpha, std::move(alphaMap)); + + if (m_conditionIndexes.hasDiffuseMap != MaterialSettings::InvalidIndex) + m_material.EnableCondition(m_conditionIndexes.hasAlphaMap, hasAlphaMap); + } + + inline void BasicMaterial::SetAlphaSampler(std::shared_ptr alphaSampler) + { + NazaraAssert(HasAlphaMap(), "Material has no alpha map slot"); + m_material.SetTextureSampler(m_textureIndexes.alpha, std::move(alphaSampler)); } inline void BasicMaterial::SetDiffuseMap(std::shared_ptr diffuseMap) { NazaraAssert(HasDiffuseMap(), "Material has no diffuse map slot"); + bool hasDiffuseMap = (diffuseMap != nullptr); m_material.SetTexture(m_textureIndexes.diffuse, std::move(diffuseMap)); + + if (m_conditionIndexes.hasDiffuseMap != MaterialSettings::InvalidIndex) + m_material.EnableCondition(m_conditionIndexes.hasDiffuseMap, hasDiffuseMap); + } + + inline void BasicMaterial::SetDiffuseSampler(std::shared_ptr diffuseSampler) + { + NazaraAssert(HasDiffuseMap(), "Material has no diffuse map slot"); + m_material.SetTextureSampler(m_textureIndexes.diffuse, std::move(diffuseSampler)); + } + + inline const std::shared_ptr& BasicMaterial::GetSettings() + { + return s_materialSettings; + } + + inline auto BasicMaterial::GetOffsets() -> const UniformOffsets& + { + return s_uniformOffsets; } } diff --git a/include/Nazara/Graphics/Material.hpp b/include/Nazara/Graphics/Material.hpp index 1459e21d0..f3e58e271 100644 --- a/include/Nazara/Graphics/Material.hpp +++ b/include/Nazara/Graphics/Material.hpp @@ -41,6 +41,7 @@ namespace Nz inline void EnableAlphaTest(bool alphaTest); inline void EnableBlending(bool blending); inline void EnableColorWrite(bool colorWrite); + inline void EnableCondition(std::size_t conditionIndex, bool enable); inline void EnableDepthBuffer(bool depthBuffer); inline void EnableDepthSorting(bool depthSorting); inline void EnableDepthWrite(bool depthWrite); @@ -53,7 +54,7 @@ namespace Nz inline void EnableVertexColor(bool vertexColor); inline void EnsurePipelineUpdate() const; - + inline RendererComparison GetDepthCompareFunc() const; inline BlendFunc GetDstBlend() const; inline FaceSide GetFaceCulling() const; @@ -63,7 +64,7 @@ namespace Nz inline const MaterialPipelineInfo& GetPipelineInfo() const; inline float GetPointSize() const; inline const std::shared_ptr& GetSettings() const; - inline const std::shared_ptr& GetShader(ShaderStageType shaderStage) const; + inline const std::shared_ptr& GetShader(ShaderStageType shaderStage) const; inline BlendFunc GetSrcBlend() const; inline const std::shared_ptr& GetTexture(std::size_t textureIndex) const; inline const std::shared_ptr& GetTextureSampler(std::size_t textureIndex) const; @@ -76,6 +77,7 @@ namespace Nz inline bool IsAlphaTestEnabled() const; inline bool IsBlendingEnabled() const; inline bool IsColorWriteEnabled() const; + inline bool IsConditionEnabled(std::size_t conditionIndex) const; inline bool IsDepthBufferEnabled() const; inline bool IsDepthSortingEnabled() const; inline bool IsDepthWriteEnabled() const; @@ -92,7 +94,6 @@ namespace Nz inline void SetFaceFilling(FaceFilling filling); inline void SetLineWidth(float lineWidth); inline void SetPointSize(float pointSize); - inline void SetShader(ShaderStageType shaderStage, std::shared_ptr shader); inline void SetUniformBuffer(std::size_t bufferIndex, UniformBufferRef uniformBuffer); inline void SetSrcBlend(BlendFunc func); inline void SetTexture(std::size_t textureIndex, std::shared_ptr texture); @@ -115,7 +116,8 @@ namespace Nz std::vector m_textures; std::vector m_uniformBuffers; mutable std::shared_ptr m_pipeline; - MaterialPipelineInfo m_pipelineInfo; + UInt32 m_enabledConditions; + mutable MaterialPipelineInfo m_pipelineInfo; mutable bool m_pipelineUpdated; bool m_shadowCastingEnabled; }; diff --git a/include/Nazara/Graphics/Material.inl b/include/Nazara/Graphics/Material.inl index 3729bf2e2..8a2e56b15 100644 --- a/include/Nazara/Graphics/Material.inl +++ b/include/Nazara/Graphics/Material.inl @@ -111,6 +111,15 @@ namespace Nz InvalidatePipeline(); } + inline void Material::EnableCondition(std::size_t conditionIndex, bool enable) + { + if (TestBit(m_enabledConditions, conditionIndex) != enable) + { + m_enabledConditions = SetBit(m_enabledConditions, conditionIndex); + InvalidatePipeline(); + } + } + /*! * \brief Enable/Disable depth buffer for this material * @@ -428,9 +437,9 @@ namespace Nz * \brief Gets the über-shader used by this material * \return Constant pointer to the über-shader used */ - inline const std::shared_ptr& Material::GetShader(ShaderStageType shaderStage) const + inline const std::shared_ptr& Material::GetShader(ShaderStageType shaderStage) const { - return m_pipelineInfo.shaders[UnderlyingCast(shaderStage)]; + return m_pipelineInfo.shaders[UnderlyingCast(shaderStage)].uberShader; } /*! @@ -507,6 +516,11 @@ namespace Nz return m_pipelineInfo.colorWrite; } + inline bool Material::IsConditionEnabled(std::size_t conditionIndex) const + { + return TestBit(m_enabledConditions, conditionIndex); + } + /*! * \brief Checks whether this material has depth buffer enabled * \return true If it is the case @@ -682,22 +696,6 @@ namespace Nz InvalidatePipeline(); } - /*! - * \brief Sets the shader with a constant reference to a ubershader - * - * \param uberShader Uber shader to apply - * - * \remark Invalidates the pipeline - * - * \see GetShader - */ - inline void Material::SetShader(ShaderStageType shaderStage, std::shared_ptr shader) - { - m_pipelineInfo.shaders[UnderlyingCast(shaderStage)] = std::move(shader); - - InvalidatePipeline(); - } - inline void Material::SetUniformBuffer(std::size_t bufferIndex, UniformBufferRef uniformBuffer) { NazaraAssert(bufferIndex < m_uniformBuffers.size(), "Invalid shared uniform buffer index"); @@ -739,6 +737,19 @@ namespace Nz inline void Material::UpdatePipeline() const { + for (auto& shader : m_pipelineInfo.shaders) + shader.enabledConditions = 0; + + const auto& conditions = m_settings->GetConditions(); + for (std::size_t conditionIndex = 0; conditionIndex < conditions.size(); ++conditionIndex) + { + if (TestBit(m_enabledConditions, conditionIndex)) + { + for (std::size_t shaderStage = 0; shaderStage < ShaderStageTypeCount; ++shaderStage) + m_pipelineInfo.shaders[shaderStage].enabledConditions |= conditions[conditionIndex].enabledConditions[shaderStage]; + } + } + m_pipeline = MaterialPipeline::Get(m_pipelineInfo); m_pipelineUpdated = true; } diff --git a/include/Nazara/Graphics/MaterialPipeline.hpp b/include/Nazara/Graphics/MaterialPipeline.hpp index 188536b23..9e02828b1 100644 --- a/include/Nazara/Graphics/MaterialPipeline.hpp +++ b/include/Nazara/Graphics/MaterialPipeline.hpp @@ -17,18 +17,24 @@ namespace Nz { - class ShaderStage; + class UberShader; struct MaterialPipelineInfo : RenderStates { + struct ShaderStage + { + std::shared_ptr uberShader; + Nz::UInt64 enabledConditions = 0; + }; + bool alphaTest = false; bool depthSorting = false; bool hasVertexColor = false; bool reflectionMapping = false; bool shadowReceive = true; + std::array shaders; std::shared_ptr settings; - std::array, ShaderStageTypeCount> shaders; }; inline bool operator==(const MaterialPipelineInfo& lhs, const MaterialPipelineInfo& rhs); diff --git a/include/Nazara/Graphics/MaterialPipeline.inl b/include/Nazara/Graphics/MaterialPipeline.inl index f4d80e9c4..b83e6fc6b 100644 --- a/include/Nazara/Graphics/MaterialPipeline.inl +++ b/include/Nazara/Graphics/MaterialPipeline.inl @@ -40,7 +40,10 @@ namespace Nz for (std::size_t i = 0; i < lhs.shaders.size(); ++i) { - if (lhs.shaders[i] != rhs.shaders[i]) + if (lhs.shaders[i].enabledConditions != rhs.shaders[i].enabledConditions) + return false; + + if (lhs.shaders[i].uberShader != rhs.shaders[i].uberShader) return false; } @@ -82,7 +85,10 @@ namespace std NazaraPipelineMember(settings.get()); //< Hash pointer for (const auto& shader : pipelineInfo.shaders) - Nz::HashCombine(seed, shader.get()); + { + Nz::HashCombine(seed, shader.enabledConditions); + Nz::HashCombine(seed, shader.uberShader.get()); + } #undef NazaraPipelineMember #undef NazaraPipelineBoolMember diff --git a/include/Nazara/Graphics/MaterialSettings.hpp b/include/Nazara/Graphics/MaterialSettings.hpp index e2aec4257..272e478df 100644 --- a/include/Nazara/Graphics/MaterialSettings.hpp +++ b/include/Nazara/Graphics/MaterialSettings.hpp @@ -19,29 +19,35 @@ namespace Nz { + class UberShader; + class MaterialSettings { public: - using DefaultShaders = std::array, ShaderStageTypeCount>; using PredefinedBinding = std::array; + using Shaders = std::array, ShaderStageTypeCount>; + struct Builder; + struct Condition; struct SharedUniformBlock; struct Texture; struct UniformBlock; inline MaterialSettings(); - inline MaterialSettings(std::vector textures, std::vector uniformBlocks, std::vector sharedUniformBlocks, const PredefinedBinding& predefinedBinding, DefaultShaders defaultShaders); + inline MaterialSettings(Builder builder); MaterialSettings(const MaterialSettings&) = default; MaterialSettings(MaterialSettings&&) = delete; ~MaterialSettings() = default; - inline const std::shared_ptr& GetDefaultShader(ShaderStageType stage) const; - inline const DefaultShaders& GetDefaultShaders() const; + inline const std::vector& GetConditions() const; + inline std::size_t GetConditionIndex(const std::string_view& name) const; inline std::size_t GetPredefinedBindingIndex(PredefinedShaderBinding binding) const; inline const std::shared_ptr& GetRenderPipelineLayout() const; + inline const std::shared_ptr& GetShader(ShaderStageType stage) const; + inline const Shaders& GetShaders() const; inline const std::vector& GetSharedUniformBlocks() const; - inline std::size_t GetSharedUniformBlockVariableOffset(std::size_t uniformBlockIndex, const std::string_view& name) const; inline std::size_t GetSharedUniformBlockIndex(const std::string_view& name) const; + inline std::size_t GetSharedUniformBlockVariableOffset(std::size_t uniformBlockIndex, const std::string_view& name) const; inline const std::vector& GetTextures() const; inline std::size_t GetTextureIndex(const std::string_view& name) const; inline const std::vector& GetUniformBlocks() const; @@ -53,6 +59,22 @@ namespace Nz static constexpr std::size_t InvalidIndex = std::numeric_limits::max(); + struct Builder + { + PredefinedBinding predefinedBinding; + Shaders shaders; + std::vector conditions; + std::vector textures; + std::vector uniformBlocks; + std::vector sharedUniformBlocks; + }; + + struct Condition + { + std::string name; + std::array enabledConditions; + }; + struct UniformVariable { std::string name; @@ -84,11 +106,7 @@ namespace Nz private: std::shared_ptr m_pipelineLayout; - std::vector m_sharedUniformBlocks; - std::vector m_textures; - std::vector m_uniformBlocks; - DefaultShaders m_defaultShaders; - PredefinedBinding m_predefinedBinding; + Builder m_data; }; } diff --git a/include/Nazara/Graphics/MaterialSettings.inl b/include/Nazara/Graphics/MaterialSettings.inl index fd0356e04..e88d6845e 100644 --- a/include/Nazara/Graphics/MaterialSettings.inl +++ b/include/Nazara/Graphics/MaterialSettings.inl @@ -10,22 +10,18 @@ namespace Nz { inline MaterialSettings::MaterialSettings() : - MaterialSettings({}, {}, {}, { InvalidIndex }, {}) + MaterialSettings(Builder{}) { } - inline MaterialSettings::MaterialSettings(std::vector textures, std::vector uniformBlocks, std::vector sharedUniformBlocks, const PredefinedBinding& predefinedBindings, DefaultShaders defaultShaders) : - m_sharedUniformBlocks(std::move(sharedUniformBlocks)), - m_textures(std::move(textures)), - m_uniformBlocks(std::move(uniformBlocks)), - m_defaultShaders(std::move(defaultShaders)), - m_predefinedBinding(predefinedBindings) + inline MaterialSettings::MaterialSettings(Builder data) : + m_data(std::move(data)) { RenderPipelineLayoutInfo info; unsigned int bindingIndex = 0; - for (const Texture& textureInfo : m_textures) + for (const Texture& textureInfo : m_data.textures) { info.bindings.push_back({ //textureInfo.bindingPoint, @@ -35,7 +31,7 @@ namespace Nz }); } - for (const UniformBlock& ubo : m_uniformBlocks) + for (const UniformBlock& ubo : m_data.uniformBlocks) { info.bindings.push_back({ //ubo.bindingPoint, @@ -45,7 +41,7 @@ namespace Nz }); } - for (const SharedUniformBlock& ubo : m_sharedUniformBlocks) + for (const SharedUniformBlock& ubo : m_data.sharedUniformBlocks) { info.bindings.push_back({ //ubo.bindingPoint, @@ -58,19 +54,25 @@ namespace Nz m_pipelineLayout = Graphics::Instance()->GetRenderDevice().InstantiateRenderPipelineLayout(std::move(info)); } - inline const std::shared_ptr& MaterialSettings::GetDefaultShader(ShaderStageType stage) const + inline auto MaterialSettings::GetConditions() const -> const std::vector& { - return m_defaultShaders[UnderlyingCast(stage)]; + return m_data.conditions; } - inline auto MaterialSettings::GetDefaultShaders() const -> const DefaultShaders& + inline std::size_t MaterialSettings::GetConditionIndex(const std::string_view& name) const { - return m_defaultShaders; + for (std::size_t i = 0; i < m_data.conditions.size(); ++i) + { + if (m_data.conditions[i].name == name) + return i; + } + + return InvalidIndex; } inline std::size_t MaterialSettings::GetPredefinedBindingIndex(PredefinedShaderBinding binding) const { - return m_predefinedBinding[UnderlyingCast(binding)]; + return m_data.predefinedBinding[UnderlyingCast(binding)]; } inline const std::shared_ptr& MaterialSettings::GetRenderPipelineLayout() const @@ -78,32 +80,37 @@ namespace Nz return m_pipelineLayout; } + inline const std::shared_ptr& MaterialSettings::GetShader(ShaderStageType stage) const + { + return m_data.shaders[UnderlyingCast(stage)]; + } + + inline auto MaterialSettings::GetShaders() const -> const Shaders& + { + return m_data.shaders; + } + inline auto MaterialSettings::GetSharedUniformBlocks() const -> const std::vector& { - return m_sharedUniformBlocks; + return m_data.sharedUniformBlocks; } inline std::size_t MaterialSettings::GetSharedUniformBlockIndex(const std::string_view& name) const { - for (std::size_t i = 0; i < m_sharedUniformBlocks.size(); ++i) + for (std::size_t i = 0; i < m_data.sharedUniformBlocks.size(); ++i) { - if (m_sharedUniformBlocks[i].name == name) + if (m_data.sharedUniformBlocks[i].name == name) return i; } return InvalidIndex; } - inline auto MaterialSettings::GetTextures() const -> const std::vector& - { - return m_textures; - } - inline std::size_t MaterialSettings::GetSharedUniformBlockVariableOffset(std::size_t uniformBlockIndex, const std::string_view& name) const { - assert(uniformBlockIndex < m_sharedUniformBlocks.size()); + assert(uniformBlockIndex < m_data.sharedUniformBlocks.size()); - const std::vector& variables = m_sharedUniformBlocks[uniformBlockIndex].uniforms; + const std::vector& variables = m_data.sharedUniformBlocks[uniformBlockIndex].uniforms; for (std::size_t i = 0; i < variables.size(); ++i) { if (variables[i].name == name) @@ -113,11 +120,16 @@ namespace Nz return InvalidIndex; } + inline auto MaterialSettings::GetTextures() const -> const std::vector& + { + return m_data.textures; + } + inline std::size_t MaterialSettings::GetTextureIndex(const std::string_view& name) const { - for (std::size_t i = 0; i < m_textures.size(); ++i) + for (std::size_t i = 0; i < m_data.textures.size(); ++i) { - if (m_textures[i].name == name) + if (m_data.textures[i].name == name) return i; } @@ -126,14 +138,14 @@ namespace Nz inline auto MaterialSettings::GetUniformBlocks() const -> const std::vector& { - return m_uniformBlocks; + return m_data.uniformBlocks; } inline std::size_t MaterialSettings::GetUniformBlockIndex(const std::string_view& name) const { - for (std::size_t i = 0; i < m_uniformBlocks.size(); ++i) + for (std::size_t i = 0; i < m_data.uniformBlocks.size(); ++i) { - if (m_uniformBlocks[i].name == name) + if (m_data.uniformBlocks[i].name == name) return i; } @@ -142,9 +154,9 @@ namespace Nz inline std::size_t MaterialSettings::GetUniformBlockVariableOffset(std::size_t uniformBlockIndex, const std::string_view& name) const { - assert(uniformBlockIndex < m_uniformBlocks.size()); + assert(uniformBlockIndex < m_data.uniformBlocks.size()); - const std::vector& variables = m_uniformBlocks[uniformBlockIndex].uniforms; + const std::vector& variables = m_data.uniformBlocks[uniformBlockIndex].uniforms; for (std::size_t i = 0; i < variables.size(); ++i) { if (variables[i].name == name) diff --git a/include/Nazara/Graphics/UberShader.hpp b/include/Nazara/Graphics/UberShader.hpp new file mode 100644 index 000000000..ae8221199 --- /dev/null +++ b/include/Nazara/Graphics/UberShader.hpp @@ -0,0 +1,39 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_UBER_SHADER_HPP +#define NAZARA_UBER_SHADER_HPP + +#include +#include +#include +#include +#include + +namespace Nz +{ + class ShaderStage; + + class NAZARA_GRAPHICS_API UberShader + { + public: + inline UberShader(ShaderAst shaderAst); + ~UberShader() = default; + + UInt64 GetConditionFlagByName(const std::string_view& condition) const; + + const std::shared_ptr& Get(UInt64 combination); + + private: + std::unordered_map> m_combinations; + ShaderAst m_shaderAst; + UInt64 m_combinationMask; + }; +} + +#include + +#endif // NAZARA_UBER_SHADER_HPP diff --git a/include/Nazara/Graphics/UberShader.inl b/include/Nazara/Graphics/UberShader.inl new file mode 100644 index 000000000..376dc23cb --- /dev/null +++ b/include/Nazara/Graphics/UberShader.inl @@ -0,0 +1,12 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ +} + +#include diff --git a/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp b/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp index 8398c8e61..610438e10 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp @@ -36,6 +36,7 @@ namespace Nz std::shared_ptr InstantiateCommandPool(QueueType queueType) override; std::shared_ptr InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override; std::shared_ptr InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) override; + std::shared_ptr InstantiateShaderStage(const ShaderAst& shaderAst, const ShaderWriter::States& states) override; std::shared_ptr InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) override; std::shared_ptr InstantiateTexture(const TextureInfo& params) override; std::shared_ptr InstantiateTextureSampler(const TextureSamplerInfo& params) override; diff --git a/include/Nazara/OpenGLRenderer/OpenGLRenderPipelineLayout.hpp b/include/Nazara/OpenGLRenderer/OpenGLRenderPipelineLayout.hpp index 30ceb101c..0340f43ae 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLRenderPipelineLayout.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLRenderPipelineLayout.hpp @@ -52,9 +52,11 @@ namespace Nz void Release(ShaderBinding& binding); inline void TryToShrink(); + static constexpr UInt32 InvalidIndex = 0xFFFFFFFF; + struct TextureDescriptor { - UInt32 bindingIndex; + UInt32 bindingIndex = InvalidIndex; GLuint texture; GLuint sampler; GL::TextureTarget textureTarget; @@ -62,7 +64,7 @@ namespace Nz struct UniformBufferDescriptor { - UInt32 bindingIndex; + UInt32 bindingIndex = InvalidIndex; GLuint buffer; GLintptr offset; GLsizeiptr size; diff --git a/include/Nazara/OpenGLRenderer/OpenGLShaderStage.hpp b/include/Nazara/OpenGLRenderer/OpenGLShaderStage.hpp index 0463f5b49..d917f6f14 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLShaderStage.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLShaderStage.hpp @@ -12,13 +12,17 @@ #include #include #include +#include #include namespace Nz { + class ShaderAst; + class NAZARA_OPENGLRENDERER_API OpenGLShaderStage : public ShaderStage { public: + OpenGLShaderStage(OpenGLDevice& device, const ShaderAst& shaderAst, const ShaderWriter::States& states); OpenGLShaderStage(OpenGLDevice& device, ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize); OpenGLShaderStage(const OpenGLShaderStage&) = delete; OpenGLShaderStage(OpenGLShaderStage&&) noexcept = default; @@ -30,6 +34,9 @@ namespace Nz OpenGLShaderStage& operator=(OpenGLShaderStage&&) noexcept = default; private: + void CheckCompilationStatus(); + void Create(OpenGLDevice& device, const ShaderAst& shaderAst, const ShaderWriter::States& states); + GL::Shader m_shader; }; } diff --git a/include/Nazara/OpenGLRenderer/Wrapper/WGL/WGLContext.inl b/include/Nazara/OpenGLRenderer/Wrapper/WGL/WGLContext.inl index d6ca768d4..f21ceb1e2 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/WGL/WGLContext.inl +++ b/include/Nazara/OpenGLRenderer/Wrapper/WGL/WGLContext.inl @@ -9,7 +9,8 @@ namespace Nz::GL { inline GL::WGLContext::WGLContext(const OpenGLDevice* device, const WGLLoader& loader) : Context(device), - m_loader(loader) + m_loader(loader), + m_handle(nullptr) { } diff --git a/include/Nazara/Renderer/RenderDevice.hpp b/include/Nazara/Renderer/RenderDevice.hpp index fb26dc58f..5f658ef69 100644 --- a/include/Nazara/Renderer/RenderDevice.hpp +++ b/include/Nazara/Renderer/RenderDevice.hpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,7 @@ namespace Nz { class CommandPool; + class ShaderAst; class ShaderStage; class NAZARA_RENDERER_API RenderDevice @@ -33,6 +35,7 @@ namespace Nz virtual std::shared_ptr InstantiateCommandPool(QueueType queueType) = 0; virtual std::shared_ptr InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) = 0; virtual std::shared_ptr InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) = 0; + virtual std::shared_ptr InstantiateShaderStage(const ShaderAst& shaderAst, const ShaderWriter::States& states) = 0; virtual std::shared_ptr InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) = 0; std::shared_ptr InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const std::filesystem::path& sourcePath); virtual std::shared_ptr InstantiateTexture(const TextureInfo& params) = 0; diff --git a/include/Nazara/Shader/ShaderAst.hpp b/include/Nazara/Shader/ShaderAst.hpp index 5b80a1380..54199a179 100644 --- a/include/Nazara/Shader/ShaderAst.hpp +++ b/include/Nazara/Shader/ShaderAst.hpp @@ -41,6 +41,8 @@ namespace Nz void AddStruct(std::string name, std::vector members); void AddUniform(std::string name, ShaderExpressionType type, std::optional bindingIndex = {}, std::optional memoryLayout = {}); + inline std::size_t FindConditionByName(const std::string_view& conditionName) const; + inline const Condition& GetCondition(std::size_t i) const; inline std::size_t GetConditionCount() const; inline const std::vector& GetConditions() const; @@ -110,6 +112,8 @@ namespace Nz ShaderExpressionType type; }; + static constexpr std::size_t InvalidCondition = std::numeric_limits::max(); + private: std::vector m_conditions; std::vector m_functions; diff --git a/include/Nazara/Shader/ShaderAst.inl b/include/Nazara/Shader/ShaderAst.inl index f00517db5..64bce4583 100644 --- a/include/Nazara/Shader/ShaderAst.inl +++ b/include/Nazara/Shader/ShaderAst.inl @@ -12,6 +12,17 @@ namespace Nz { } + inline std::size_t ShaderAst::FindConditionByName(const std::string_view& conditionName) const + { + for (std::size_t i = 0; i < m_conditions.size(); ++i) + { + if (m_conditions[i].name == conditionName) + return i; + } + + return InvalidCondition; + } + inline auto Nz::ShaderAst::GetCondition(std::size_t i) const -> const Condition& { assert(i < m_functions.size()); diff --git a/include/Nazara/Shader/ShaderAstSerializer.hpp b/include/Nazara/Shader/ShaderAstSerializer.hpp index 5155a702e..e6e50487a 100644 --- a/include/Nazara/Shader/ShaderAstSerializer.hpp +++ b/include/Nazara/Shader/ShaderAstSerializer.hpp @@ -141,6 +141,7 @@ namespace Nz }; NAZARA_SHADER_API ByteArray SerializeShader(const ShaderAst& shader); + inline ShaderAst UnserializeShader(const void* data, std::size_t size); NAZARA_SHADER_API ShaderAst UnserializeShader(ByteStream& stream); } diff --git a/include/Nazara/Shader/ShaderAstSerializer.inl b/include/Nazara/Shader/ShaderAstSerializer.inl index 31882eeb7..6b61c1197 100644 --- a/include/Nazara/Shader/ShaderAstSerializer.inl +++ b/include/Nazara/Shader/ShaderAstSerializer.inl @@ -128,6 +128,12 @@ namespace Nz m_stream(stream) { } + + inline ShaderAst UnserializeShader(const void* data, std::size_t size) + { + ByteStream byteStream(data, size); + return UnserializeShader(byteStream); + } } #include diff --git a/include/Nazara/Shader/ShaderBuilder.hpp b/include/Nazara/Shader/ShaderBuilder.hpp index d7c982eee..03ac51ac2 100644 --- a/include/Nazara/Shader/ShaderBuilder.hpp +++ b/include/Nazara/Shader/ShaderBuilder.hpp @@ -56,7 +56,12 @@ namespace Nz::ShaderBuilder constexpr GenBuilder DeclareVariable; constexpr GenBuilder Discard; constexpr BinOpBuilder Divide; - constexpr BinOpBuilder Equal; + constexpr BinOpBuilder Equal; + constexpr BinOpBuilder GreaterThan; + constexpr BinOpBuilder GreaterThanOrEqual; + constexpr BinOpBuilder LessThan; + constexpr BinOpBuilder LessThanOrEqual; + constexpr BinOpBuilder NotEqual; constexpr GenBuilder ExprStatement; constexpr GenBuilder Identifier; constexpr GenBuilder IntrinsicCall; diff --git a/include/Nazara/Shader/ShaderEnums.hpp b/include/Nazara/Shader/ShaderEnums.hpp index 596292d9d..ccb2f78d5 100644 --- a/include/Nazara/Shader/ShaderEnums.hpp +++ b/include/Nazara/Shader/ShaderEnums.hpp @@ -33,7 +33,7 @@ namespace Nz::ShaderNodes UInt1, //< uint UInt2, //< uvec2 UInt3, //< uvec3 - UInt4 //< uvec4 + UInt4 //< uvec4 }; enum class BinaryType @@ -43,7 +43,12 @@ namespace Nz::ShaderNodes Multiply, //< * Divide, //< / - Equality //< == + CompEq, //< == + CompGe, //< >= + CompGt, //< > + CompLe, //< <= + CompLt, //< < + CompNe //< <= }; enum class BuiltinEntry @@ -87,7 +92,9 @@ namespace Nz::ShaderNodes IntrinsicCall, Sample2D, SwizzleOp, - StatementBlock + StatementBlock, + + Max = StatementBlock }; enum class SsaInstruction diff --git a/include/Nazara/Shader/ShaderNodes.inl b/include/Nazara/Shader/ShaderNodes.inl index fe0872a9d..f3fbecaff 100644 --- a/include/Nazara/Shader/ShaderNodes.inl +++ b/include/Nazara/Shader/ShaderNodes.inl @@ -149,7 +149,7 @@ namespace Nz::ShaderNodes inline Discard::Discard() : - Statement(NodeType::DeclareVariable) + Statement(NodeType::Discard) { } diff --git a/include/Nazara/Shader/ShaderWriter.hpp b/include/Nazara/Shader/ShaderWriter.hpp index 3fd25d7ff..337c3c3cf 100644 --- a/include/Nazara/Shader/ShaderWriter.hpp +++ b/include/Nazara/Shader/ShaderWriter.hpp @@ -28,7 +28,7 @@ namespace Nz struct States { - std::unordered_set enabledConditions; + Nz::UInt64 enabledConditions = 0; }; }; } diff --git a/include/Nazara/Shader/SpirvWriter.inl b/include/Nazara/Shader/SpirvWriter.inl index 44babe815..ed518e5f4 100644 --- a/include/Nazara/Shader/SpirvWriter.inl +++ b/include/Nazara/Shader/SpirvWriter.inl @@ -3,13 +3,17 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include namespace Nz { inline bool SpirvWriter::IsConditionEnabled(const std::string& condition) const { - return m_context.states->enabledConditions.find(condition) != m_context.states->enabledConditions.end(); + std::size_t conditionIndex = m_context.shader->FindConditionByName(condition); + assert(conditionIndex != ShaderAst::InvalidCondition); + + return TestBit(m_context.states->enabledConditions, conditionIndex); } } diff --git a/include/Nazara/VulkanRenderer/VulkanDevice.hpp b/include/Nazara/VulkanRenderer/VulkanDevice.hpp index 873c7dc9c..4d47de3bf 100644 --- a/include/Nazara/VulkanRenderer/VulkanDevice.hpp +++ b/include/Nazara/VulkanRenderer/VulkanDevice.hpp @@ -27,6 +27,7 @@ namespace Nz std::shared_ptr InstantiateCommandPool(QueueType queueType) override; std::shared_ptr InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override; std::shared_ptr InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) override; + std::shared_ptr InstantiateShaderStage(const ShaderAst& shaderAst, const ShaderWriter::States& states) override; std::shared_ptr InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) override; std::shared_ptr InstantiateTexture(const TextureInfo& params) override; std::shared_ptr InstantiateTextureSampler(const TextureSamplerInfo& params) override; diff --git a/include/Nazara/VulkanRenderer/VulkanShaderStage.hpp b/include/Nazara/VulkanRenderer/VulkanShaderStage.hpp index 059183853..a82ed6894 100644 --- a/include/Nazara/VulkanRenderer/VulkanShaderStage.hpp +++ b/include/Nazara/VulkanRenderer/VulkanShaderStage.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -23,6 +24,7 @@ namespace Nz VulkanShaderStage(VulkanShaderStage&&) = delete; ~VulkanShaderStage() = default; + bool Create(Vk::Device& device, const ShaderAst& shader, const ShaderWriter::States& states); bool Create(Vk::Device& device, ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize); inline const Vk::ShaderModule& GetHandle() const; diff --git a/shaders/BasicMaterial/basicmaterial.frag.shaderflow b/shaders/BasicMaterial/basicmaterial.frag.shaderflow index 4ffa6960d..ead0fa7f7 100644 --- a/shaders/BasicMaterial/basicmaterial.frag.shaderflow +++ b/shaders/BasicMaterial/basicmaterial.frag.shaderflow @@ -19,35 +19,52 @@ "type": "UniformBufferObject" } ], + "conditions": [ + { + "name": "HAS_DIFFUSE_TEXTURE" + }, + { + "name": "HAS_ALPHA_TEXTURE" + }, + { + "name": "ALPHA_TEST" + } + ], "connections": [ { - "in_id": "{fbaddbbe-f9cd-4e8d-b7a8-40c10c96f580}", + "in_id": "{359a78e1-df0d-467f-907e-7bff04a55db5}", + "in_index": 3, + "out_id": "{93fdbb4c-bc81-4100-89a9-b465793099b9}", + "out_index": 0 + }, + { + "in_id": "{359a78e1-df0d-467f-907e-7bff04a55db5}", "in_index": 0, - "out_id": "{ac98a68f-0160-4189-af31-b8278e7c119c}", + "out_id": "{becdd0d4-2b28-44f5-86c2-2ed6b846326c}", "out_index": 0 }, { - "in_id": "{fbaddbbe-f9cd-4e8d-b7a8-40c10c96f580}", - "in_index": 1, - "out_id": "{db10f064-504d-4072-a49e-51a061b2efbe}", - "out_index": 0 - }, - { - "in_id": "{cf0ae20a-88cd-4788-9ed7-eaf014d8f971}", + "in_id": "{92d95fe0-84f6-4d27-91ea-992d5f73c04e}", "in_index": 0, - "out_id": "{c41cd67b-2f34-4ec4-acc6-2f7285e7c6e3}", + "out_id": "{359a78e1-df0d-467f-907e-7bff04a55db5}", "out_index": 0 }, { - "in_id": "{cf0ae20a-88cd-4788-9ed7-eaf014d8f971}", + "in_id": "{bed466d8-5ed0-4e8a-bba7-1c809cb4c3f7}", "in_index": 1, - "out_id": "{74d3ca95-ae1d-496d-88c1-ce6c7327012a}", + "out_id": "{07a43c79-67e2-46b1-87d4-e00d2da22820}", "out_index": 0 }, { - "in_id": "{f5a6874b-0559-4fd1-9836-27567f9696a4}", - "in_index": 1, - "out_id": "{fbaddbbe-f9cd-4e8d-b7a8-40c10c96f580}", + "in_id": "{93fdbb4c-bc81-4100-89a9-b465793099b9}", + "in_index": 0, + "out_id": "{6fcfbcd0-c2df-41dd-bb50-74b455b9021f}", + "out_index": 0 + }, + { + "in_id": "{becdd0d4-2b28-44f5-86c2-2ed6b846326c}", + "in_index": 0, + "out_id": "{f5a6874b-0559-4fd1-9836-27567f9696a4}", "out_index": 0 }, { @@ -57,22 +74,136 @@ "out_index": 0 }, { - "in_id": "{bed466d8-5ed0-4e8a-bba7-1c809cb4c3f7}", + "in_id": "{92d95fe0-84f6-4d27-91ea-992d5f73c04e}", "in_index": 1, - "out_id": "{43df5c43-d6f4-440f-a049-4fde6e738883}", - "out_index": 0 - }, - { - "in_id": "{43df5c43-d6f4-440f-a049-4fde6e738883}", - "in_index": 0, - "out_id": "{07a43c79-67e2-46b1-87d4-e00d2da22820}", + "out_id": "{f5a6874b-0559-4fd1-9836-27567f9696a4}", "out_index": 0 }, { "in_id": "{be3547ff-0bf3-4701-9c27-c21e9d1322c3}", "in_index": 0, - "out_id": "{f5a6874b-0559-4fd1-9836-27567f9696a4}", + "out_id": "{92d95fe0-84f6-4d27-91ea-992d5f73c04e}", "out_index": 0 + }, + { + "in_id": "{e1f86d56-eb21-4267-9075-e6b0cc875a6d}", + "in_index": 0, + "out_id": "{bed466d8-5ed0-4e8a-bba7-1c809cb4c3f7}", + "out_index": 0 + }, + { + "in_id": "{93fdbb4c-bc81-4100-89a9-b465793099b9}", + "in_index": 1, + "out_id": "{becdd0d4-2b28-44f5-86c2-2ed6b846326c}", + "out_index": 3 + }, + { + "in_id": "{359a78e1-df0d-467f-907e-7bff04a55db5}", + "in_index": 2, + "out_id": "{becdd0d4-2b28-44f5-86c2-2ed6b846326c}", + "out_index": 2 + }, + { + "in_id": "{fbaddbbe-f9cd-4e8d-b7a8-40c10c96f580}", + "in_index": 0, + "out_id": "{ac98a68f-0160-4189-af31-b8278e7c119c}", + "out_index": 0 + }, + { + "in_id": "{7750a050-b116-4e1b-bd89-b194c366d256}", + "in_index": 1, + "out_id": "{ca2c2ac5-39e0-4814-9432-fbf3e20d3cad}", + "out_index": 0 + }, + { + "in_id": "{3cdb5bb1-f572-4055-a1af-460b152b0c13}", + "in_index": 0, + "out_id": "{d7acd173-9188-43b5-bfa1-31f17dff44ad}", + "out_index": 0 + }, + { + "in_id": "{cf0ae20a-88cd-4788-9ed7-eaf014d8f971}", + "in_index": 0, + "out_id": "{c41cd67b-2f34-4ec4-acc6-2f7285e7c6e3}", + "out_index": 0 + }, + { + "in_id": "{e1f86d56-eb21-4267-9075-e6b0cc875a6d}", + "in_index": 1, + "out_id": "{07a43c79-67e2-46b1-87d4-e00d2da22820}", + "out_index": 0 + }, + { + "in_id": "{359a78e1-df0d-467f-907e-7bff04a55db5}", + "in_index": 1, + "out_id": "{becdd0d4-2b28-44f5-86c2-2ed6b846326c}", + "out_index": 1 + }, + { + "in_id": "{fbaddbbe-f9cd-4e8d-b7a8-40c10c96f580}", + "in_index": 1, + "out_id": "{db10f064-504d-4072-a49e-51a061b2efbe}", + "out_index": 0 + }, + { + "in_id": "{d7acd173-9188-43b5-bfa1-31f17dff44ad}", + "in_index": 1, + "out_id": "{1f9d52d7-4f44-4d96-8edb-fbc1239a93bb}", + "out_index": 0 + }, + { + "in_id": "{bed466d8-5ed0-4e8a-bba7-1c809cb4c3f7}", + "in_index": 0, + "out_id": "{fbaddbbe-f9cd-4e8d-b7a8-40c10c96f580}", + "out_index": 0 + }, + { + "in_id": "{f5a6874b-0559-4fd1-9836-27567f9696a4}", + "in_index": 1, + "out_id": "{e1f86d56-eb21-4267-9075-e6b0cc875a6d}", + "out_index": 0 + }, + { + "in_id": "{cf0ae20a-88cd-4788-9ed7-eaf014d8f971}", + "in_index": 1, + "out_id": "{74d3ca95-ae1d-496d-88c1-ce6c7327012a}", + "out_index": 0 + }, + { + "in_id": "{bb071807-e65e-4c31-acf0-d296efa665fa}", + "in_index": 0, + "out_id": "{92d95fe0-84f6-4d27-91ea-992d5f73c04e}", + "out_index": 0 + }, + { + "in_id": "{7750a050-b116-4e1b-bd89-b194c366d256}", + "in_index": 0, + "out_id": "{f9ba0cce-3b85-4f95-a79e-a2f64d955d89}", + "out_index": 0 + }, + { + "in_id": "{6fcfbcd0-c2df-41dd-bb50-74b455b9021f}", + "in_index": 0, + "out_id": "{7750a050-b116-4e1b-bd89-b194c366d256}", + "out_index": 0 + }, + { + "in_id": "{d7acd173-9188-43b5-bfa1-31f17dff44ad}", + "in_index": 0, + "out_id": "{fc7542b2-5752-4891-98c1-35b498da257b}", + "out_index": 0 + }, + { + "in_id": "{fc7542b2-5752-4891-98c1-35b498da257b}", + "in_index": 1, + "out_id": "{743930bd-1d81-4d4c-b7ec-175a34838d69}", + "out_index": 0 + }, + { + "in_id": "{fc7542b2-5752-4891-98c1-35b498da257b}", + "in_index": 0, + "out_id": "{bb071807-e65e-4c31-acf0-d296efa665fa}", + "out_index": 3 } ], "inputs": [ @@ -103,8 +234,22 @@ "variable_name": "" }, "position": { - "x": 103, - "y": 173 + "x": 330.0833333333333, + "y": 236.19444444444446 + } + }, + { + "id": "{becdd0d4-2b28-44f5-86c2-2ed6b846326c}", + "model": { + "name": "vec_decompose", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "variable_name": "" + }, + "position": { + "x": 1022.5200000000003, + "y": -53.35999999999996 } }, { @@ -117,8 +262,8 @@ "variable_name": "lightFactor" }, "position": { - "x": 278, - "y": 212 + "x": 486.33333333333326, + "y": 285.61111111111114 } }, { @@ -136,8 +281,8 @@ "variable_name": "lightDir" }, "position": { - "x": 115, - "y": 267 + "x": 294.1666666666667, + "y": 358.6666666666667 } }, { @@ -150,8 +295,8 @@ "variable_name": "" }, "position": { - "x": 299, - "y": 488 + "x": 167.75, + "y": 473.97222222222194 } }, { @@ -165,8 +310,8 @@ "variable_name": "" }, "position": { - "x": 103, - "y": 470 + "x": -10.194444444444457, + "y": 445 } }, { @@ -180,8 +325,8 @@ "variable_name": "" }, "position": { - "x": 113, - "y": 579 + "x": -0.19444444444445708, + "y": 554.0000000000001 } }, { @@ -191,11 +336,25 @@ "preview_enabled": false, "preview_height": 64, "preview_width": 64, + "variable_name": "textureColor" + }, + "position": { + "x": 1055.9166666666665, + "y": 458.6388888888888 + } + }, + { + "id": "{93fdbb4c-bc81-4100-89a9-b465793099b9}", + "model": { + "name": "float_mul", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, "variable_name": "" }, "position": { - "x": 488, - "y": 376 + "x": 1051.286666666667, + "y": 195.20666666666665 } }, { @@ -209,8 +368,8 @@ "variable_name": "" }, "position": { - "x": 912, - "y": 489 + "x": 2598.5, + "y": 293.33333333333326 } }, { @@ -223,28 +382,8 @@ "variable_name": "" }, "position": { - "x": 707, - "y": 492 - } - }, - { - "id": "{43df5c43-d6f4-440f-a049-4fde6e738883}", - "model": { - "name": "cast_vec4", - "preview_enabled": false, - "preview_height": 64, - "preview_width": 64, - "value": [ - 1, - 0, - 0, - 0 - ], - "variable_name": "matDiffuse" - }, - "position": { - "x": 521, - "y": 616 + "x": 377.1388888888888, + "y": 507.83333333333337 } }, { @@ -259,8 +398,198 @@ "variable_name": "" }, "position": { - "x": 309, - "y": 637 + "x": 135.11111111111126, + "y": 643.5277777777775 + } + }, + { + "id": "{e1f86d56-eb21-4267-9075-e6b0cc875a6d}", + "model": { + "condition_name": "HAS_DIFFUSE_TEXTURE", + "name": "ConditionalExpression", + "preview_enabled": true, + "preview_height": 128, + "preview_width": 128, + "variable_name": "" + }, + "position": { + "x": 602.5, + "y": 566.5 + } + }, + { + "id": "{ca2c2ac5-39e0-4814-9432-fbf3e20d3cad}", + "model": { + "input": "vertUV", + "name": "Input", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "variable_name": "" + }, + "position": { + "x": 344.36666666666684, + "y": 53.300000000000026 + } + }, + { + "id": "{f9ba0cce-3b85-4f95-a79e-a2f64d955d89}", + "model": { + "name": "Texture", + "preview_enabled": true, + "preview_height": 64, + "preview_width": 64, + "texture": "MaterialAlphaMap", + "variable_name": "" + }, + "position": { + "x": 344.59999999999985, + "y": -35.10000000000005 + } + }, + { + "id": "{7750a050-b116-4e1b-bd89-b194c366d256}", + "model": { + "name": "SampleTexture", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "variable_name": "" + }, + "position": { + "x": 491.0333333333334, + "y": 18.366666666666674 + } + }, + { + "id": "{6fcfbcd0-c2df-41dd-bb50-74b455b9021f}", + "model": { + "name": "vec_decompose", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "variable_name": "" + }, + "position": { + "x": 682.0999999999998, + "y": 19.88000000000003 + } + }, + { + "id": "{359a78e1-df0d-467f-907e-7bff04a55db5}", + "model": { + "name": "vec_compose4", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "variable_name": "" + }, + "position": { + "x": 1240.62, + "y": -41.900000000000034 + } + }, + { + "id": "{bb071807-e65e-4c31-acf0-d296efa665fa}", + "model": { + "name": "vec_decompose", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "variable_name": "" + }, + "position": { + "x": 2270, + "y": 67 + } + }, + { + "id": "{92d95fe0-84f6-4d27-91ea-992d5f73c04e}", + "model": { + "condition_name": "HAS_ALPHA_TEXTURE", + "name": "ConditionalExpression", + "preview_enabled": true, + "preview_height": 128, + "preview_width": 128, + "variable_name": "" + }, + "position": { + "x": 1415.8933333333334, + "y": 135.44000000000005 + } + }, + { + "id": "{3cdb5bb1-f572-4055-a1af-460b152b0c13}", + "model": { + "name": "Discard", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "variable_name": "" + }, + "position": { + "x": 2694, + "y": 4 + } + }, + { + "id": "{d7acd173-9188-43b5-bfa1-31f17dff44ad}", + "model": { + "condition_name": "ALPHA_TEST", + "name": "ConditionalExpression", + "preview_enabled": true, + "preview_height": 128, + "preview_width": 128, + "variable_name": "" + }, + "position": { + "x": 2240, + "y": -174 + } + }, + { + "id": "{1f9d52d7-4f44-4d96-8edb-fbc1239a93bb}", + "model": { + "name": "bool_constant", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "value": false, + "variable_name": "" + }, + "position": { + "x": 2005, + "y": -99 + } + }, + { + "id": "{fc7542b2-5752-4891-98c1-35b498da257b}", + "model": { + "name": "float_lt", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "variable_name": "" + }, + "position": { + "x": 2000, + "y": -241 + } + }, + { + "id": "{743930bd-1d81-4d4c-b7ec-175a34838d69}", + "model": { + "buffer": "settings", + "field": "AlphaThreshold", + "name": "BufferField", + "preview_enabled": false, + "preview_height": 64, + "preview_width": 64, + "variable_name": "" + }, + "position": { + "x": 1675, + "y": -254 } } ], @@ -280,7 +609,7 @@ }, { "name": "DiffuseColor", - "type": "Float3" + "type": "Float4" } ], "name": "BasicSettings" diff --git a/src/Nazara/Core/Error.cpp b/src/Nazara/Core/Error.cpp index 348950bec..7f7b12232 100644 --- a/src/Nazara/Core/Error.cpp +++ b/src/Nazara/Core/Error.cpp @@ -88,7 +88,7 @@ namespace Nz #if defined(NAZARA_PLATFORM_WINDOWS) wchar_t* buffer = nullptr; - FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, + DWORD length = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, code, 0, @@ -96,6 +96,9 @@ namespace Nz 0, nullptr); + if (length == 0) + return ""; + CallOnExit freeOnExit([buffer] { LocalFree(buffer); }); return FromWideString(buffer); #elif defined(NAZARA_PLATFORM_POSIX) diff --git a/src/Nazara/Graphics/BasicMaterial.cpp b/src/Nazara/Graphics/BasicMaterial.cpp index 59798a086..f92e61f7f 100644 --- a/src/Nazara/Graphics/BasicMaterial.cpp +++ b/src/Nazara/Graphics/BasicMaterial.cpp @@ -6,7 +6,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -33,12 +35,17 @@ namespace Nz const std::shared_ptr& materialSettings = material.GetSettings(); if (materialSettings == s_materialSettings) { + m_conditionIndexes = s_conditionIndexes; m_textureIndexes = s_textureIndexes; m_uniformBlockIndex = s_uniformBlockIndex; m_uniformOffsets = s_uniformOffsets; } else { + m_conditionIndexes.alphaTest = materialSettings->GetConditionIndex("AlphaTest"); + m_conditionIndexes.hasAlphaMap = materialSettings->GetConditionIndex("HasAlphaMap"); + m_conditionIndexes.hasDiffuseMap = materialSettings->GetConditionIndex("HasDiffuseMap"); + m_textureIndexes.alpha = materialSettings->GetTextureIndex("Alpha"); m_textureIndexes.diffuse = materialSettings->GetTextureIndex("Diffuse"); @@ -49,9 +56,9 @@ namespace Nz } } - float BasicMaterial::GetAlphaThreshold() const + float BasicMaterial::GetAlphaTestThreshold() const { - NazaraAssert(HasAlphaThreshold(), "Material has no alpha threshold uniform"); + NazaraAssert(HasAlphaTestThreshold(), "Material has no alpha threshold uniform"); BufferMapper mapper(m_material.GetUniformBuffer(m_uniformBlockIndex), BufferAccess_ReadOnly); return AccessByOffset(mapper.GetPointer(), m_uniformOffsets.alphaThreshold); @@ -67,9 +74,9 @@ namespace Nz return Color(colorPtr[0] * 255, colorPtr[1] * 255, colorPtr[2] * 255, colorPtr[3] * 255); //< TODO: Make color able to use float } - void BasicMaterial::SetAlphaThreshold(float alphaThreshold) + void BasicMaterial::SetAlphaTestThreshold(float alphaThreshold) { - NazaraAssert(HasAlphaThreshold(), "Material has no alpha threshold uniform"); + NazaraAssert(HasAlphaTestThreshold(), "Material has no alpha threshold uniform"); BufferMapper mapper(m_material.GetUniformBuffer(m_uniformBlockIndex), BufferAccess_WriteOnly); AccessByOffset(mapper.GetPointer(), m_uniformOffsets.alphaThreshold) = alphaThreshold; @@ -87,20 +94,16 @@ namespace Nz colorPtr[3] = diffuse.a / 255.f; } - const std::shared_ptr& BasicMaterial::GetSettings() - { - return s_materialSettings; - } - bool BasicMaterial::Initialize() { FieldOffsets fieldOffsets(StructLayout_Std140); - s_uniformOffsets.diffuseColor = fieldOffsets.AddField(StructFieldType_Float4); s_uniformOffsets.alphaThreshold = fieldOffsets.AddField(StructFieldType_Float1); + s_uniformOffsets.diffuseColor = fieldOffsets.AddField(StructFieldType_Float4); + s_uniformOffsets.totalSize = fieldOffsets.GetSize(); - MaterialSettings::PredefinedBinding predefinedBinding; - predefinedBinding.fill(MaterialSettings::InvalidIndex); + MaterialSettings::Builder settings; + settings.predefinedBinding.fill(MaterialSettings::InvalidIndex); std::vector variables; variables.assign({ @@ -120,31 +123,29 @@ namespace Nz AccessByOffset(defaultValues.data(), s_uniformOffsets.diffuseColor) = Vector4f(1.f, 1.f, 1.f, 1.f); AccessByOffset(defaultValues.data(), s_uniformOffsets.alphaThreshold) = 0.2f; - std::vector textures; - s_textureIndexes.alpha = textures.size(); - textures.push_back({ + s_textureIndexes.alpha = settings.textures.size(); + settings.textures.push_back({ "MaterialAlphaMap", "Alpha", ImageType_2D }); - - s_textureIndexes.diffuse = textures.size(); - textures.push_back({ + + s_textureIndexes.diffuse = settings.textures.size(); + settings.textures.push_back({ "MaterialDiffuseMap", "Diffuse", ImageType_2D }); - predefinedBinding[UnderlyingCast(PredefinedShaderBinding::TexOverlay)] = textures.size(); - textures.push_back({ + settings.predefinedBinding[UnderlyingCast(PredefinedShaderBinding::TexOverlay)] = settings.textures.size(); + settings.textures.push_back({ "TextureOverlay", "Overlay", ImageType_2D }); - std::vector uniformBlocks; - s_uniformBlockIndex = uniformBlocks.size(); - uniformBlocks.assign({ + s_uniformBlockIndex = settings.uniformBlocks.size(); + settings.uniformBlocks.assign({ { fieldOffsets.GetSize(), "BasicSettings", @@ -154,19 +155,61 @@ namespace Nz } }); - std::vector sharedUniformBlock; + settings.predefinedBinding[UnderlyingCast(PredefinedShaderBinding::UboInstanceData)] = settings.textures.size() + settings.uniformBlocks.size() + settings.sharedUniformBlocks.size(); + settings.sharedUniformBlocks.push_back(PredefinedInstanceData::GetUniformBlock()); - predefinedBinding[UnderlyingCast(PredefinedShaderBinding::UboInstanceData)] = textures.size() + uniformBlocks.size() + sharedUniformBlock.size(); - sharedUniformBlock.push_back(PredefinedInstanceData::GetUniformBlock()); - predefinedBinding[UnderlyingCast(PredefinedShaderBinding::UboViewerData)] = textures.size() + uniformBlocks.size() + sharedUniformBlock.size(); - sharedUniformBlock.push_back(PredefinedViewerData::GetUniformBlock()); + settings.predefinedBinding[UnderlyingCast(PredefinedShaderBinding::UboViewerData)] = settings.textures.size() + settings.uniformBlocks.size() + settings.sharedUniformBlocks.size(); + settings.sharedUniformBlocks.push_back(PredefinedViewerData::GetUniformBlock()); // Shaders - MaterialSettings::DefaultShaders defaultShaders; - defaultShaders[UnderlyingCast(ShaderStageType::Fragment)] = Graphics::Instance()->GetRenderDevice().InstantiateShaderStage(Nz::ShaderStageType::Fragment, Nz::ShaderLanguage::NazaraBinary, r_fragmentShader, sizeof(r_fragmentShader)); - defaultShaders[UnderlyingCast(ShaderStageType::Vertex)] = Graphics::Instance()->GetRenderDevice().InstantiateShaderStage(Nz::ShaderStageType::Vertex, Nz::ShaderLanguage::NazaraBinary, r_vertexShader, sizeof(r_vertexShader)); + auto& fragmentShader = settings.shaders[UnderlyingCast(ShaderStageType::Fragment)]; + auto& vertexShader = settings.shaders[UnderlyingCast(ShaderStageType::Vertex)]; - s_materialSettings = std::make_shared(std::move(textures), std::move(uniformBlocks), std::move(sharedUniformBlock), predefinedBinding, std::move(defaultShaders)); + fragmentShader = std::make_shared(UnserializeShader(r_fragmentShader, sizeof(r_fragmentShader))); + vertexShader = std::make_shared(UnserializeShader(r_vertexShader, sizeof(r_vertexShader))); + + // Conditions + + // HasDiffuseMap + { + std::array shaderConditions; + shaderConditions.fill(0); + shaderConditions[UnderlyingCast(ShaderStageType::Fragment)] = fragmentShader->GetConditionFlagByName("HAS_DIFFUSE_TEXTURE"); + + s_conditionIndexes.hasDiffuseMap = settings.conditions.size(); + settings.conditions.push_back({ + "HasDiffuseMap", + shaderConditions + }); + } + + // HasAlphaMap + { + std::array shaderConditions; + shaderConditions.fill(0); + shaderConditions[UnderlyingCast(ShaderStageType::Fragment)] = fragmentShader->GetConditionFlagByName("HAS_ALPHA_TEXTURE"); + + s_conditionIndexes.hasAlphaMap = settings.conditions.size(); + settings.conditions.push_back({ + "HasAlphaMap", + shaderConditions + }); + } + + // AlphaTest + { + std::array shaderConditions; + shaderConditions.fill(0); + shaderConditions[UnderlyingCast(ShaderStageType::Fragment)] = fragmentShader->GetConditionFlagByName("ALPHA_TEST"); + + s_conditionIndexes.alphaTest = settings.conditions.size(); + settings.conditions.push_back({ + "AlphaTest", + shaderConditions + }); + } + + s_materialSettings = std::make_shared(std::move(settings)); return true; } @@ -178,6 +221,7 @@ namespace Nz std::shared_ptr BasicMaterial::s_materialSettings; std::size_t BasicMaterial::s_uniformBlockIndex; + BasicMaterial::ConditionIndexes BasicMaterial::s_conditionIndexes; BasicMaterial::TextureIndexes BasicMaterial::s_textureIndexes; BasicMaterial::UniformOffsets BasicMaterial::s_uniformOffsets; } diff --git a/src/Nazara/Graphics/Material.cpp b/src/Nazara/Graphics/Material.cpp index 952402cb5..7a51c9ba2 100644 --- a/src/Nazara/Graphics/Material.cpp +++ b/src/Nazara/Graphics/Material.cpp @@ -24,11 +24,15 @@ namespace Nz */ Material::Material(std::shared_ptr settings) : m_settings(std::move(settings)), + m_enabledConditions(0), m_pipelineUpdated(false), m_shadowCastingEnabled(true) { m_pipelineInfo.settings = m_settings; - m_pipelineInfo.shaders = m_settings->GetDefaultShaders(); + + const auto& shaders = m_settings->GetShaders(); + for (std::size_t i = 0; i < ShaderStageTypeCount; ++i) + m_pipelineInfo.shaders[i].uberShader = shaders[i]; m_textures.resize(m_settings->GetTextures().size()); diff --git a/src/Nazara/Graphics/MaterialPipeline.cpp b/src/Nazara/Graphics/MaterialPipeline.cpp index 5996f64b0..938563bee 100644 --- a/src/Nazara/Graphics/MaterialPipeline.cpp +++ b/src/Nazara/Graphics/MaterialPipeline.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include namespace Nz @@ -47,10 +48,10 @@ namespace Nz renderPipelineInfo.pipelineLayout = m_pipelineInfo.settings->GetRenderPipelineLayout(); - for (const auto& shaderStage : m_pipelineInfo.shaders) + for (const auto& shaderEntry : m_pipelineInfo.shaders) { - if (shaderStage) - renderPipelineInfo.shaderStages.push_back(shaderStage); + if (shaderEntry.uberShader) + renderPipelineInfo.shaderStages.push_back(shaderEntry.uberShader->Get(shaderEntry.enabledConditions)); } renderPipelineInfo.vertexBuffers = vertexBuffers; diff --git a/src/Nazara/Graphics/PhongLightingMaterial.cpp b/src/Nazara/Graphics/PhongLightingMaterial.cpp index 903c34d97..d8258c55a 100644 --- a/src/Nazara/Graphics/PhongLightingMaterial.cpp +++ b/src/Nazara/Graphics/PhongLightingMaterial.cpp @@ -151,8 +151,8 @@ namespace Nz s_phongUniformOffsets.diffuseColor = phongUniformStruct.AddField(StructFieldType_Float4); s_phongUniformOffsets.specularColor = phongUniformStruct.AddField(StructFieldType_Float4); - MaterialSettings::PredefinedBinding predefinedBinding; - predefinedBinding.fill(MaterialSettings::InvalidIndex); + MaterialSettings::Builder settings; + settings.predefinedBinding.fill(MaterialSettings::InvalidIndex); std::vector phongVariables; phongVariables.assign({ @@ -187,10 +187,8 @@ namespace Nz AccessByOffset(defaultValues.data(), s_phongUniformOffsets.alphaThreshold) = 0.2f; AccessByOffset(defaultValues.data(), s_phongUniformOffsets.shininess) = 50.f; - std::vector uniformBlocks; - - s_phongUniformBlockIndex = uniformBlocks.size(); - uniformBlocks.push_back({ + s_phongUniformBlockIndex = settings.uniformBlocks.size(); + settings.uniformBlocks.push_back({ phongUniformStruct.GetSize(), "PhongSettings", "MaterialPhongSettings", @@ -198,65 +196,63 @@ namespace Nz std::move(defaultValues) }); - std::vector sharedUniformBlock; - predefinedBinding[UnderlyingCast(PredefinedShaderBinding::UboInstanceData)] = sharedUniformBlock.size(); - sharedUniformBlock.push_back(PredefinedInstanceData::GetUniformBlock()); - predefinedBinding[UnderlyingCast(PredefinedShaderBinding::UboLighData)] = sharedUniformBlock.size(); - sharedUniformBlock.push_back(PredefinedLightData::GetUniformBlock()); - predefinedBinding[UnderlyingCast(PredefinedShaderBinding::UboViewerData)] = sharedUniformBlock.size(); - sharedUniformBlock.push_back(PredefinedViewerData::GetUniformBlock()); + settings.predefinedBinding[UnderlyingCast(PredefinedShaderBinding::UboInstanceData)] = settings.sharedUniformBlocks.size(); + settings.sharedUniformBlocks.push_back(PredefinedInstanceData::GetUniformBlock()); + settings.predefinedBinding[UnderlyingCast(PredefinedShaderBinding::UboLighData)] = settings.sharedUniformBlocks.size(); + settings.sharedUniformBlocks.push_back(PredefinedLightData::GetUniformBlock()); + settings.predefinedBinding[UnderlyingCast(PredefinedShaderBinding::UboViewerData)] = settings.sharedUniformBlocks.size(); + settings.sharedUniformBlocks.push_back(PredefinedViewerData::GetUniformBlock()); - std::vector textures; - s_textureIndexes.alpha = textures.size(); - textures.push_back({ + s_textureIndexes.alpha = settings.textures.size(); + settings.textures.push_back({ "MaterialAlphaMap", "Alpha", ImageType_2D }); - s_textureIndexes.diffuse = textures.size(); - textures.push_back({ + s_textureIndexes.diffuse = settings.textures.size(); + settings.textures.push_back({ "MaterialDiffuseMap", "Diffuse", ImageType_2D }); - s_textureIndexes.emissive = textures.size(); - textures.push_back({ + s_textureIndexes.emissive = settings.textures.size(); + settings.textures.push_back({ "MaterialEmissiveMap", "Emissive", ImageType_2D }); - s_textureIndexes.height = textures.size(); - textures.push_back({ + s_textureIndexes.height = settings.textures.size(); + settings.textures.push_back({ "MaterialHeightMap", "Height", ImageType_2D }); - s_textureIndexes.normal = textures.size(); - textures.push_back({ + s_textureIndexes.normal = settings.textures.size(); + settings.textures.push_back({ "MaterialNormalMap", "Normal", ImageType_2D }); - s_textureIndexes.specular = textures.size(); - textures.push_back({ + s_textureIndexes.specular = settings.textures.size(); + settings.textures.push_back({ "MaterialSpecularMap", "Specular", ImageType_2D }); - predefinedBinding[UnderlyingCast(PredefinedShaderBinding::TexOverlay)] = textures.size(); - textures.push_back({ + settings.predefinedBinding[UnderlyingCast(PredefinedShaderBinding::TexOverlay)] = settings.textures.size(); + settings.textures.push_back({ "TextureOverlay", "Overlay", ImageType_2D, }); - s_materialSettings = std::make_shared(std::move(textures), std::move(uniformBlocks), std::move(sharedUniformBlock), predefinedBinding, MaterialSettings::DefaultShaders{}); + s_materialSettings = std::make_shared(std::move(settings)); return true; } diff --git a/src/Nazara/Graphics/Resources/Shaders/basicmaterial.frag.shader b/src/Nazara/Graphics/Resources/Shaders/basicmaterial.frag.shader index de1e590c453324d531d93dd1a59942a62bb8cccd..70cdc4d2b1d52a3468c1d90ddbec8d2df18d90ec 100644 GIT binary patch literal 1745 zcmbVMU2obj6wL~)Xb2e{e`F7Puh;-lX>Ab+-QFq-T=0}8$Z_e%pX;CMYt`OkY-X>a zL%q@=`1ss=eXnnFmJG*15PTxQYJ|?Pn_Tuz27^h`zfAkT)5*9`^bzRp&(W~!kf9}# z)OfePvr%}$w;;*OTVAt4s|>epL3yb%1BOXCb-dnt=Qe5yo|`w==6VYFp0Tu~Tb z-Xb}I`)mv$qWJWY5x?DOOPm52w9f>0!mGv2b-^x3eVX6#v4u2)z`0?K-F@FF7u0Q-QO z?MHpZx zBo?KomKXp97+8Q9q#b4ph~@?vHF*y+KPxwo$2s{kvl1icv4FEYDO_P`e V%!ORJi9q+IrIi+^0*z&00RW*5Cj6mo$S`sEkpCgy+?gUkb&0kV!WGY=wB4CG+iG+B~ahmm`74YMvMNFD@0 YJX2PXe%8s-Op24QGfMzfd|*}s03Zn&1poj5 delta 181 zcmbQmF^z-AFW4i9fq{V$geMBPFfwlpHDMCv1#+2zm;)*Wq!>6S&tnqP;Dm~BW#)yX zRygP97o~tCnSdBo@f{{9b(mt#%sjvRqTIxsVvt%)gJqd@7&#|5FzbRefB}eS$_nDL SPL^j +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + UberShader::UberShader(ShaderAst shaderAst) : + m_shaderAst(std::move(shaderAst)) + { + std::size_t conditionCount = m_shaderAst.GetConditionCount(); + + if (conditionCount >= 64) + throw std::runtime_error("Too many conditions"); + + m_combinationMask = std::numeric_limits::max(); + m_combinationMask <<= conditionCount; + m_combinationMask = ~m_combinationMask; + } + + UInt64 UberShader::GetConditionFlagByName(const std::string_view& condition) const + { + std::size_t conditionIndex = m_shaderAst.FindConditionByName(condition); + if (conditionIndex != ShaderAst::InvalidCondition) + return SetBit(0, conditionIndex); + else + return 0; + } + + const std::shared_ptr& UberShader::Get(UInt64 combination) + { + combination &= m_combinationMask; + + auto it = m_combinations.find(combination); + if (it == m_combinations.end()) + { + ShaderWriter::States states; + states.enabledConditions = combination; + + std::shared_ptr stage = Graphics::Instance()->GetRenderDevice().InstantiateShaderStage(m_shaderAst, std::move(states)); + + it = m_combinations.emplace(combination, std::move(stage)).first; + } + + return it->second; + } +} diff --git a/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp b/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp index f23eba582..b5ccbd0ed 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp @@ -93,6 +93,7 @@ namespace Nz command.framebuffer->Activate(); context = GL::Context::GetCurrentContext(); + context->glClearColor(0.5, 0.5, 0.5, 1.0); context->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } else diff --git a/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp b/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp index 3085a7955..5d2ffa399 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp @@ -68,6 +68,11 @@ namespace Nz return std::make_shared(std::move(pipelineLayoutInfo)); } + std::shared_ptr OpenGLDevice::InstantiateShaderStage(const ShaderAst& shaderAst, const ShaderWriter::States& states) + { + return std::make_shared(*this, shaderAst, states); + } + std::shared_ptr OpenGLDevice::InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) { return std::make_shared(*this, type, lang, source, sourceSize); diff --git a/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp b/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp index a236d81c7..adca247e9 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp @@ -20,6 +20,8 @@ namespace Nz const auto& textureDescriptor = m_owner.GetTextureDescriptor(m_poolIndex, m_bindingIndex, i); UInt32 textureIndex = textureDescriptor.bindingIndex; + if (textureIndex == OpenGLRenderPipelineLayout::InvalidIndex) + continue; context.BindSampler(textureIndex, textureDescriptor.sampler); context.BindTexture(textureIndex, textureDescriptor.textureTarget, textureDescriptor.texture); @@ -29,6 +31,10 @@ namespace Nz { const auto& uboDescriptor = m_owner.GetUniformBufferDescriptor(m_poolIndex, m_bindingIndex, i); + UInt32 uboIndex = uboDescriptor.bindingIndex; + if (uboIndex == OpenGLRenderPipelineLayout::InvalidIndex) + continue; + context.BindUniformBuffer(uboDescriptor.bindingIndex, uboDescriptor.buffer, uboDescriptor.offset, uboDescriptor.size); } } diff --git a/src/Nazara/OpenGLRenderer/OpenGLShaderStage.cpp b/src/Nazara/OpenGLRenderer/OpenGLShaderStage.cpp index 068ef9634..dd7a69e5b 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLShaderStage.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLShaderStage.cpp @@ -14,6 +14,15 @@ namespace Nz { + OpenGLShaderStage::OpenGLShaderStage(OpenGLDevice& device, const ShaderAst& shaderAst, const ShaderWriter::States& states) + { + if (!m_shader.Create(device, ToOpenGL(shaderAst.GetStage()))) + throw std::runtime_error("failed to create shader"); //< TODO: Handle error message + + Create(device, shaderAst, states); + CheckCompilationStatus(); + } + OpenGLShaderStage::OpenGLShaderStage(OpenGLDevice& device, ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) { if (!m_shader.Create(device, ToOpenGL(type))) @@ -28,32 +37,11 @@ namespace Nz case ShaderLanguage::NazaraBinary: { - ByteStream byteStream(source, sourceSize); - auto shader = Nz::UnserializeShader(byteStream); - + auto shader = UnserializeShader(source, sourceSize); if (shader.GetStage() != type) throw std::runtime_error("incompatible shader stage"); - const auto& context = device.GetReferenceContext(); - const auto& contextParams = context.GetParams(); - - GlslWriter::Environment env; - env.glES = (contextParams.type == GL::ContextType::OpenGL_ES); - env.glMajorVersion = contextParams.glMajorVersion; - env.glMinorVersion = contextParams.glMinorVersion; - env.extCallback = [&](const std::string_view& ext) - { - return context.IsExtensionSupported(std::string(ext)); - }; - env.flipYPosition = true; - - GlslWriter writer; - writer.SetEnv(env); - - std::string code = writer.Generate(shader); - - m_shader.SetSource(code.data(), code.size()); - m_shader.Compile(); + Create(device, shader, {}); break; } @@ -71,8 +59,39 @@ namespace Nz throw std::runtime_error("Unsupported shader language"); } + CheckCompilationStatus(); + } + + void OpenGLShaderStage::CheckCompilationStatus() + { std::string errorLog; if (!m_shader.GetCompilationStatus(&errorLog)) throw std::runtime_error("Failed to compile shader: " + errorLog); } + + void OpenGLShaderStage::Create(OpenGLDevice& device, const ShaderAst& shaderAst, const ShaderWriter::States& states) + { + const auto& context = device.GetReferenceContext(); + const auto& contextParams = context.GetParams(); + + GlslWriter::Environment env; + env.glES = (contextParams.type == GL::ContextType::OpenGL_ES); + env.glMajorVersion = contextParams.glMajorVersion; + env.glMinorVersion = contextParams.glMinorVersion; + env.extCallback = [&](const std::string_view& ext) + { + return context.IsExtensionSupported(std::string(ext)); + }; + env.flipYPosition = true; + + GlslWriter writer; + writer.SetEnv(env); + + std::string code = writer.Generate(shaderAst, states); + + NazaraError(code); + + m_shader.SetSource(code.data(), code.size()); + m_shader.Compile(); + } } diff --git a/src/Nazara/OpenGLRenderer/Wrapper/WGL/WGLContext.cpp b/src/Nazara/OpenGLRenderer/Wrapper/WGL/WGLContext.cpp index ffa9339e3..052c0f63a 100644 --- a/src/Nazara/OpenGLRenderer/Wrapper/WGL/WGLContext.cpp +++ b/src/Nazara/OpenGLRenderer/Wrapper/WGL/WGLContext.cpp @@ -174,7 +174,7 @@ namespace Nz::GL WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB }; - m_handle = baseContext->wglCreateContextAttribsARB(m_deviceContext, nullptr, attributes.data()); + m_handle = baseContext->wglCreateContextAttribsARB(m_deviceContext, (shareContext) ? shareContext->m_handle : nullptr, attributes.data()); if (m_handle) { m_params.type = ContextType::OpenGL; @@ -198,16 +198,16 @@ namespace Nz::GL return false; } - m_params.type = ContextType::OpenGL; - } - - if (shareContext) - { - if (!m_loader.wglShareLists(shareContext->m_handle, m_handle)) + if (shareContext) { - NazaraError("failed to share context objects: " + Error::GetLastSystemError()); - return false; + if (!m_loader.wglShareLists(shareContext->m_handle, m_handle)) + { + NazaraError("failed to share context objects: " + Error::GetLastSystemError()); + return false; + } } + + m_params.type = ContextType::OpenGL; } LoadWGLExt(); diff --git a/src/Nazara/Physics2D/Arbiter2D.cpp b/src/Nazara/Physics2D/Arbiter2D.cpp index 9da160216..2cb35ff4f 100644 --- a/src/Nazara/Physics2D/Arbiter2D.cpp +++ b/src/Nazara/Physics2D/Arbiter2D.cpp @@ -39,7 +39,7 @@ namespace Nz float Arbiter2D::GetContactDepth(std::size_t i) const { - return cpArbiterGetDepth(m_arbiter, int(i)); + return float(cpArbiterGetDepth(m_arbiter, int(i))); } Nz::Vector2f Arbiter2D::GetContactPointA(std::size_t i) const diff --git a/src/Nazara/Shader/GlslWriter.cpp b/src/Nazara/Shader/GlslWriter.cpp index 649f25072..0dfe2476c 100644 --- a/src/Nazara/Shader/GlslWriter.cpp +++ b/src/Nazara/Shader/GlslWriter.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -418,21 +419,17 @@ namespace Nz switch (node.op) { - case ShaderNodes::BinaryType::Add: - Append(" + "); - break; - case ShaderNodes::BinaryType::Substract: - Append(" - "); - break; - case ShaderNodes::BinaryType::Multiply: - Append(" * "); - break; - case ShaderNodes::BinaryType::Divide: - Append(" / "); - break; - case ShaderNodes::BinaryType::Equality: - Append(" == "); - break; + case ShaderNodes::BinaryType::Add: Append(" + "); break; + case ShaderNodes::BinaryType::Substract: Append(" - "); break; + case ShaderNodes::BinaryType::Multiply: Append(" * "); break; + case ShaderNodes::BinaryType::Divide: Append(" / "); break; + + case ShaderNodes::BinaryType::CompEq: Append(" == "); break; + case ShaderNodes::BinaryType::CompGe: Append(" >= "); break; + case ShaderNodes::BinaryType::CompGt: Append(" > "); break; + case ShaderNodes::BinaryType::CompLe: Append(" <= "); break; + case ShaderNodes::BinaryType::CompLt: Append(" < "); break; + case ShaderNodes::BinaryType::CompNe: Append(" != "); break; } Visit(node.right, true); @@ -448,15 +445,17 @@ namespace Nz Append(node.exprType); Append("("); - for (std::size_t i = 0; node.expressions[i]; ++i) + bool first = true; + for (const auto& exprPtr : node.expressions) { - if (i != 0) + if (!exprPtr) + break; + + if (!first) m_currentState->stream << ", "; - const auto& exprPtr = node.expressions[i]; - NazaraAssert(exprPtr, "Invalid expression"); - Visit(exprPtr); + first = false; } Append(")"); @@ -465,7 +464,10 @@ namespace Nz void GlslWriter::Visit(ShaderNodes::ConditionalExpression& node) { - if (m_context.states->enabledConditions.count(node.conditionName) != 0) + std::size_t conditionIndex = m_context.shader->FindConditionByName(node.conditionName); + assert(conditionIndex != ShaderAst::InvalidCondition); + + if (TestBit(m_context.states->enabledConditions, conditionIndex)) Visit(node.truePath); else Visit(node.falsePath); @@ -473,7 +475,10 @@ namespace Nz void GlslWriter::Visit(ShaderNodes::ConditionalStatement& node) { - if (m_context.states->enabledConditions.count(node.conditionName) != 0) + std::size_t conditionIndex = m_context.shader->FindConditionByName(node.conditionName); + assert(conditionIndex != ShaderAst::InvalidCondition); + + if (TestBit(m_context.states->enabledConditions, conditionIndex)) Visit(node.statement); } @@ -604,7 +609,7 @@ namespace Nz void GlslWriter::Visit(ShaderNodes::SwizzleOp& node) { - Visit(node.expression); + Visit(node.expression, true); Append("."); for (std::size_t i = 0; i < node.componentCount; ++i) diff --git a/src/Nazara/Shader/ShaderAstSerializer.cpp b/src/Nazara/Shader/ShaderAstSerializer.cpp index a5e870713..7f12ad3b5 100644 --- a/src/Nazara/Shader/ShaderAstSerializer.cpp +++ b/src/Nazara/Shader/ShaderAstSerializer.cpp @@ -659,6 +659,9 @@ namespace Nz Int32 nodeTypeInt; m_stream >> nodeTypeInt; + if (nodeTypeInt < static_cast(ShaderNodes::NodeType::None) || nodeTypeInt > static_cast(ShaderNodes::NodeType::Max)) + throw std::runtime_error("invalid node type"); + ShaderNodes::NodeType nodeType = static_cast(nodeTypeInt); #define HandleType(Type) case ShaderNodes::NodeType:: Type : node = std::make_shared(); break diff --git a/src/Nazara/Shader/ShaderAstValidator.cpp b/src/Nazara/Shader/ShaderAstValidator.cpp index 643ff2d85..e139fa25e 100644 --- a/src/Nazara/Shader/ShaderAstValidator.cpp +++ b/src/Nazara/Shader/ShaderAstValidator.cpp @@ -150,8 +150,17 @@ namespace Nz switch (node.op) { + case ShaderNodes::BinaryType::CompGe: + case ShaderNodes::BinaryType::CompGt: + case ShaderNodes::BinaryType::CompLe: + case ShaderNodes::BinaryType::CompLt: + if (leftType == ShaderNodes::BasicType::Boolean) + throw AstError{ "this operation is not supported for booleans" }; + + [[fallthrough]]; case ShaderNodes::BinaryType::Add: - case ShaderNodes::BinaryType::Equality: + case ShaderNodes::BinaryType::CompEq: + case ShaderNodes::BinaryType::CompNe: case ShaderNodes::BinaryType::Substract: TypeMustMatch(node.left, node.right); break; @@ -236,7 +245,7 @@ namespace Nz } if (componentCount != requiredComponents) - throw AstError{ "Component count doesn't match required component count" }; + throw AstError{ "component count doesn't match required component count" }; ShaderAstRecursiveVisitor::Visit(node); } @@ -246,28 +255,16 @@ namespace Nz MandatoryNode(node.truePath); MandatoryNode(node.falsePath); - for (std::size_t i = 0; i < m_shader.GetConditionCount(); ++i) - { - const auto& condition = m_shader.GetCondition(i); - if (condition.name == node.conditionName) - return; - } - - throw AstError{ "Condition not found" }; + if (m_shader.FindConditionByName(node.conditionName) == ShaderAst::InvalidCondition) + throw AstError{ "condition not found" }; } void ShaderAstValidator::Visit(ShaderNodes::ConditionalStatement& node) { MandatoryNode(node.statement); - for (std::size_t i = 0; i < m_shader.GetConditionCount(); ++i) - { - const auto& condition = m_shader.GetCondition(i); - if (condition.name == node.conditionName) - return; - } - - throw AstError{ "Condition not found" }; + if (m_shader.FindConditionByName(node.conditionName) == ShaderAst::InvalidCondition) + throw AstError{ "condition not found" }; } void ShaderAstValidator::Visit(ShaderNodes::Constant& /*node*/) diff --git a/src/Nazara/Shader/ShaderNodes.cpp b/src/Nazara/Shader/ShaderNodes.cpp index c6aa7874a..2aa00ec69 100644 --- a/src/Nazara/Shader/ShaderNodes.cpp +++ b/src/Nazara/Shader/ShaderNodes.cpp @@ -140,7 +140,12 @@ namespace Nz::ShaderNodes break; } - case BinaryType::Equality: + case BinaryType::CompEq: + case BinaryType::CompGe: + case BinaryType::CompGt: + case BinaryType::CompLe: + case BinaryType::CompLt: + case BinaryType::CompNe: exprType = BasicType::Boolean; break; } diff --git a/src/Nazara/Shader/SpirvAstVisitor.cpp b/src/Nazara/Shader/SpirvAstVisitor.cpp index 871f41b41..e012d6de3 100644 --- a/src/Nazara/Shader/SpirvAstVisitor.cpp +++ b/src/Nazara/Shader/SpirvAstVisitor.cpp @@ -154,7 +154,7 @@ namespace Nz break; } - case ShaderNodes::BinaryType::Equality: + case ShaderNodes::BinaryType::CompEq: { switch (leftType) { @@ -185,6 +185,166 @@ namespace Nz break; } + + case ShaderNodes::BinaryType::CompGe: + { + switch (leftType) + { + case ShaderNodes::BasicType::Float1: + case ShaderNodes::BasicType::Float2: + case ShaderNodes::BasicType::Float3: + case ShaderNodes::BasicType::Float4: + case ShaderNodes::BasicType::Mat4x4: + return SpirvOp::OpFOrdGreaterThan; + + case ShaderNodes::BasicType::Int1: + case ShaderNodes::BasicType::Int2: + case ShaderNodes::BasicType::Int3: + case ShaderNodes::BasicType::Int4: + return SpirvOp::OpSGreaterThan; + + case ShaderNodes::BasicType::UInt1: + case ShaderNodes::BasicType::UInt2: + case ShaderNodes::BasicType::UInt3: + case ShaderNodes::BasicType::UInt4: + return SpirvOp::OpUGreaterThan; + + case ShaderNodes::BasicType::Boolean: + case ShaderNodes::BasicType::Sampler2D: + case ShaderNodes::BasicType::Void: + break; + } + + break; + } + + case ShaderNodes::BinaryType::CompGt: + { + switch (leftType) + { + case ShaderNodes::BasicType::Float1: + case ShaderNodes::BasicType::Float2: + case ShaderNodes::BasicType::Float3: + case ShaderNodes::BasicType::Float4: + case ShaderNodes::BasicType::Mat4x4: + return SpirvOp::OpFOrdGreaterThanEqual; + + case ShaderNodes::BasicType::Int1: + case ShaderNodes::BasicType::Int2: + case ShaderNodes::BasicType::Int3: + case ShaderNodes::BasicType::Int4: + return SpirvOp::OpSGreaterThanEqual; + + case ShaderNodes::BasicType::UInt1: + case ShaderNodes::BasicType::UInt2: + case ShaderNodes::BasicType::UInt3: + case ShaderNodes::BasicType::UInt4: + return SpirvOp::OpUGreaterThanEqual; + + case ShaderNodes::BasicType::Boolean: + case ShaderNodes::BasicType::Sampler2D: + case ShaderNodes::BasicType::Void: + break; + } + + break; + } + + case ShaderNodes::BinaryType::CompLe: + { + switch (leftType) + { + case ShaderNodes::BasicType::Float1: + case ShaderNodes::BasicType::Float2: + case ShaderNodes::BasicType::Float3: + case ShaderNodes::BasicType::Float4: + case ShaderNodes::BasicType::Mat4x4: + return SpirvOp::OpFOrdLessThanEqual; + + case ShaderNodes::BasicType::Int1: + case ShaderNodes::BasicType::Int2: + case ShaderNodes::BasicType::Int3: + case ShaderNodes::BasicType::Int4: + return SpirvOp::OpSLessThanEqual; + + case ShaderNodes::BasicType::UInt1: + case ShaderNodes::BasicType::UInt2: + case ShaderNodes::BasicType::UInt3: + case ShaderNodes::BasicType::UInt4: + return SpirvOp::OpULessThanEqual; + + case ShaderNodes::BasicType::Boolean: + case ShaderNodes::BasicType::Sampler2D: + case ShaderNodes::BasicType::Void: + break; + } + + break; + } + + case ShaderNodes::BinaryType::CompLt: + { + switch (leftType) + { + case ShaderNodes::BasicType::Float1: + case ShaderNodes::BasicType::Float2: + case ShaderNodes::BasicType::Float3: + case ShaderNodes::BasicType::Float4: + case ShaderNodes::BasicType::Mat4x4: + return SpirvOp::OpFOrdLessThan; + + case ShaderNodes::BasicType::Int1: + case ShaderNodes::BasicType::Int2: + case ShaderNodes::BasicType::Int3: + case ShaderNodes::BasicType::Int4: + return SpirvOp::OpSLessThan; + + case ShaderNodes::BasicType::UInt1: + case ShaderNodes::BasicType::UInt2: + case ShaderNodes::BasicType::UInt3: + case ShaderNodes::BasicType::UInt4: + return SpirvOp::OpULessThan; + + case ShaderNodes::BasicType::Boolean: + case ShaderNodes::BasicType::Sampler2D: + case ShaderNodes::BasicType::Void: + break; + } + + break; + } + + case ShaderNodes::BinaryType::CompNe: + { + switch (leftType) + { + case ShaderNodes::BasicType::Boolean: + return SpirvOp::OpLogicalNotEqual; + + case ShaderNodes::BasicType::Float1: + case ShaderNodes::BasicType::Float2: + case ShaderNodes::BasicType::Float3: + case ShaderNodes::BasicType::Float4: + case ShaderNodes::BasicType::Mat4x4: + return SpirvOp::OpFOrdNotEqual; + + case ShaderNodes::BasicType::Int1: + case ShaderNodes::BasicType::Int2: + case ShaderNodes::BasicType::Int3: + case ShaderNodes::BasicType::Int4: + case ShaderNodes::BasicType::UInt1: + case ShaderNodes::BasicType::UInt2: + case ShaderNodes::BasicType::UInt3: + case ShaderNodes::BasicType::UInt4: + return SpirvOp::OpINotEqual; + + case ShaderNodes::BasicType::Sampler2D: + case ShaderNodes::BasicType::Void: + break; + } + + break; + } case ShaderNodes::BinaryType::Multiply: { diff --git a/src/Nazara/Shader/SpirvWriter.cpp b/src/Nazara/Shader/SpirvWriter.cpp index c8ad4d4b4..535d53297 100644 --- a/src/Nazara/Shader/SpirvWriter.cpp +++ b/src/Nazara/Shader/SpirvWriter.cpp @@ -33,7 +33,8 @@ namespace Nz using LocalContainer = std::unordered_set>; using ParameterContainer = std::unordered_set< std::shared_ptr>; - PreVisitor(const SpirvWriter::States& conditions, SpirvConstantCache& constantCache) : + PreVisitor(const ShaderAst& shader, const SpirvWriter::States& conditions, SpirvConstantCache& constantCache) : + m_shader(shader), m_conditions(conditions), m_constantCache(constantCache) { @@ -52,7 +53,10 @@ namespace Nz void Visit(ShaderNodes::ConditionalExpression& node) override { - if (m_conditions.enabledConditions.count(node.conditionName) != 0) + std::size_t conditionIndex = m_shader.FindConditionByName(node.conditionName); + assert(conditionIndex != ShaderAst::InvalidCondition); + + if (TestBit(m_conditions.enabledConditions, conditionIndex)) Visit(node.truePath); else Visit(node.falsePath); @@ -60,7 +64,10 @@ namespace Nz void Visit(ShaderNodes::ConditionalStatement& node) override { - if (m_conditions.enabledConditions.count(node.conditionName) != 0) + std::size_t conditionIndex = m_shader.FindConditionByName(node.conditionName); + assert(conditionIndex != ShaderAst::InvalidCondition); + + if (TestBit(m_conditions.enabledConditions, conditionIndex)) Visit(node.statement); } @@ -141,6 +148,7 @@ namespace Nz ParameterContainer paramVars; private: + const ShaderAst& m_shader; const SpirvWriter::States& m_conditions; SpirvConstantCache& m_constantCache; }; @@ -229,7 +237,7 @@ namespace Nz ShaderAstCloner cloner; - PreVisitor preVisitor(conditions, state.constantTypeCache); + PreVisitor preVisitor(shader, conditions, state.constantTypeCache); for (const auto& func : shader.GetFunctions()) { functionStatements.emplace_back(cloner.Clone(func.statement)); diff --git a/src/Nazara/VulkanRenderer/VulkanDevice.cpp b/src/Nazara/VulkanRenderer/VulkanDevice.cpp index 2d67003e7..5f6ed9e3d 100644 --- a/src/Nazara/VulkanRenderer/VulkanDevice.cpp +++ b/src/Nazara/VulkanRenderer/VulkanDevice.cpp @@ -39,6 +39,15 @@ namespace Nz return pipelineLayout; } + std::shared_ptr VulkanDevice::InstantiateShaderStage(const ShaderAst& shaderAst, const ShaderWriter::States& states) + { + auto stage = std::make_shared(); + if (!stage->Create(*this, shaderAst, states)) + return {}; + + return stage; + } + std::shared_ptr VulkanDevice::InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) { auto stage = std::make_shared(); diff --git a/src/Nazara/VulkanRenderer/VulkanShaderStage.cpp b/src/Nazara/VulkanRenderer/VulkanShaderStage.cpp index 9459ccfe3..2162a1c64 100644 --- a/src/Nazara/VulkanRenderer/VulkanShaderStage.cpp +++ b/src/Nazara/VulkanRenderer/VulkanShaderStage.cpp @@ -10,6 +10,26 @@ namespace Nz { + bool VulkanShaderStage::Create(Vk::Device& device, const ShaderAst& shader, const ShaderWriter::States& states) + { + m_stage = shader.GetStage(); + + SpirvWriter::Environment env; + + SpirvWriter writer; + writer.SetEnv(env); + + std::vector code = writer.Generate(shader, states); + + if (!m_shaderModule.Create(device, code.data(), code.size() * sizeof(UInt32))) + { + NazaraError("Failed to create shader module"); + return false; + } + + return true; + } + bool VulkanShaderStage::Create(Vk::Device& device, ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) { m_stage = type; @@ -18,24 +38,12 @@ namespace Nz { case ShaderLanguage::NazaraBinary: { - ByteStream byteStream(source, sourceSize); - auto shader = Nz::UnserializeShader(byteStream); - + auto shader = UnserializeShader(source, sourceSize); if (shader.GetStage() != type) throw std::runtime_error("incompatible shader stage"); - SpirvWriter::Environment env; - - SpirvWriter writer; - writer.SetEnv(env); - - std::vector code = writer.Generate(shader); - - if (!m_shaderModule.Create(device, code.data(), code.size() * sizeof(UInt32))) - { - NazaraError("Failed to create shader module"); + if (!Create(device, shader, {})) return false; - } break; } diff --git a/src/Nazara/VulkanRenderer/Wrapper/Instance.cpp b/src/Nazara/VulkanRenderer/Wrapper/Instance.cpp index e15812528..aa5f6f513 100644 --- a/src/Nazara/VulkanRenderer/Wrapper/Instance.cpp +++ b/src/Nazara/VulkanRenderer/Wrapper/Instance.cpp @@ -49,7 +49,11 @@ namespace Nz ss << "[Validation]"; - ss << "[" << pCallbackData->messageIdNumber << ":" << pCallbackData->pMessageIdName << "]: " << pCallbackData->pMessage; + ss << "[" << pCallbackData->messageIdNumber; + if (pCallbackData->pMessageIdName) + ss << ":" << pCallbackData->pMessageIdName; + + ss << "]: " << pCallbackData->pMessage; if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) NazaraError(ss.str()); diff --git a/src/ShaderNode/DataModels/BinOp.hpp b/src/ShaderNode/DataModels/BinOp.hpp new file mode 100644 index 000000000..8efb9fc6e --- /dev/null +++ b/src/ShaderNode/DataModels/BinOp.hpp @@ -0,0 +1,163 @@ +#pragma once + +#ifndef NAZARA_SHADERNODES_BINOP_HPP +#define NAZARA_SHADERNODES_BINOP_HPP + +#include +#include +#include + +template +class BinOp : public ShaderNode +{ + public: + BinOp(ShaderGraph& graph); + ~BinOp() = default; + + Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + + virtual QString GetOperationString() const = 0; + + unsigned int nPorts(QtNodes::PortType portType) const override; + + QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; + + std::shared_ptr outData(QtNodes::PortIndex port) override; + + QString portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; + bool portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; + + void setInData(std::shared_ptr value, int index) override; + + QtNodes::NodeValidationState validationState() const override; + QString validationMessage() const override; + + private: + virtual void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) = 0; + + bool ComputePreview(QPixmap& pixmap) override; + void UpdateOutput(); + + std::shared_ptr m_lhs; + std::shared_ptr m_rhs; + std::shared_ptr m_output; +}; + + +template +class BinAdd : public BinOp +{ + public: + using BinOp::BinOp; + + void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; + QString GetOperationString() const final; +}; + +template +class BinMul : public BinOp +{ + public: + using BinOp::BinOp; + + void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; + QString GetOperationString() const final; +}; + +template +class BinSub : public BinOp +{ + public: + using BinOp::BinOp; + + void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; + QString GetOperationString() const final; +}; + +template +class BinDiv : public BinOp +{ + public: + using BinOp::BinOp; + + void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; + QString GetOperationString() const final; +}; + + +class FloatAdd : public BinAdd +{ + public: + using BinAdd::BinAdd; + + QString caption() const override { return "Float addition"; } + QString name() const override { return "float_add"; } +}; + +class FloatMul : public BinMul +{ + public: + using BinMul::BinMul; + + QString caption() const override { return "Float multiplication"; } + QString name() const override { return "float_mul"; } +}; + +class FloatSub : public BinMul +{ + public: + using BinMul::BinMul; + + QString caption() const override { return "Float subtraction"; } + QString name() const override { return "float_sub"; } +}; + +class FloatDiv : public BinDiv +{ + public: + using BinDiv::BinDiv; + + QString caption() const override { return "Float division"; } + QString name() const override { return "float_div"; } +}; + + +class VecAdd : public BinAdd +{ + public: + using BinAdd::BinAdd; + + QString caption() const override { return "Vector addition"; } + QString name() const override { return "vec_add"; } +}; + +class VecMul : public BinMul +{ + public: + using BinMul::BinMul; + + QString caption() const override { return "Vector multiplication"; } + QString name() const override { return "vec_mul"; } +}; + +class VecSub : public BinMul +{ + public: + using BinMul::BinMul; + + QString caption() const override { return "Vector subtraction"; } + QString name() const override { return "vec_sub"; } +}; + +class VecDiv : public BinDiv +{ + public: + using BinDiv::BinDiv; + + QString caption() const override { return "Vector division"; } + QString name() const override { return "vec_div"; } +}; + +#include + +#endif diff --git a/src/ShaderNode/DataModels/BinOp.inl b/src/ShaderNode/DataModels/BinOp.inl new file mode 100644 index 000000000..10031254c --- /dev/null +++ b/src/ShaderNode/DataModels/BinOp.inl @@ -0,0 +1,240 @@ +#include +#include + +template +BinOp::BinOp(ShaderGraph& graph) : +ShaderNode(graph) +{ + UpdateOutput(); +} + +template +Nz::ShaderNodes::NodePtr BinOp::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +{ + assert(count == 2); + assert(outputIndex == 0); + + using BuilderType = typename Nz::ShaderBuilder::template BinOpBuilder; + constexpr BuilderType builder; + return builder(expressions[0], expressions[1]); +} + +template +QtNodes::NodeDataType BinOp::dataType(QtNodes::PortType /*portType*/, QtNodes::PortIndex portIndex) const +{ + assert(portIndex == 0 || portIndex == 1); + + return DataType::Type(); +} + +template +unsigned int BinOp::nPorts(QtNodes::PortType portType) const +{ + switch (portType) + { + case QtNodes::PortType::In: return 2; + case QtNodes::PortType::Out: return 1; + default: break; + } + + assert(false); + throw std::runtime_error("invalid port type"); +} + +template +std::shared_ptr BinOp::outData(QtNodes::PortIndex port) +{ + assert(port == 0); + return m_output; +} + +template +QString BinOp::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const +{ + switch (portType) + { + case QtNodes::PortType::In: + { + switch (portIndex) + { + case 0: + return "A"; + + case 1: + return "B"; + + default: + break; + } + } + + case QtNodes::PortType::Out: + { + assert(portIndex == 0); + return "A " + GetOperationString() + " B"; + } + + default: + break; + } + + return QString{}; +} + +template +bool BinOp::portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const +{ + assert(portIndex == 0 || portIndex == 1); + return portType == QtNodes::PortType::In || portType == QtNodes::PortType::Out; +} + +template +void BinOp::setInData(std::shared_ptr value, int index) +{ + assert(index == 0 || index == 1); + + std::shared_ptr castedValue; + if (value && value->type().id == DataType::Type().id) + castedValue = std::static_pointer_cast(value); + + if (index == 0) + m_lhs = std::move(castedValue); + else + m_rhs = std::move(castedValue); + + UpdateOutput(); +} + +template +QtNodes::NodeValidationState BinOp::validationState() const +{ + if (!m_lhs || !m_rhs) + return QtNodes::NodeValidationState::Error; + + if constexpr (std::is_same_v) + { + if (m_lhs->componentCount != m_rhs->componentCount) + return QtNodes::NodeValidationState::Error; + } + + return QtNodes::NodeValidationState::Valid; +} + +template +QString BinOp::validationMessage() const +{ + if (!m_lhs || !m_rhs) + return "Missing operands"; + + if constexpr (std::is_same_v) + { + if (m_lhs->componentCount != m_rhs->componentCount) + return "Incompatible components count (left has " + QString::number(m_lhs->componentCount) + ", right has " + QString::number(m_rhs->componentCount) + ")"; + } + + return QString(); +} + +template +bool BinOp::ComputePreview(QPixmap& pixmap) +{ + if (!m_lhs || !m_rhs) + return false; + + pixmap = QPixmap::fromImage(m_output->preview.GenerateImage()); + return true; +} + +template +void BinOp::UpdateOutput() +{ + if (validationState() != QtNodes::NodeValidationState::Valid) + { + if constexpr (std::is_same_v) + m_output = std::make_shared(4); + else + m_output = std::make_shared(); + + m_output->preview = PreviewValues(1, 1); + m_output->preview.Fill(Nz::Vector4f::Zero()); + return; + } + + if constexpr (std::is_same_v) + m_output = std::make_shared(m_lhs->componentCount); + else + m_output = std::make_shared(); + + const PreviewValues& leftPreview = m_lhs->preview; + const PreviewValues& rightPreview = m_rhs->preview; + std::size_t maxWidth = std::max(leftPreview.GetWidth(), rightPreview.GetWidth()); + std::size_t maxHeight = std::max(leftPreview.GetHeight(), rightPreview.GetHeight()); + + // FIXME: Prevent useless copy + PreviewValues leftResized = leftPreview; + if (leftResized.GetWidth() != maxWidth || leftResized.GetHeight() != maxHeight) + leftResized = leftResized.Resized(maxWidth, maxHeight); + + PreviewValues rightResized = rightPreview; + if (rightResized.GetWidth() != maxWidth || rightResized.GetHeight() != maxHeight) + rightResized = rightResized.Resized(maxWidth, maxHeight); + + m_output->preview = PreviewValues(maxWidth, maxHeight); + ApplyOp(leftResized.GetData(), rightResized.GetData(), m_output->preview.GetData(), maxWidth * maxHeight); + + Q_EMIT dataUpdated(0); + + UpdatePreview(); +} + +template +void BinAdd::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) +{ + for (std::size_t i = 0; i < pixelCount; ++i) + output[i] = left[i] + right[i]; +} + +template +QString BinAdd::GetOperationString() const +{ + return "+"; +} + +template +void BinMul::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) +{ + for (std::size_t i = 0; i < pixelCount; ++i) + output[i] = left[i] * right[i]; +} + +template +QString BinMul::GetOperationString() const +{ + return "*"; +} + +template +void BinSub::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) +{ + for (std::size_t i = 0; i < pixelCount; ++i) + output[i] = left[i] - right[i]; +} + +template +QString BinSub::GetOperationString() const +{ + return "-"; +} + +template +void BinDiv::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) +{ + for (std::size_t i = 0; i < pixelCount; ++i) + output[i] = left[i] / right[i]; +} + +template +QString BinDiv::GetOperationString() const +{ + return "/"; +} diff --git a/src/ShaderNode/DataModels/BoolValue.cpp b/src/ShaderNode/DataModels/BoolValue.cpp new file mode 100644 index 000000000..940d8f0fb --- /dev/null +++ b/src/ShaderNode/DataModels/BoolValue.cpp @@ -0,0 +1,126 @@ +#include +#include +#include +#include +#include + +BoolValue::BoolValue(ShaderGraph& graph) : +ShaderNode(graph), +m_value(true) +{ + UpdatePreview(); +} + +QString BoolValue::caption() const +{ + static QString caption = "Boolean constant"; + return caption; +} + +QString BoolValue::name() const +{ + static QString name = "bool_constant"; + return name; +} + +QtNodes::NodeDataType BoolValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const +{ + assert(portType == QtNodes::PortType::Out); + assert(portIndex == 0); + + return BoolData::Type(); +} + +unsigned int BoolValue::nPorts(QtNodes::PortType portType) const +{ + switch (portType) + { + case QtNodes::PortType::In: return 0; + case QtNodes::PortType::Out: return 1; + + default: + break; + } + + assert(false); + throw std::runtime_error("Invalid port type"); +} + +std::shared_ptr BoolValue::outData(QtNodes::PortIndex port) +{ + assert(port == 0); + + float c = (m_value) ? 1.f : 0.f; + + auto out = std::make_shared(); + out->preview(0, 0) = Nz::Vector4f(c, c, c, 1.f); + + return out; +} + +QString BoolValue::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const +{ + assert(portIndex == 0); + assert(portType == QtNodes::PortType::Out); + + return (m_value) ? "true" : "false"; +} + +bool BoolValue::portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const +{ + assert(portIndex == 0); + return portType == QtNodes::PortType::Out; +} + +void BoolValue::BuildNodeEdition(QFormLayout* layout) +{ + ShaderNode::BuildNodeEdition(layout); + + QCheckBox* checkbox = new QCheckBox; + checkbox->setCheckState((m_value) ? Qt::Checked : Qt::Unchecked); + connect(checkbox, &QCheckBox::stateChanged, [=](int newState) + { + m_value = (newState == Qt::Checked); + Q_EMIT dataUpdated(0); + + UpdatePreview(); + }); + + layout->addRow(tr("Value"), checkbox); +} + +Nz::ShaderNodes::NodePtr BoolValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count, std::size_t outputIndex) const +{ + assert(count == 0); + assert(outputIndex == 0); + + return Nz::ShaderBuilder::Constant(m_value); +} + +bool BoolValue::ComputePreview(QPixmap& pixmap) +{ + pixmap.fill(ToColor()); + return true; +} + +QColor BoolValue::ToColor() const +{ + float value = (m_value) ? 1.f : 0.f; + + return QColor::fromRgbF(value, value, value, value); +} + +void BoolValue::restore(const QJsonObject& data) +{ + m_value = float(data["value"].toBool(m_value)); + + ShaderNode::restore(data); +} + +QJsonObject BoolValue::save() const +{ + QJsonObject data = ShaderNode::save(); + data["value"] = m_value; + + return data; +} diff --git a/src/ShaderNode/DataModels/BoolValue.hpp b/src/ShaderNode/DataModels/BoolValue.hpp new file mode 100644 index 000000000..d3e664d9d --- /dev/null +++ b/src/ShaderNode/DataModels/BoolValue.hpp @@ -0,0 +1,47 @@ +#pragma once + +#ifndef NAZARA_SHADERNODES_BOOLVALUE_HPP +#define NAZARA_SHADERNODES_BOOLVALUE_HPP + +#include +#include +#include +#include +#include +#include +#include + +class BoolValue : public ShaderNode +{ + public: + BoolValue(ShaderGraph& graph); + ~BoolValue() = default; + + Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + void BuildNodeEdition(QFormLayout* layout) override; + + QString caption() const override; + QString name() const override; + + QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; + + unsigned int nPorts(QtNodes::PortType portType) const override; + + std::shared_ptr outData(QtNodes::PortIndex port) override; + + QString portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; + bool portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; + + private: + bool ComputePreview(QPixmap& pixmap) override; + QColor ToColor() const; + + void restore(const QJsonObject& data) override; + QJsonObject save() const override; + + bool m_value; +}; + +#include + +#endif diff --git a/src/ShaderNode/DataModels/BoolValue.inl b/src/ShaderNode/DataModels/BoolValue.inl new file mode 100644 index 000000000..428c66ae7 --- /dev/null +++ b/src/ShaderNode/DataModels/BoolValue.inl @@ -0,0 +1 @@ +#include diff --git a/src/ShaderNode/DataModels/BufferField.cpp b/src/ShaderNode/DataModels/BufferField.cpp index 3f3986fb5..11707f717 100644 --- a/src/ShaderNode/DataModels/BufferField.cpp +++ b/src/ShaderNode/DataModels/BufferField.cpp @@ -49,9 +49,10 @@ ShaderNode(graph) UpdatePreview(); } -Nz::ShaderNodes::ExpressionPtr BufferField::GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const +Nz::ShaderNodes::NodePtr BufferField::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == 0); + assert(outputIndex == 0); if (!m_currentBufferIndex) throw std::runtime_error("no buffer"); diff --git a/src/ShaderNode/DataModels/BufferField.hpp b/src/ShaderNode/DataModels/BufferField.hpp index 8bd232a7a..7e5e46be4 100644 --- a/src/ShaderNode/DataModels/BufferField.hpp +++ b/src/ShaderNode/DataModels/BufferField.hpp @@ -15,10 +15,9 @@ class BufferField : public ShaderNode BufferField(ShaderGraph& graph); ~BufferField() = default; + Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; void BuildNodeEdition(QFormLayout* layout) override; - Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const override; - QString caption() const override { return "BufferField"; } QString name() const override { return "BufferField"; } diff --git a/src/ShaderNode/DataModels/Cast.hpp b/src/ShaderNode/DataModels/Cast.hpp index c30f3eadc..ea3303dd3 100644 --- a/src/ShaderNode/DataModels/Cast.hpp +++ b/src/ShaderNode/DataModels/Cast.hpp @@ -17,10 +17,9 @@ class CastVec : public ShaderNode CastVec(ShaderGraph& graph); ~CastVec() = default; + Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const; void BuildNodeEdition(QFormLayout* layout) override; - Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override; - QString caption() const override; QString name() const override; diff --git a/src/ShaderNode/DataModels/Cast.inl b/src/ShaderNode/DataModels/Cast.inl index 0bad72055..5a215c72a 100644 --- a/src/ShaderNode/DataModels/Cast.inl +++ b/src/ShaderNode/DataModels/Cast.inl @@ -16,6 +16,44 @@ ShaderNode(graph) m_output = std::make_shared(ToComponentCount); } +template +Nz::ShaderNodes::NodePtr CastVec::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +{ + assert(m_input); + assert(count == 1); + assert(outputIndex == 0); + + std::size_t fromComponentCount = m_input->componentCount; + + if (ToComponentCount > fromComponentCount) + { + std::size_t overflowComponentCount = ToComponentCount - fromComponentCount; + + std::array expr; + expr[0] = expressions[0]; + for (std::size_t i = 0; i < overflowComponentCount; ++i) + expr[i + 1] = Nz::ShaderBuilder::Constant(m_overflowComponents[i]); + + constexpr auto ExpressionType = VecExpressionType; + + return Nz::ShaderBuilder::Cast(expr.data(), 1 + overflowComponentCount); + } + else if (ToComponentCount < fromComponentCount) + { + std::array swizzleComponents; + for (std::size_t i = 0; i < ToComponentCount; ++i) + swizzleComponents[i] = static_cast(static_cast(Nz::ShaderNodes::SwizzleComponent::First) + i); + + return std::apply([&](auto... components) + { + std::initializer_list componentList{ components... }; + return Nz::ShaderBuilder::Swizzle(expressions[0], componentList); + }, swizzleComponents); + } + else + return expressions[0]; //< no-op +} + template void CastVec::BuildNodeEdition(QFormLayout* layout) { @@ -48,43 +86,6 @@ void CastVec::BuildNodeEdition(QFormLayout* layout) } } -template -Nz::ShaderNodes::ExpressionPtr CastVec::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const -{ - assert(m_input); - assert(count == 1); - - std::size_t fromComponentCount = m_input->componentCount; - - if (ToComponentCount > fromComponentCount) - { - std::size_t overflowComponentCount = ToComponentCount - fromComponentCount; - - std::array expr; - expr[0] = expressions[0]; - for (std::size_t i = 0; i < overflowComponentCount; ++i) - expr[i + 1] = Nz::ShaderBuilder::Constant(m_overflowComponents[i]); - - constexpr auto ExpressionType = VecExpressionType; - - return Nz::ShaderBuilder::Cast(expr.data(), 1 + overflowComponentCount); - } - else if (ToComponentCount < fromComponentCount) - { - std::array swizzleComponents; - for (std::size_t i = 0; i < ToComponentCount; ++i) - swizzleComponents[i] = static_cast(static_cast(Nz::ShaderNodes::SwizzleComponent::First) + i); - - return std::apply([&](auto... components) - { - std::initializer_list componentList{ components... }; - return Nz::ShaderBuilder::Swizzle(expressions[0], componentList); - }, swizzleComponents); - } - else - return expressions[0]; //< no-op -} - template QString CastVec::caption() const { diff --git a/src/ShaderNode/DataModels/CompOp.hpp b/src/ShaderNode/DataModels/CompOp.hpp new file mode 100644 index 000000000..cb7da53e4 --- /dev/null +++ b/src/ShaderNode/DataModels/CompOp.hpp @@ -0,0 +1,220 @@ +#pragma once + +#ifndef NAZARA_SHADERNODES_COMPOP_HPP +#define NAZARA_SHADERNODES_COMPOP_HPP + +#include +#include +#include +#include + +template +class CompOp : public ShaderNode +{ + public: + CompOp(ShaderGraph& graph); + ~CompOp() = default; + + Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + + virtual QString GetOperationString() const = 0; + + unsigned int nPorts(QtNodes::PortType portType) const override; + + QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; + + std::shared_ptr outData(QtNodes::PortIndex port) override; + + QString portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; + bool portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; + + void setInData(std::shared_ptr value, int index) override; + + QtNodes::NodeValidationState validationState() const override; + QString validationMessage() const override; + + private: + virtual void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) = 0; + + bool ComputePreview(QPixmap& pixmap) override; + void UpdateOutput(); + + std::shared_ptr m_output; + std::shared_ptr m_lhs; + std::shared_ptr m_rhs; +}; + + +template +class CompEq : public CompOp +{ + public: + using CompOp::CompOp; + + void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; + QString GetOperationString() const final; +}; + +template +class CompGe : public CompOp +{ + public: + using CompOp::CompOp; + + void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; + QString GetOperationString() const final; +}; + +template +class CompGt : public CompOp +{ + public: + using CompOp::CompOp; + + void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; + QString GetOperationString() const final; +}; + +template +class CompLe : public CompOp +{ + public: + using CompOp::CompOp; + + void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; + QString GetOperationString() const final; +}; + +template +class CompLt : public CompOp +{ + public: + using CompOp::CompOp; + + void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; + QString GetOperationString() const final; +}; + +template +class CompNe : public CompOp +{ + public: + using CompOp::CompOp; + + void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; + QString GetOperationString() const final; +}; + + +class FloatEq : public CompEq +{ + public: + using CompEq::CompEq; + + QString caption() const override { return "Float equality"; } + QString name() const override { return "float_eq"; } +}; + +class FloatGe : public CompGe +{ + public: + using CompGe::CompGe; + + QString caption() const override { return "Float greater than or equal"; } + QString name() const override { return "float_ge"; } +}; + +class FloatGt : public CompGt +{ + public: + using CompGt::CompGt; + + QString caption() const override { return "Float greater than"; } + QString name() const override { return "float_gt"; } +}; + +class FloatLe : public CompLe +{ + public: + using CompLe::CompLe; + + QString caption() const override { return "Float less than or equal"; } + QString name() const override { return "float_le"; } +}; + +class FloatLt : public CompLt +{ + public: + using CompLt::CompLt; + + QString caption() const override { return "Float less than"; } + QString name() const override { return "float_lt"; } +}; + +class FloatNe : public CompNe +{ + public: + using CompNe::CompNe; + + QString caption() const override { return "Float inequality"; } + QString name() const override { return "float_ne"; } +}; + + +class VecEq : public CompEq +{ + public: + using CompEq::CompEq; + + QString caption() const override { return "Vector equality"; } + QString name() const override { return "vec_eq"; } +}; + +class VecGe : public CompGe +{ + public: + using CompGe::CompGe; + + QString caption() const override { return "Vector greater than or equal"; } + QString name() const override { return "vec_ge"; } +}; + +class VecGt : public CompGt +{ + public: + using CompGt::CompGt; + + QString caption() const override { return "Vector greater than"; } + QString name() const override { return "vec_gt"; } +}; + +class VecLe : public CompLe +{ + public: + using CompLe::CompLe; + + QString caption() const override { return "Vector less than or equal"; } + QString name() const override { return "vec_le"; } +}; + +class VecLt : public CompLt +{ + public: + using CompLt::CompLt; + + QString caption() const override { return "Vector less than"; } + QString name() const override { return "vec_lt"; } +}; + +class VecNe : public CompNe +{ + public: + using CompNe::CompNe; + + QString caption() const override { return "Vector inequality"; } + QString name() const override { return "vec_ne"; } +}; + +#include + +#endif diff --git a/src/ShaderNode/DataModels/CompOp.inl b/src/ShaderNode/DataModels/CompOp.inl new file mode 100644 index 000000000..4ca0a122e --- /dev/null +++ b/src/ShaderNode/DataModels/CompOp.inl @@ -0,0 +1,293 @@ +#include +#include + +template +CompOp::CompOp(ShaderGraph& graph) : +ShaderNode(graph) +{ + UpdateOutput(); +} + +template +Nz::ShaderNodes::NodePtr CompOp::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +{ + assert(count == 2); + assert(outputIndex == 0); + + using BuilderType = typename Nz::ShaderBuilder::template BinOpBuilder; + constexpr BuilderType builder; + return builder(expressions[0], expressions[1]); +} + +template +QtNodes::NodeDataType CompOp::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const +{ + switch (portType) + { + case QtNodes::PortType::In: + { + assert(portIndex == 0 || portIndex == 1); + return DataType::Type(); + } + + case QtNodes::PortType::Out: + { + assert(portIndex == 0); + return BoolData::Type(); + } + + default: break; + } + + assert(false); + throw std::runtime_error("invalid port type"); +} + +template +unsigned int CompOp::nPorts(QtNodes::PortType portType) const +{ + switch (portType) + { + case QtNodes::PortType::In: return 2; + case QtNodes::PortType::Out: return 1; + default: break; + } + + assert(false); + throw std::runtime_error("invalid port type"); +} + +template +std::shared_ptr CompOp::outData(QtNodes::PortIndex port) +{ + assert(port == 0); + return m_output; +} + +template +QString CompOp::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const +{ + switch (portType) + { + case QtNodes::PortType::In: + { + switch (portIndex) + { + case 0: + return "A"; + + case 1: + return "B"; + + default: + break; + } + } + + case QtNodes::PortType::Out: + { + assert(portIndex == 0); + return "A " + GetOperationString() + " B"; + } + + default: + break; + } + + return QString{}; +} + +template +bool CompOp::portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const +{ + assert(portIndex == 0 || portIndex == 1); + return portType == QtNodes::PortType::In || portType == QtNodes::PortType::Out; +} + +template +void CompOp::setInData(std::shared_ptr value, int index) +{ + assert(index == 0 || index == 1); + + std::shared_ptr castedValue; + if (value && value->type().id == DataType::Type().id) + castedValue = std::static_pointer_cast(value); + + if (index == 0) + m_lhs = std::move(castedValue); + else + m_rhs = std::move(castedValue); + + UpdateOutput(); +} + +template +QtNodes::NodeValidationState CompOp::validationState() const +{ + if (!m_lhs || !m_rhs) + return QtNodes::NodeValidationState::Error; + + if constexpr (std::is_same_v) + { + if (m_lhs->componentCount != m_rhs->componentCount) + return QtNodes::NodeValidationState::Error; + } + + return QtNodes::NodeValidationState::Valid; +} + +template +QString CompOp::validationMessage() const +{ + if (!m_lhs || !m_rhs) + return "Missing operands"; + + if constexpr (std::is_same_v) + { + if (m_lhs->componentCount != m_rhs->componentCount) + return "Incompatible components count (left has " + QString::number(m_lhs->componentCount) + ", right has " + QString::number(m_rhs->componentCount) + ")"; + } + + return QString(); +} + +template +bool CompOp::ComputePreview(QPixmap& pixmap) +{ + if (!m_lhs || !m_rhs) + return false; + + pixmap = QPixmap::fromImage(m_output->preview.GenerateImage()); + return true; +} + +template +void CompOp::UpdateOutput() +{ + if (validationState() != QtNodes::NodeValidationState::Valid) + { + m_output = std::make_shared(); + m_output->preview = PreviewValues(1, 1); + m_output->preview.Fill(Nz::Vector4f::Zero()); + return; + } + + m_output = std::make_shared(); + + const PreviewValues& leftPreview = m_lhs->preview; + const PreviewValues& rightPreview = m_rhs->preview; + std::size_t maxWidth = std::max(leftPreview.GetWidth(), rightPreview.GetWidth()); + std::size_t maxHeight = std::max(leftPreview.GetHeight(), rightPreview.GetHeight()); + + // FIXME: Prevent useless copy + PreviewValues leftResized = leftPreview; + if (leftResized.GetWidth() != maxWidth || leftResized.GetHeight() != maxHeight) + leftResized = leftResized.Resized(maxWidth, maxHeight); + + PreviewValues rightResized = rightPreview; + if (rightResized.GetWidth() != maxWidth || rightResized.GetHeight() != maxHeight) + rightResized = rightResized.Resized(maxWidth, maxHeight); + + m_output->preview = PreviewValues(maxWidth, maxHeight); + ApplyOp(leftResized.GetData(), rightResized.GetData(), m_output->preview.GetData(), maxWidth * maxHeight); + + Q_EMIT dataUpdated(0); + + UpdatePreview(); +} + +template +void CompEq::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) +{ + for (std::size_t i = 0; i < pixelCount; ++i) + { + float r = (left[i] == right[i]) ? 1.f : 0.f; + output[i] = Nz::Vector4f(r, r, r, r); + } +} + +template +QString CompEq::GetOperationString() const +{ + return "=="; +} + +template +void CompGe::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) +{ + for (std::size_t i = 0; i < pixelCount; ++i) + { + float r = (left[i] >= right[i]) ? 1.f : 0.f; + output[i] = Nz::Vector4f(r, r, r, r); + } +} + +template +QString CompGe::GetOperationString() const +{ + return ">="; +} + +template +void CompGt::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) +{ + for (std::size_t i = 0; i < pixelCount; ++i) + { + float r = (left[i] > right[i]) ? 1.f : 0.f; + output[i] = Nz::Vector4f(r, r, r, r); + } +} + +template +QString CompGt::GetOperationString() const +{ + return ">"; +} + +template +void CompLe::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) +{ + for (std::size_t i = 0; i < pixelCount; ++i) + { + float r = (left[i] >= right[i]) ? 1.f : 0.f; + output[i] = Nz::Vector4f(r, r, r, r); + } +} + +template +QString CompLe::GetOperationString() const +{ + return "<="; +} + +template +void CompLt::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) +{ + for (std::size_t i = 0; i < pixelCount; ++i) + { + float r = (left[i] > right[i]) ? 1.f : 0.f; + output[i] = Nz::Vector4f(r, r, r, r); + } +} + +template +QString CompLt::GetOperationString() const +{ + return "<"; +} + +template +void CompNe::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) +{ + for (std::size_t i = 0; i < pixelCount; ++i) + { + float r = (left[i] != right[i]) ? 1.f : 0.f; + output[i] = Nz::Vector4f(r, r, r, r); + } +} + +template +QString CompNe::GetOperationString() const +{ + return "!="; +} diff --git a/src/ShaderNode/DataModels/ConditionalExpression.cpp b/src/ShaderNode/DataModels/ConditionalExpression.cpp index d034ada49..27224e8d6 100644 --- a/src/ShaderNode/DataModels/ConditionalExpression.cpp +++ b/src/ShaderNode/DataModels/ConditionalExpression.cpp @@ -35,9 +35,10 @@ ShaderNode(graph) UpdatePreview(); } -Nz::ShaderNodes::ExpressionPtr ConditionalExpression::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const +Nz::ShaderNodes::NodePtr ConditionalExpression::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == 2); + assert(outputIndex == 0); if (!m_currentConditionIndex) throw std::runtime_error("no condition"); @@ -100,15 +101,48 @@ void ConditionalExpression::BuildNodeEdition(QFormLayout* layout) auto ConditionalExpression::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const -> QtNodes::NodeDataType { + switch (portType) + { + case QtNodes::PortType::In: + { + switch (portIndex) + { + case 0: + { + if (!m_truePath && !m_falsePath) + return VecData::Type(); + + return (m_truePath) ? m_truePath->type() : m_falsePath->type(); + } + + case 1: + { + if (!m_truePath && !m_falsePath) + return VecData::Type(); + + return (m_falsePath) ? m_falsePath->type() : m_truePath->type(); + } + + default: + break; + } + } + + case QtNodes::PortType::Out: + { + assert(portIndex == 0); + + if (!m_truePath && !m_falsePath) + return VecData::Type(); + + return (m_truePath) ? m_truePath->type() : m_falsePath->type(); + } + + default: + break; + } + return VecData::Type(); - - assert(portType == QtNodes::PortType::Out); - assert(portIndex == 0); - - if (!m_truePath && !m_falsePath) - return VecData::Type(); - - return (m_truePath) ? m_truePath->type() : m_falsePath->type(); } QString ConditionalExpression::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const @@ -120,10 +154,10 @@ QString ConditionalExpression::portCaption(QtNodes::PortType portType, QtNodes:: switch (portIndex) { case 0: - return "True path"; + return "True expression"; case 1: - return "False path"; + return "False expression"; default: break; @@ -189,6 +223,9 @@ QtNodes::NodeValidationState ConditionalExpression::validationState() const QString ConditionalExpression::validationMessage() const { + if (!m_currentConditionIndex) + return "Invalid condition"; + if (!m_truePath || !m_falsePath) return "Missing input"; diff --git a/src/ShaderNode/DataModels/ConditionalExpression.hpp b/src/ShaderNode/DataModels/ConditionalExpression.hpp index a89d6c40c..1c732243d 100644 --- a/src/ShaderNode/DataModels/ConditionalExpression.hpp +++ b/src/ShaderNode/DataModels/ConditionalExpression.hpp @@ -15,10 +15,9 @@ class ConditionalExpression : public ShaderNode ConditionalExpression(ShaderGraph& graph); ~ConditionalExpression() = default; + Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; void BuildNodeEdition(QFormLayout* layout) override; - Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const override; - QString caption() const override; QString name() const override; diff --git a/src/ShaderNode/DataModels/FloatValue.cpp b/src/ShaderNode/DataModels/FloatValue.cpp index 23a4c766f..4efc10585 100644 --- a/src/ShaderNode/DataModels/FloatValue.cpp +++ b/src/ShaderNode/DataModels/FloatValue.cpp @@ -36,9 +36,13 @@ unsigned int FloatValue::nPorts(QtNodes::PortType portType) const { case QtNodes::PortType::In: return 0; case QtNodes::PortType::Out: return 1; + + default: + break; } - return 0; + assert(false); + throw std::runtime_error("Invalid port type"); } std::shared_ptr FloatValue::outData(QtNodes::PortIndex port) @@ -51,6 +55,20 @@ std::shared_ptr FloatValue::outData(QtNodes::PortIndex port) return out; } +QString FloatValue::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const +{ + assert(portIndex == 0); + assert(portType == QtNodes::PortType::Out); + + return QString::number(m_value); +} + +bool FloatValue::portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const +{ + assert(portIndex == 0); + return portType == QtNodes::PortType::Out; +} + void FloatValue::BuildNodeEdition(QFormLayout* layout) { ShaderNode::BuildNodeEdition(layout); @@ -71,9 +89,10 @@ void FloatValue::BuildNodeEdition(QFormLayout* layout) layout->addRow(tr("Value"), spinbox); } -Nz::ShaderNodes::ExpressionPtr FloatValue::GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const +Nz::ShaderNodes::NodePtr FloatValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == 0); + assert(outputIndex == 0); return Nz::ShaderBuilder::Constant(m_value); } diff --git a/src/ShaderNode/DataModels/FloatValue.hpp b/src/ShaderNode/DataModels/FloatValue.hpp index fe77e5464..6dfb110f8 100644 --- a/src/ShaderNode/DataModels/FloatValue.hpp +++ b/src/ShaderNode/DataModels/FloatValue.hpp @@ -17,6 +17,9 @@ class FloatValue : public ShaderNode FloatValue(ShaderGraph& graph); ~FloatValue() = default; + Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + void BuildNodeEdition(QFormLayout* layout) override; + QString caption() const override; QString name() const override; @@ -26,9 +29,8 @@ class FloatValue : public ShaderNode std::shared_ptr outData(QtNodes::PortIndex port) override; - void BuildNodeEdition(QFormLayout* layout) override; - - Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override; + QString portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; + bool portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; private: bool ComputePreview(QPixmap& pixmap) override; diff --git a/src/ShaderNode/DataModels/InputValue.cpp b/src/ShaderNode/DataModels/InputValue.cpp index e4710e6f5..f6926278b 100644 --- a/src/ShaderNode/DataModels/InputValue.cpp +++ b/src/ShaderNode/DataModels/InputValue.cpp @@ -109,9 +109,10 @@ void InputValue::BuildNodeEdition(QFormLayout* layout) layout->addRow(tr("Input"), inputSelection); } -Nz::ShaderNodes::ExpressionPtr InputValue::GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const +Nz::ShaderNodes::NodePtr InputValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count, std::size_t outputIndex) const { assert(count == 0); + assert(outputIndex == 0); if (!m_currentInputIndex) throw std::runtime_error("no input"); @@ -184,6 +185,35 @@ std::shared_ptr InputValue::outData(QtNodes::PortIndex port) throw std::runtime_error("Unhandled input type"); } +QString InputValue::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const +{ + assert(portIndex == 0); + assert(portType == QtNodes::PortType::Out); + + if (!m_currentInputIndex) + return QString(); + + const auto& inputEntry = GetGraph().GetInput(*m_currentInputIndex); + return QString::fromStdString(inputEntry.name); +} + +bool InputValue::portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const +{ + assert(portIndex == 0); + + switch (portType) + { + case QtNodes::PortType::In: return false; + case QtNodes::PortType::Out: return m_currentInputIndex.has_value(); + + default: + break; + } + + assert(false); + throw std::runtime_error("Invalid port type"); +} + QtNodes::NodeValidationState InputValue::validationState() const { if (!m_currentInputIndex) diff --git a/src/ShaderNode/DataModels/InputValue.hpp b/src/ShaderNode/DataModels/InputValue.hpp index d0e1593b9..9863d7b98 100644 --- a/src/ShaderNode/DataModels/InputValue.hpp +++ b/src/ShaderNode/DataModels/InputValue.hpp @@ -19,7 +19,7 @@ class InputValue : public ShaderNode void BuildNodeEdition(QFormLayout* layout) override; - Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const override; + Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override { return "Input"; } QString name() const override { return "Input"; } @@ -30,6 +30,9 @@ class InputValue : public ShaderNode std::shared_ptr outData(QtNodes::PortIndex port) override; + QString portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; + bool portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; + QtNodes::NodeValidationState validationState() const override; QString validationMessage() const override; diff --git a/src/ShaderNode/DataModels/Mat4BinOp.hpp b/src/ShaderNode/DataModels/Mat4BinOp.hpp index c90549bdd..1cd7e06dd 100644 --- a/src/ShaderNode/DataModels/Mat4BinOp.hpp +++ b/src/ShaderNode/DataModels/Mat4BinOp.hpp @@ -6,14 +6,14 @@ #include #include -template +template class Mat4BinOp : public ShaderNode { public: Mat4BinOp(ShaderGraph& graph); ~Mat4BinOp() = default; - Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override; + Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const; unsigned int nPorts(QtNodes::PortType portType) const override; diff --git a/src/ShaderNode/DataModels/Mat4BinOp.inl b/src/ShaderNode/DataModels/Mat4BinOp.inl index eb57e74c2..50c4102e4 100644 --- a/src/ShaderNode/DataModels/Mat4BinOp.inl +++ b/src/ShaderNode/DataModels/Mat4BinOp.inl @@ -1,51 +1,55 @@ #include #include -template -Mat4BinOp::Mat4BinOp(ShaderGraph& graph) : +template +Mat4BinOp::Mat4BinOp(ShaderGraph& graph) : ShaderNode(graph) { UpdateOutput(); } -template -Nz::ShaderNodes::ExpressionPtr Mat4BinOp::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const +template +Nz::ShaderNodes::NodePtr Mat4BinOp::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == 2); - using BuilderType = typename Nz::ShaderBuilder::template BinOpBuilder; + assert(outputIndex == 0); + + using BuilderType = typename Nz::ShaderBuilder::template BinOpBuilder; constexpr BuilderType builder; return builder(expressions[0], expressions[1]); } -template -QtNodes::NodeDataType Mat4BinOp::dataType(QtNodes::PortType /*portType*/, QtNodes::PortIndex portIndex) const +template +QtNodes::NodeDataType Mat4BinOp::dataType(QtNodes::PortType /*portType*/, QtNodes::PortIndex portIndex) const { assert(portIndex == 0 || portIndex == 1); return Matrix4Data::Type(); } -template -unsigned int Mat4BinOp::nPorts(QtNodes::PortType portType) const +template +unsigned int Mat4BinOp::nPorts(QtNodes::PortType portType) const { switch (portType) { case QtNodes::PortType::In: return 2; case QtNodes::PortType::Out: return 1; + default: break; } - return 0; + assert(false); + throw std::runtime_error("invalid port type"); } -template -std::shared_ptr Mat4BinOp::outData(QtNodes::PortIndex port) +template +std::shared_ptr Mat4BinOp::outData(QtNodes::PortIndex port) { assert(port == 0); return m_output; } -template -void Mat4BinOp::setInData(std::shared_ptr value, int index) +template +void Mat4BinOp::setInData(std::shared_ptr value, int index) { assert(index == 0 || index == 1); @@ -64,8 +68,8 @@ void Mat4BinOp::setInData(std::shared_ptr value, int i UpdateOutput(); } -template -QtNodes::NodeValidationState Mat4BinOp::validationState() const +template +QtNodes::NodeValidationState Mat4BinOp::validationState() const { if (!m_lhs || !m_rhs) return QtNodes::NodeValidationState::Error; @@ -73,8 +77,8 @@ QtNodes::NodeValidationState Mat4BinOp::validationState() const return QtNodes::NodeValidationState::Valid; } -template -QString Mat4BinOp::validationMessage() const +template +QString Mat4BinOp::validationMessage() const { if (!m_lhs || !m_rhs) return "Missing operands"; @@ -82,8 +86,8 @@ QString Mat4BinOp::validationMessage() const return QString(); } -template -bool Mat4BinOp::ComputePreview(QPixmap& pixmap) +template +bool Mat4BinOp::ComputePreview(QPixmap& pixmap) { if (!m_lhs || !m_rhs) return false; @@ -94,8 +98,8 @@ bool Mat4BinOp::ComputePreview(QPixmap& pixmap) //return true; } -template -void Mat4BinOp::UpdateOutput() +template +void Mat4BinOp::UpdateOutput() { if (validationState() != QtNodes::NodeValidationState::Valid) { diff --git a/src/ShaderNode/DataModels/Mat4VecMul.cpp b/src/ShaderNode/DataModels/Mat4VecMul.cpp index af43e4f1d..426c0bde1 100644 --- a/src/ShaderNode/DataModels/Mat4VecMul.cpp +++ b/src/ShaderNode/DataModels/Mat4VecMul.cpp @@ -7,9 +7,11 @@ ShaderNode(graph) UpdateOutput(); } -Nz::ShaderNodes::ExpressionPtr Mat4VecMul::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const +Nz::ShaderNodes::NodePtr Mat4VecMul::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == 2); + assert(outputIndex == 0); + using namespace Nz::ShaderNodes; return BinaryOp::Build(BinaryType::Multiply, expressions[0], expressions[1]); } diff --git a/src/ShaderNode/DataModels/Mat4VecMul.hpp b/src/ShaderNode/DataModels/Mat4VecMul.hpp index 608439fcb..d3b25b3b1 100644 --- a/src/ShaderNode/DataModels/Mat4VecMul.hpp +++ b/src/ShaderNode/DataModels/Mat4VecMul.hpp @@ -13,7 +13,7 @@ class Mat4VecMul : public ShaderNode Mat4VecMul(ShaderGraph& graph); ~Mat4VecMul() = default; - Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override; + Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override; QString name() const override; diff --git a/src/ShaderNode/DataModels/OutputValue.cpp b/src/ShaderNode/DataModels/OutputValue.cpp index 7ffb4df91..22d4bfb72 100644 --- a/src/ShaderNode/DataModels/OutputValue.cpp +++ b/src/ShaderNode/DataModels/OutputValue.cpp @@ -54,12 +54,13 @@ void OutputValue::BuildNodeEdition(QFormLayout* layout) layout->addRow(tr("Output"), outputSelection); } -Nz::ShaderNodes::ExpressionPtr OutputValue::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const +Nz::ShaderNodes::NodePtr OutputValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { using namespace Nz::ShaderBuilder; using namespace Nz::ShaderNodes; assert(count == 1); + assert(outputIndex == 0); if (!m_currentOutputIndex) throw std::runtime_error("no output"); @@ -70,6 +71,11 @@ Nz::ShaderNodes::ExpressionPtr OutputValue::GetExpression(Nz::ShaderNodes::Expre return Nz::ShaderBuilder::Assign(std::move(output), *expressions); } +std::shared_ptr OutputValue::outData(QtNodes::PortIndex /*port*/) +{ + return {}; +} + QtNodes::NodeDataType OutputValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const { assert(portType == QtNodes::PortType::In); @@ -88,14 +94,40 @@ unsigned int OutputValue::nPorts(QtNodes::PortType portType) const { case QtNodes::PortType::In: return 1; case QtNodes::PortType::Out: return 0; + default: break; } - return 0; + assert(false); + throw std::runtime_error("invalid port type"); } -std::shared_ptr OutputValue::outData(QtNodes::PortIndex /*port*/) +QString OutputValue::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const { - return {}; + assert(portType == QtNodes::PortType::In); + assert(portIndex == 0); + + if (!m_currentOutputIndex) + return QString(); + + const auto& outputEntry = GetGraph().GetOutput(*m_currentOutputIndex); + return QString::fromStdString(outputEntry.name); +} + +bool OutputValue::portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const +{ + assert(portIndex == 0); + + switch (portType) + { + case QtNodes::PortType::In: return m_currentOutputIndex.has_value(); + case QtNodes::PortType::Out: return false; + + default: + break; + } + + assert(false); + throw std::runtime_error("Invalid port type"); } void OutputValue::setInData(std::shared_ptr value, int index) diff --git a/src/ShaderNode/DataModels/OutputValue.hpp b/src/ShaderNode/DataModels/OutputValue.hpp index 12c812c5c..e798b7e82 100644 --- a/src/ShaderNode/DataModels/OutputValue.hpp +++ b/src/ShaderNode/DataModels/OutputValue.hpp @@ -16,7 +16,7 @@ class OutputValue : public ShaderNode void BuildNodeEdition(QFormLayout* layout) override; - Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override; + Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override { return "Output"; } QString name() const override { return "Output"; } @@ -27,6 +27,9 @@ class OutputValue : public ShaderNode std::shared_ptr outData(QtNodes::PortIndex port) override; + QString portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; + bool portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; + void setInData(std::shared_ptr value, int index) override; QtNodes::NodeValidationState validationState() const override; diff --git a/src/ShaderNode/DataModels/PositionOutputValue.cpp b/src/ShaderNode/DataModels/PositionOutputValue.cpp index 6f2ab9d3a..2f9f59716 100644 --- a/src/ShaderNode/DataModels/PositionOutputValue.cpp +++ b/src/ShaderNode/DataModels/PositionOutputValue.cpp @@ -14,12 +14,13 @@ ShaderNode(graph) DisableCustomVariableName(); } -Nz::ShaderNodes::ExpressionPtr PositionOutputValue::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const +Nz::ShaderNodes::NodePtr PositionOutputValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { using namespace Nz::ShaderBuilder; using namespace Nz::ShaderNodes; assert(count == 1); + assert(outputIndex == 0); auto output = Nz::ShaderBuilder::Identifier(Nz::ShaderBuilder::Builtin(BuiltinEntry::VertexPosition)); return Nz::ShaderBuilder::Assign(std::move(output), *expressions); diff --git a/src/ShaderNode/DataModels/PositionOutputValue.hpp b/src/ShaderNode/DataModels/PositionOutputValue.hpp index 2c2b6eb54..6626226e4 100644 --- a/src/ShaderNode/DataModels/PositionOutputValue.hpp +++ b/src/ShaderNode/DataModels/PositionOutputValue.hpp @@ -14,7 +14,7 @@ class PositionOutputValue : public ShaderNode public: PositionOutputValue(ShaderGraph& graph); - Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override; + Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override { return "PositionOutputValue"; } QString name() const override { return "PositionOutputValue"; } diff --git a/src/ShaderNode/DataModels/SampleTexture.cpp b/src/ShaderNode/DataModels/SampleTexture.cpp index f0eccc770..4d7fcddee 100644 --- a/src/ShaderNode/DataModels/SampleTexture.cpp +++ b/src/ShaderNode/DataModels/SampleTexture.cpp @@ -71,11 +71,12 @@ bool SampleTexture::ComputePreview(QPixmap& pixmap) return true; } -Nz::ShaderNodes::ExpressionPtr SampleTexture::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const +Nz::ShaderNodes::NodePtr SampleTexture::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(m_texture); assert(m_uv); assert(count == 2); + assert(outputIndex == 0); return Nz::ShaderBuilder::Sample2D(expressions[0], expressions[1]); } diff --git a/src/ShaderNode/DataModels/SampleTexture.hpp b/src/ShaderNode/DataModels/SampleTexture.hpp index 5b1dd98fd..d819a0df0 100644 --- a/src/ShaderNode/DataModels/SampleTexture.hpp +++ b/src/ShaderNode/DataModels/SampleTexture.hpp @@ -17,7 +17,7 @@ class SampleTexture : public ShaderNode SampleTexture(ShaderGraph& graph); ~SampleTexture() = default; - Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const override; + Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override { return "Sample texture"; } QString name() const override { return "SampleTexture"; } diff --git a/src/ShaderNode/DataModels/ShaderNode.cpp b/src/ShaderNode/DataModels/ShaderNode.cpp index e596a6a6d..abda9cd6b 100644 --- a/src/ShaderNode/DataModels/ShaderNode.cpp +++ b/src/ShaderNode/DataModels/ShaderNode.cpp @@ -85,6 +85,11 @@ void ShaderNode::EnablePreview(bool enable) } } +int ShaderNode::GetOutputOrder() const +{ + return 0; +} + QWidget* ShaderNode::embeddedWidget() { if (!m_embeddedWidget) diff --git a/src/ShaderNode/DataModels/ShaderNode.hpp b/src/ShaderNode/DataModels/ShaderNode.hpp index 874fce54f..d3b200768 100644 --- a/src/ShaderNode/DataModels/ShaderNode.hpp +++ b/src/ShaderNode/DataModels/ShaderNode.hpp @@ -18,14 +18,15 @@ class ShaderNode : public QtNodes::NodeDataModel public: ShaderNode(ShaderGraph& graph); + virtual Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const = 0; virtual void BuildNodeEdition(QFormLayout* layout); inline void DisablePreview(); void EnablePreview(bool enable = true); - virtual Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const = 0; inline ShaderGraph& GetGraph(); inline const ShaderGraph& GetGraph() const; + virtual int GetOutputOrder() const; inline const std::string& GetVariableName() const; inline void SetPreviewSize(const Nz::Vector2i& size); diff --git a/src/ShaderNode/DataModels/TextureValue.cpp b/src/ShaderNode/DataModels/TextureValue.cpp index c400d0469..9d0d25665 100644 --- a/src/ShaderNode/DataModels/TextureValue.cpp +++ b/src/ShaderNode/DataModels/TextureValue.cpp @@ -110,12 +110,13 @@ void TextureValue::BuildNodeEdition(QFormLayout* layout) layout->addRow(tr("Texture"), textureSelection); } -Nz::ShaderNodes::ExpressionPtr TextureValue::GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const +Nz::ShaderNodes::NodePtr TextureValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { if (!m_currentTextureIndex) throw std::runtime_error("invalid texture input"); assert(count == 0); + assert(outputIndex == 0); const auto& textureEntry = GetGraph().GetTexture(*m_currentTextureIndex); @@ -178,6 +179,32 @@ std::shared_ptr TextureValue::outData(QtNodes::PortIndex port return textureData; } +QString TextureValue::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const +{ + assert(portType == QtNodes::PortType::Out); + + if (!m_currentTextureIndex) + return QString(); + + const auto& textureEntry = GetGraph().GetTexture(*m_currentTextureIndex); + return QString::fromStdString(textureEntry.name); +} + +bool TextureValue::portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const +{ + switch (portType) + { + case QtNodes::PortType::In: return false; + case QtNodes::PortType::Out: return m_currentTextureIndex.has_value(); + + default: + break; + } + + assert(false); + throw std::runtime_error("Invalid port type"); +} + QtNodes::NodeValidationState TextureValue::validationState() const { if (!m_currentTextureIndex) diff --git a/src/ShaderNode/DataModels/TextureValue.hpp b/src/ShaderNode/DataModels/TextureValue.hpp index d328e2f05..6d6e6ff27 100644 --- a/src/ShaderNode/DataModels/TextureValue.hpp +++ b/src/ShaderNode/DataModels/TextureValue.hpp @@ -18,7 +18,7 @@ class TextureValue : public ShaderNode void BuildNodeEdition(QFormLayout* layout) override; - Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const override; + Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override { return "Texture"; } QString name() const override { return "Texture"; } @@ -29,6 +29,9 @@ class TextureValue : public ShaderNode std::shared_ptr outData(QtNodes::PortIndex port) override; + QString portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; + bool portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; + QtNodes::NodeValidationState validationState() const override; QString validationMessage() const override; diff --git a/src/ShaderNode/DataModels/VecBinOp.cpp b/src/ShaderNode/DataModels/VecBinOp.cpp deleted file mode 100644 index f99591420..000000000 --- a/src/ShaderNode/DataModels/VecBinOp.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include - -QString VecAdd::caption() const -{ - static QString caption = "Vector addition"; - return caption; -} - -QString VecAdd::name() const -{ - static QString name = "vec_add"; - return name; -} - -void VecAdd::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) -{ - for (std::size_t i = 0; i < pixelCount; ++i) - output[i] = left[i] + right[i]; -} - -QString VecMul::caption() const -{ - static QString caption = "Vector multiplication"; - return caption; -} - -QString VecMul::name() const -{ - static QString name = "vec_mul"; - return name; -} - -void VecMul::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) -{ - for (std::size_t i = 0; i < pixelCount; ++i) - output[i] = left[i] * right[i]; -} - -QString VecSub::caption() const -{ - static QString caption = "Vector subtraction"; - return caption; -} - - -QString VecSub::name() const -{ - static QString name = "vec_sub"; - return name; -} - -void VecSub::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) -{ - for (std::size_t i = 0; i < pixelCount; ++i) - output[i] = left[i] - right[i]; -} - -QString VecDiv::caption() const -{ - static QString caption = "Vector divide"; - return caption; -} - - -QString VecDiv::name() const -{ - static QString name = "vec_div"; - return name; -} - -void VecDiv::ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) -{ - for (std::size_t i = 0; i < pixelCount; ++i) - output[i] = left[i] / right[i]; -} diff --git a/src/ShaderNode/DataModels/VecBinOp.hpp b/src/ShaderNode/DataModels/VecBinOp.hpp deleted file mode 100644 index 3c0a5aebd..000000000 --- a/src/ShaderNode/DataModels/VecBinOp.hpp +++ /dev/null @@ -1,86 +0,0 @@ -#pragma once - -#ifndef NAZARA_SHADERNODES_VECBINOP_HPP -#define NAZARA_SHADERNODES_VECBINOP_HPP - -#include -#include - -template -class VecBinOp : public ShaderNode -{ - public: - VecBinOp(ShaderGraph& graph); - ~VecBinOp() = default; - - Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override; - - unsigned int nPorts(QtNodes::PortType portType) const override; - - QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; - - std::shared_ptr outData(QtNodes::PortIndex port) override; - - void setInData(std::shared_ptr value, int index) override; - - QtNodes::NodeValidationState validationState() const override; - QString validationMessage() const override; - - private: - virtual void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) = 0; - - bool ComputePreview(QPixmap& pixmap) override; - void UpdateOutput(); - - std::shared_ptr m_lhs; - std::shared_ptr m_rhs; - std::shared_ptr m_output; -}; - -class VecAdd : public VecBinOp -{ - public: - using VecBinOp::VecBinOp; - - QString caption() const override; - QString name() const override; - - void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; -}; - -class VecMul : public VecBinOp -{ - public: - using VecBinOp::VecBinOp; - - QString caption() const override; - QString name() const override; - - void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; -}; - -class VecSub : public VecBinOp -{ - public: - using VecBinOp::VecBinOp; - - QString caption() const override; - QString name() const override; - - void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; -}; - -class VecDiv : public VecBinOp -{ - public: - using VecBinOp::VecBinOp; - - QString caption() const override; - QString name() const override; - - void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; -}; - -#include - -#endif diff --git a/src/ShaderNode/DataModels/VecBinOp.inl b/src/ShaderNode/DataModels/VecBinOp.inl deleted file mode 100644 index a8b9d6d2d..000000000 --- a/src/ShaderNode/DataModels/VecBinOp.inl +++ /dev/null @@ -1,131 +0,0 @@ -#include -#include - -template -VecBinOp::VecBinOp(ShaderGraph& graph) : -ShaderNode(graph) -{ - UpdateOutput(); -} - -template -Nz::ShaderNodes::ExpressionPtr VecBinOp::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const -{ - assert(count == 2); - using BuilderType = typename Nz::ShaderBuilder::template BinOpBuilder; - constexpr BuilderType builder; - return builder(expressions[0], expressions[1]); -} - -template -QtNodes::NodeDataType VecBinOp::dataType(QtNodes::PortType /*portType*/, QtNodes::PortIndex portIndex) const -{ - assert(portIndex == 0 || portIndex == 1); - - return VecData::Type(); -} - -template -unsigned int VecBinOp::nPorts(QtNodes::PortType portType) const -{ - switch (portType) - { - case QtNodes::PortType::In: return 2; - case QtNodes::PortType::Out: return 1; - } - - return 0; -} - -template -std::shared_ptr VecBinOp::outData(QtNodes::PortIndex port) -{ - assert(port == 0); - return m_output; -} - -template -void VecBinOp::setInData(std::shared_ptr value, int index) -{ - assert(index == 0 || index == 1); - - std::shared_ptr castedValue; - if (value && value->type().id == VecData::Type().id) - castedValue = std::static_pointer_cast(value); - - if (index == 0) - m_lhs = std::move(castedValue); - else - m_rhs = std::move(castedValue); - - UpdateOutput(); -} - -template -QtNodes::NodeValidationState VecBinOp::validationState() const -{ - if (!m_lhs || !m_rhs) - return QtNodes::NodeValidationState::Error; - - if (m_lhs->componentCount != m_rhs->componentCount) - return QtNodes::NodeValidationState::Error; - - return QtNodes::NodeValidationState::Valid; -} - -template -QString VecBinOp::validationMessage() const -{ - if (!m_lhs || !m_rhs) - return "Missing operands"; - - if (m_lhs->componentCount != m_rhs->componentCount) - return "Incompatible components count (left has " + QString::number(m_lhs->componentCount) + ", right has " + QString::number(m_rhs->componentCount) + ")"; - - return QString(); -} - -template -bool VecBinOp::ComputePreview(QPixmap& pixmap) -{ - if (!m_lhs || !m_rhs) - return false; - - pixmap = QPixmap::fromImage(m_output->preview.GenerateImage()); - return true; -} - -template -void VecBinOp::UpdateOutput() -{ - if (validationState() != QtNodes::NodeValidationState::Valid) - { - m_output = std::make_shared(4); - m_output->preview = PreviewValues(1, 1); - m_output->preview.Fill(Nz::Vector4f::Zero()); - return; - } - - m_output = std::make_shared(m_lhs->componentCount); - - const PreviewValues& leftPreview = m_lhs->preview; - const PreviewValues& rightPreview = m_rhs->preview; - std::size_t maxWidth = std::max(leftPreview.GetWidth(), rightPreview.GetWidth()); - std::size_t maxHeight = std::max(leftPreview.GetHeight(), rightPreview.GetHeight()); - - // FIXME: Prevent useless copy - PreviewValues leftResized = leftPreview; - if (leftResized.GetWidth() != maxWidth || leftResized.GetHeight() != maxHeight) - leftResized = leftResized.Resized(maxWidth, maxHeight); - - PreviewValues rightResized = rightPreview; - if (rightResized.GetWidth() != maxWidth || rightResized.GetHeight() != maxHeight) - rightResized = rightResized.Resized(maxWidth, maxHeight); - - m_output->preview = PreviewValues(maxWidth, maxHeight); - ApplyOp(leftResized.GetData(), rightResized.GetData(), m_output->preview.GetData(), maxWidth * maxHeight); - - Q_EMIT dataUpdated(0); - - UpdatePreview(); -} diff --git a/src/ShaderNode/DataModels/VecComposition.hpp b/src/ShaderNode/DataModels/VecComposition.hpp new file mode 100644 index 000000000..6a41b1e20 --- /dev/null +++ b/src/ShaderNode/DataModels/VecComposition.hpp @@ -0,0 +1,49 @@ +#pragma once + +#ifndef NAZARA_SHADERNODES_VECTOR_COMPOSITION_HPP +#define NAZARA_SHADERNODES_VECTOR_COMPOSITION_HPP + +#include +#include +#include +#include +#include +#include + +template +class VecComposition : public ShaderNode +{ + public: + VecComposition(ShaderGraph& graph); + ~VecComposition() = default; + + Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const; + + QString caption() const override; + QString name() const override; + + QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; + unsigned int nPorts(QtNodes::PortType portType) const override; + + std::shared_ptr outData(QtNodes::PortIndex port) override; + + void setInData(std::shared_ptr value, int index) override; + + QtNodes::NodeValidationState validationState() const override; + QString validationMessage() const override; + + private: + bool ComputePreview(QPixmap& pixmap) override; + void UpdateOutput(); + + std::array, ComponentCount> m_inputs; + std::shared_ptr m_output; +}; + +using Vec2Composition = VecComposition<2>; +using Vec3Composition = VecComposition<3>; +using Vec4Composition = VecComposition<4>; + +#include + +#endif diff --git a/src/ShaderNode/DataModels/VecComposition.inl b/src/ShaderNode/DataModels/VecComposition.inl new file mode 100644 index 000000000..9f17da698 --- /dev/null +++ b/src/ShaderNode/DataModels/VecComposition.inl @@ -0,0 +1,192 @@ +#include +#include +#include +#include +#include + +template +VecComposition::VecComposition(ShaderGraph& graph) : +ShaderNode(graph) +{ + static_assert(ComponentCount <= s_vectorComponents.size()); + + m_output = std::make_shared(ComponentCount); +} + +template +Nz::ShaderNodes::NodePtr VecComposition::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +{ + assert(count == ComponentCount); + assert(outputIndex == 0); + + std::array expr; + for (std::size_t i = 0; i < count; ++i) + expr[i] = expressions[i]; + + constexpr auto ExpressionType = VecExpressionType; + return Nz::ShaderBuilder::Cast(expr.data(), expr.size()); +} + +template +QString VecComposition::caption() const +{ + static QString caption = "Compose Vector" + QString::number(ComponentCount); + return caption; +} + +template +QString VecComposition::name() const +{ + static QString name = "vec_compose" + QString::number(ComponentCount); + return name; +} + +template +QtNodes::NodeDataType VecComposition::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const +{ + switch (portType) + { + case QtNodes::PortType::In: + { + assert(portIndex >= 0); + assert(portIndex < ComponentCount); + return FloatData::Type(); + } + + case QtNodes::PortType::Out: + { + assert(portIndex == 0); + return VecData::Type(); + } + + default: break; + } + + assert(false); + throw std::runtime_error("Invalid port type"); +} + +template +unsigned int VecComposition::nPorts(QtNodes::PortType portType) const +{ + switch (portType) + { + case QtNodes::PortType::In: return ComponentCount; + case QtNodes::PortType::Out: return 1; + + default: break; + } + + assert(false); + throw std::runtime_error("Invalid port type"); +} + +template +std::shared_ptr VecComposition::outData(QtNodes::PortIndex port) +{ + assert(port == 0); + + if (validationState() != QtNodes::NodeValidationState::Valid) + return nullptr; + + return m_output; +} + +template +void VecComposition::setInData(std::shared_ptr value, int index) +{ + assert(index >= 0 && index < ComponentCount); + + if (value && value->type().id == FloatData::Type().id) + { + assert(dynamic_cast(value.get()) != nullptr); + m_inputs[index] = std::static_pointer_cast(value); + } + else + m_inputs[index].reset(); + + UpdateOutput(); +} + +template +QtNodes::NodeValidationState VecComposition::validationState() const +{ + for (std::size_t i = 0; i < ComponentCount; ++i) + { + if (!m_inputs[i]) + return QtNodes::NodeValidationState::Error; + } + + return QtNodes::NodeValidationState::Valid; +} + +template +QString VecComposition::validationMessage() const +{ + for (std::size_t i = 0; i < ComponentCount; ++i) + { + if (!m_inputs[i]) + return "Missing input #" + QString::number(i + 1); + } + + return QString(); +} + +template +bool VecComposition::ComputePreview(QPixmap& pixmap) +{ + if (validationState() != QtNodes::NodeValidationState::Valid) + return false; + + pixmap = QPixmap::fromImage(m_output->preview.GenerateImage()); + return true; +} + +template +void VecComposition::UpdateOutput() +{ + if (validationState() != QtNodes::NodeValidationState::Valid) + { + m_output->preview = PreviewValues(1, 1); + m_output->preview(0, 0) = Nz::Vector4f::Zero(); + return; + } + + std::array previewResized; + std::size_t maxInputWidth = 0; + std::size_t maxInputHeight = 0; + + for (std::size_t i = 0; i < ComponentCount; ++i) + { + // FIXME: Prevent useless copy + previewResized[i] = m_inputs[i]->preview; + + maxInputWidth = std::max(maxInputWidth, previewResized[i].GetWidth()); + maxInputHeight = std::max(maxInputHeight, previewResized[i].GetHeight()); + } + + PreviewValues& output = m_output->preview; + output = PreviewValues(maxInputWidth, maxInputHeight); + + for (std::size_t i = 0; i < ComponentCount; ++i) + { + if (previewResized[i].GetWidth() != maxInputWidth || previewResized[i].GetHeight() != maxInputHeight) + previewResized[i] = previewResized[i].Resized(maxInputWidth, maxInputHeight); + } + + for (std::size_t y = 0; y < maxInputHeight; ++y) + { + for (std::size_t x = 0; x < maxInputWidth; ++x) + { + Nz::Vector4f color(0.f, 0.f, 0.f, 1.f); + for (std::size_t i = 0; i < ComponentCount; ++i) + color[i] = previewResized[i](x, y)[0]; + + output(x, y) = color; + } + } + + Q_EMIT dataUpdated(0); + + UpdatePreview(); +} diff --git a/src/ShaderNode/DataModels/VecDecomposition.cpp b/src/ShaderNode/DataModels/VecDecomposition.cpp new file mode 100644 index 000000000..df69df8e6 --- /dev/null +++ b/src/ShaderNode/DataModels/VecDecomposition.cpp @@ -0,0 +1,176 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +VecDecomposition::VecDecomposition(ShaderGraph& graph) : +ShaderNode(graph) +{ + DisablePreview(); + DisableCustomVariableName(); +} + +Nz::ShaderNodes::NodePtr VecDecomposition::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +{ + assert(count == 1); + assert(outputIndex < m_outputs.size()); + + using namespace Nz::ShaderBuilder; + using namespace Nz::ShaderNodes; + + return Nz::ShaderBuilder::Swizzle(expressions[0], static_cast(Nz::UnderlyingCast(SwizzleComponent::First) + outputIndex)); +} + +QString VecDecomposition::caption() const +{ + return "Vector decomposition"; +} + +QString VecDecomposition::name() const +{ + return "vec_decompose"; +} + +QtNodes::NodeDataType VecDecomposition::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const +{ + switch (portType) + { + case QtNodes::PortType::In: + { + assert(portIndex == 0); + return VecData::Type(); + } + + case QtNodes::PortType::Out: + { + assert(portIndex >= 0 && portIndex < m_outputs.size()); + return FloatData::Type(); + } + + default: + break; + } + + assert(false); + throw std::runtime_error("Invalid port type"); +} + +unsigned int VecDecomposition::nPorts(QtNodes::PortType portType) const +{ + switch (portType) + { + case QtNodes::PortType::In: return 1; + case QtNodes::PortType::Out: return m_outputs.size(); + + default: + break; + } + + assert(false); + throw std::runtime_error("Invalid port type"); +} + +QString VecDecomposition::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const +{ + assert(portType == QtNodes::PortType::Out); + assert(portIndex >= 0 && portIndex < s_vectorComponents.size()); + + return QString(QChar(s_vectorComponents[portIndex])); +} + +bool VecDecomposition::portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const +{ + switch (portType) + { + case QtNodes::PortType::In: return false; + case QtNodes::PortType::Out: return true; + + default: + break; + } + + assert(false); + throw std::runtime_error("Invalid port type"); +} + +std::shared_ptr VecDecomposition::outData(QtNodes::PortIndex port) +{ + if (!m_input) + return {}; + + return m_outputs[port]; +} + +void VecDecomposition::setInData(std::shared_ptr value, int index) +{ + assert(index == 0); + + std::shared_ptr castedValue; + if (value && value->type().id == VecData::Type().id) + castedValue = std::static_pointer_cast(value); + + m_input = std::move(castedValue); + + UpdateOutputs(); +} + +QtNodes::NodeValidationState VecDecomposition::validationState() const +{ + if (!m_input) + return QtNodes::NodeValidationState::Error; + + return QtNodes::NodeValidationState::Valid; +} + +QString VecDecomposition::validationMessage() const +{ + if (!m_input) + return "Missing input"; + + return QString(); +} + +void VecDecomposition::UpdateOutputs() +{ + if (validationState() != QtNodes::NodeValidationState::Valid) + { + auto dummy = std::make_shared(); + dummy->preview = PreviewValues(1, 1); + dummy->preview.Fill(Nz::Vector4f::Zero()); + + m_outputs.fill(dummy); + return; + } + + std::size_t previewWidth = m_input->preview.GetWidth(); + std::size_t previewHeight = m_input->preview.GetHeight(); + std::size_t pixelCount = previewWidth * previewHeight; + + for (std::size_t i = 0; i < m_input->componentCount; ++i) + { + m_outputs[i] = std::make_shared(); + m_outputs[i]->preview = PreviewValues(previewWidth, previewHeight); + + const Nz::Vector4f* inputData = m_input->preview.GetData(); + Nz::Vector4f* outputData = m_outputs[i]->preview.GetData(); + for (std::size_t j = 0; j < pixelCount; ++j) + { + const Nz::Vector4f& input = *inputData++; + + *outputData++ = Nz::Vector4f(input[i], input[i], input[i], input[i]); + } + + Q_EMIT dataUpdated(i); + } + + for (std::size_t i = m_input->componentCount; i < m_outputs.size(); ++i) + m_outputs[i] = nullptr; + + UpdatePreview(); +} diff --git a/src/ShaderNode/DataModels/VecDecomposition.hpp b/src/ShaderNode/DataModels/VecDecomposition.hpp new file mode 100644 index 000000000..c50c95f40 --- /dev/null +++ b/src/ShaderNode/DataModels/VecDecomposition.hpp @@ -0,0 +1,48 @@ +#pragma once + +#ifndef NAZARA_SHADERNODES_VECTOR_DECOMPOSITION_HPP +#define NAZARA_SHADERNODES_VECTOR_DECOMPOSITION_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +class VecDecomposition : public ShaderNode +{ + public: + VecDecomposition(ShaderGraph& graph); + ~VecDecomposition() = default; + + Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + + QString caption() const override; + QString name() const override; + + QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; + unsigned int nPorts(QtNodes::PortType portType) const override; + + QString portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; + bool portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; + + std::shared_ptr outData(QtNodes::PortIndex port) override; + + void setInData(std::shared_ptr value, int index) override; + + QtNodes::NodeValidationState validationState() const override; + QString validationMessage() const override; + + private: + void UpdateOutputs(); + + std::shared_ptr m_input; + std::array, 4> m_outputs; +}; + +#include + +#endif diff --git a/src/ShaderNode/DataModels/Cast.cpp b/src/ShaderNode/DataModels/VecDecomposition.inl similarity index 100% rename from src/ShaderNode/DataModels/Cast.cpp rename to src/ShaderNode/DataModels/VecDecomposition.inl diff --git a/src/ShaderNode/DataModels/VecDot.cpp b/src/ShaderNode/DataModels/VecDot.cpp index 516e1b19b..e327cf06b 100644 --- a/src/ShaderNode/DataModels/VecDot.cpp +++ b/src/ShaderNode/DataModels/VecDot.cpp @@ -8,9 +8,11 @@ ShaderNode(graph) UpdateOutput(); } -Nz::ShaderNodes::ExpressionPtr VecDot::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const +Nz::ShaderNodes::NodePtr VecDot::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == 2); + assert(outputIndex == 0); + using namespace Nz::ShaderNodes; return IntrinsicCall::Build(IntrinsicType::DotProduct, { expressions[0], expressions[1] }); } diff --git a/src/ShaderNode/DataModels/VecDot.hpp b/src/ShaderNode/DataModels/VecDot.hpp index 74e6a7266..251694ae8 100644 --- a/src/ShaderNode/DataModels/VecDot.hpp +++ b/src/ShaderNode/DataModels/VecDot.hpp @@ -13,7 +13,7 @@ class VecDot : public ShaderNode VecDot(ShaderGraph& graph); ~VecDot() = default; - Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override; + Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override; QString name() const override; diff --git a/src/ShaderNode/DataModels/VecFloatMul.cpp b/src/ShaderNode/DataModels/VecFloatMul.cpp index 06ee951c6..33237dc25 100644 --- a/src/ShaderNode/DataModels/VecFloatMul.cpp +++ b/src/ShaderNode/DataModels/VecFloatMul.cpp @@ -7,9 +7,11 @@ ShaderNode(graph) UpdateOutput(); } -Nz::ShaderNodes::ExpressionPtr VecFloatMul::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const +Nz::ShaderNodes::NodePtr VecFloatMul::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == 2); + assert(outputIndex == 0); + using namespace Nz::ShaderNodes; return BinaryOp::Build(BinaryType::Multiply, expressions[0], expressions[1]); } diff --git a/src/ShaderNode/DataModels/VecFloatMul.hpp b/src/ShaderNode/DataModels/VecFloatMul.hpp index dd1fbd1af..b7759d4c7 100644 --- a/src/ShaderNode/DataModels/VecFloatMul.hpp +++ b/src/ShaderNode/DataModels/VecFloatMul.hpp @@ -13,7 +13,7 @@ class VecFloatMul : public ShaderNode VecFloatMul(ShaderGraph& graph); ~VecFloatMul() = default; - Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override; + Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override; QString name() const override; diff --git a/src/ShaderNode/DataModels/VecValue.cpp b/src/ShaderNode/DataModels/VecValue.cpp deleted file mode 100644 index ede5bdfac..000000000 --- a/src/ShaderNode/DataModels/VecValue.cpp +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/src/ShaderNode/DataModels/VecValue.hpp b/src/ShaderNode/DataModels/VecValue.hpp index 86cd93692..3fcebb638 100644 --- a/src/ShaderNode/DataModels/VecValue.hpp +++ b/src/ShaderNode/DataModels/VecValue.hpp @@ -18,6 +18,9 @@ class VecValue : public ShaderNode VecValue(ShaderGraph& graph); ~VecValue() = default; + Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + void BuildNodeEdition(QFormLayout* layout) override; + QString caption() const override; QString name() const override; @@ -27,9 +30,8 @@ class VecValue : public ShaderNode std::shared_ptr outData(QtNodes::PortIndex port) override; - void BuildNodeEdition(QFormLayout* layout) override; - - Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override; + QString portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; + bool portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override; private: bool ComputePreview(QPixmap& pixmap) override; diff --git a/src/ShaderNode/DataModels/VecValue.inl b/src/ShaderNode/DataModels/VecValue.inl index b07c46a9b..ef5ad0622 100644 --- a/src/ShaderNode/DataModels/VecValue.inl +++ b/src/ShaderNode/DataModels/VecValue.inl @@ -75,6 +75,33 @@ std::shared_ptr VecValue::outData(QtNodes::Po return out; } +template +QString VecValue::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const +{ + assert(portIndex == 0); + assert(portType == QtNodes::PortType::Out); + + QString caption = "vec" + QString::number(ComponentCount) + "("; + for (std::size_t i = 0; i < ComponentCount; ++i) + { + if (i > 0) + caption += ", "; + + caption += QString::number(m_value[i]); + } + + caption += ")"; + + return caption; +} + +template +bool VecValue::portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const +{ + assert(portIndex == 0); + return portType == QtNodes::PortType::Out; +} + template void VecValue::BuildNodeEdition(QFormLayout* layout) { @@ -100,9 +127,10 @@ void VecValue::BuildNodeEdition(QFormLayout* layout) } template -Nz::ShaderNodes::ExpressionPtr VecValue::GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const +Nz::ShaderNodes::NodePtr VecValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count, std::size_t outputIndex) const { assert(count == 0); + assert(outputIndex == 0); return Nz::ShaderBuilder::Constant(m_value); } diff --git a/src/ShaderNode/ShaderGraph.cpp b/src/ShaderNode/ShaderGraph.cpp index c0c575493..d385b098d 100644 --- a/src/ShaderNode/ShaderGraph.cpp +++ b/src/ShaderNode/ShaderGraph.cpp @@ -1,19 +1,23 @@ #include #include +#include +#include #include #include +#include #include #include #include #include +#include +#include #include +#include #include #include #include -#include -#include -#include -#include +#include +#include #include #include #include @@ -61,27 +65,6 @@ m_type(ShaderType::NotSet) AddInput("UV", PrimitiveType::Float2, InputRole::TexCoord, 0, 0); AddOutput("RenderTarget0", PrimitiveType::Float4, 0); AddTexture("Potato", TextureType::Sampler2D, 1); - AddStruct("TestStruct", { - { - { "position", PrimitiveType::Float3 }, - { "normal", PrimitiveType::Float3 }, - { "uv", PrimitiveType::Float2 }, - { "inner", 2 } - } - }); - AddStruct("InnerStruct", { - { - { "a", PrimitiveType::Float3 }, - } - }); - AddStruct("OuterStruct", { - { - { "a", 1 }, - { "b", PrimitiveType::Float1 } - } - }); - - AddBuffer("testUBO", BufferType::UniformBufferObject, 0, 0); UpdateTexturePreview(0, QImage(R"(C:\Users\Lynix\Pictures\potatavril.png)")); @@ -460,23 +443,30 @@ QJsonObject ShaderGraph::Save() Nz::ShaderNodes::StatementPtr ShaderGraph::ToAst() { std::vector statements; - QHash usageCount; - std::function DetectVariables; - DetectVariables = [&](QtNodes::Node* node) + using Key = QPair; + auto BuildKey = [](QUuid uuid, std::size_t index) { - auto it = usageCount.find(node->id()); + return Key(uuid, index); + }; + + QHash usageCount; + + std::function DetectVariables; + DetectVariables = [&](QtNodes::Node* node, std::size_t outputIndex) + { + auto it = usageCount.find(BuildKey(node->id(), outputIndex)); if (it == usageCount.end()) { for (const auto& connectionSet : node->nodeState().getEntries(QtNodes::PortType::In)) { for (const auto& [uuid, conn] : connectionSet) { - DetectVariables(conn->getNode(QtNodes::PortType::Out)); + DetectVariables(conn->getNode(QtNodes::PortType::Out), conn->getPortIndex(QtNodes::PortType::Out)); } } - it = usageCount.insert(node->id(), 0); + it = usageCount.insert(BuildKey(node->id(), outputIndex), 0); } (*it)++; @@ -488,28 +478,28 @@ Nz::ShaderNodes::StatementPtr ShaderGraph::ToAst() { if (node->nodeDataModel()->nPorts(QtNodes::PortType::Out) == 0) { - DetectVariables(node); + DetectVariables(node, 0); outputNodes.push_back(node); } }); - QHash variableExpressions; + QHash variableExpressions; unsigned int varCount = 0; std::unordered_set usedVariableNames; - std::function HandleNode; - HandleNode = [&](QtNodes::Node* node) -> Nz::ShaderNodes::ExpressionPtr + std::function HandleNode; + HandleNode = [&](QtNodes::Node* node, std::size_t portIndex) -> Nz::ShaderNodes::NodePtr { ShaderNode* shaderNode = static_cast(node->nodeDataModel()); if (shaderNode->validationState() != QtNodes::NodeValidationState::Valid) throw std::runtime_error(shaderNode->validationMessage().toStdString()); qDebug() << shaderNode->name() << node->id(); - if (auto it = variableExpressions.find(node->id()); it != variableExpressions.end()) + if (auto it = variableExpressions.find(BuildKey(node->id(), portIndex)); it != variableExpressions.end()) return *it; - auto it = usageCount.find(node->id()); + auto it = usageCount.find(BuildKey(node->id(), portIndex)); assert(it != usageCount.end()); std::size_t inputCount = shaderNode->nPorts(QtNodes::PortType::In); @@ -521,16 +511,25 @@ Nz::ShaderNodes::StatementPtr ShaderGraph::ToAst() for (const auto& [uuid, conn] : connectionSet) { assert(i < expressions.size()); - expressions[i] = HandleNode(conn->getNode(QtNodes::PortType::Out)); + Nz::ShaderNodes::NodePtr inputNode = HandleNode(conn->getNode(QtNodes::PortType::Out), conn->getPortIndex(QtNodes::PortType::Out)); + if (inputNode->IsStatement()) + throw std::runtime_error("unexpected statement"); + + expressions[i] = std::static_pointer_cast(inputNode); i++; } } - auto expression = shaderNode->GetExpression(expressions.data(), expressions.size()); + auto astNode = shaderNode->BuildNode(expressions.data(), expressions.size(), portIndex); const std::string& variableName = shaderNode->GetVariableName(); if (*it > 1 || !variableName.empty()) { + if (astNode->IsStatement()) + throw std::runtime_error("unexpected statement"); + + auto expression = std::static_pointer_cast(astNode); + Nz::ShaderNodes::ExpressionPtr varExpression; if (expression->GetExpressionCategory() == Nz::ShaderNodes::ExpressionCategory::RValue) { @@ -546,23 +545,37 @@ Nz::ShaderNodes::StatementPtr ShaderGraph::ToAst() usedVariableNames.insert(name); auto variable = Nz::ShaderBuilder::Local(std::move(name), expression->GetExpressionType()); - statements.emplace_back(Nz::ShaderBuilder::DeclareVariable(variable, expression)); + statements.emplace_back(Nz::ShaderBuilder::DeclareVariable(variable, std::move(expression))); varExpression = Nz::ShaderBuilder::Identifier(variable); } else - varExpression = expression; + varExpression = std::move(expression); - variableExpressions.insert(node->id(), varExpression); + variableExpressions.insert(BuildKey(node->id(), portIndex), varExpression); return varExpression; } else - return expression; + return astNode; }; + std::sort(outputNodes.begin(), outputNodes.end(), [](QtNodes::Node* lhs, QtNodes::Node* rhs) + { + ShaderNode* leftNode = static_cast(lhs->nodeDataModel()); + ShaderNode* rightNode = static_cast(rhs->nodeDataModel()); + + return leftNode->GetOutputOrder() < rightNode->GetOutputOrder(); + }); + for (QtNodes::Node* node : outputNodes) - statements.emplace_back(Nz::ShaderBuilder::ExprStatement(HandleNode(node))); + { + auto astNode = HandleNode(node, 0); + if (!astNode->IsStatement()) + statements.emplace_back(Nz::ShaderBuilder::ExprStatement(std::static_pointer_cast(astNode))); + else + statements.emplace_back(std::static_pointer_cast(astNode)); + } return Nz::ShaderNodes::StatementBlock::Build(std::move(statements)); } @@ -738,31 +751,74 @@ Nz::ShaderStageType ShaderGraph::ToShaderStageType(ShaderType type) std::shared_ptr ShaderGraph::BuildRegistry() { auto registry = std::make_shared(); - RegisterShaderNode(*this, registry, "Inputs"); + + // Casts RegisterShaderNode(*this, registry, "Casts"); RegisterShaderNode(*this, registry, "Casts"); RegisterShaderNode(*this, registry, "Casts"); - RegisterShaderNode(*this, registry, "Shader"); - RegisterShaderNode(*this, registry, "Outputs"); + + // Constants + RegisterShaderNode(*this, registry, "Constants"); RegisterShaderNode(*this, registry, "Constants"); + RegisterShaderNode(*this, registry, "Constants"); + RegisterShaderNode(*this, registry, "Constants"); + RegisterShaderNode(*this, registry, "Constants"); + + // Inputs + RegisterShaderNode(*this, registry, "Inputs"); RegisterShaderNode(*this, registry, "Inputs"); - RegisterShaderNode(*this, registry, "Outputs"); + + // Outputs + RegisterShaderNode(*this, registry, "Outputs"); RegisterShaderNode(*this, registry, "Outputs"); - RegisterShaderNode(*this, registry, "Texture"); - RegisterShaderNode(*this, registry, "Texture"); + RegisterShaderNode(*this, registry, "Outputs"); + + // Float comparison + RegisterShaderNode(*this, registry, "Float comparisons"); + RegisterShaderNode(*this, registry, "Float comparisons"); + RegisterShaderNode(*this, registry, "Float comparisons"); + RegisterShaderNode(*this, registry, "Float comparisons"); + RegisterShaderNode(*this, registry, "Float comparisons"); + RegisterShaderNode(*this, registry, "Float comparisons"); + + // Float operations + RegisterShaderNode(*this, registry, "Float operations"); + RegisterShaderNode(*this, registry, "Float operations"); + RegisterShaderNode(*this, registry, "Float operations"); + RegisterShaderNode(*this, registry, "Float operations"); + + // Matrix operations RegisterShaderNode(*this, registry, "Matrix operations"); RegisterShaderNode(*this, registry, "Matrix operations"); RegisterShaderNode(*this, registry, "Matrix operations"); RegisterShaderNode(*this, registry, "Matrix operations"); + + // Shader + RegisterShaderNode(*this, registry, "Shader"); + + // Texture + RegisterShaderNode(*this, registry, "Texture"); + RegisterShaderNode(*this, registry, "Texture"); + + // Vector comparison + RegisterShaderNode(*this, registry, "Vector comparisons"); + RegisterShaderNode(*this, registry, "Vector comparisons"); + RegisterShaderNode(*this, registry, "Vector comparisons"); + RegisterShaderNode(*this, registry, "Vector comparisons"); + RegisterShaderNode(*this, registry, "Vector comparisons"); + RegisterShaderNode(*this, registry, "Vector comparisons"); + + // Vector operations RegisterShaderNode(*this, registry, "Vector operations"); + RegisterShaderNode(*this, registry, "Vector operations"); + RegisterShaderNode(*this, registry, "Vector operations"); + RegisterShaderNode(*this, registry, "Vector operations"); + RegisterShaderNode(*this, registry, "Vector operations"); RegisterShaderNode(*this, registry, "Vector operations"); RegisterShaderNode(*this, registry, "Vector operations"); RegisterShaderNode(*this, registry, "Vector operations"); RegisterShaderNode(*this, registry, "Vector operations"); RegisterShaderNode(*this, registry, "Vector operations"); - RegisterShaderNode(*this, registry, "Constants"); - RegisterShaderNode(*this, registry, "Constants"); - RegisterShaderNode(*this, registry, "Constants"); return registry; } diff --git a/src/ShaderNode/Widgets/ConditionEditor.cpp b/src/ShaderNode/Widgets/ConditionEditor.cpp index 2b8c40ab8..e16527254 100644 --- a/src/ShaderNode/Widgets/ConditionEditor.cpp +++ b/src/ShaderNode/Widgets/ConditionEditor.cpp @@ -112,6 +112,8 @@ void ConditionEditor::RefreshConditions() checkbox->setCheckable(true); checkbox->setCheckState((conditionEntry.enabled) ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); - m_model->setItem(rowIndex, 1, checkbox); + m_model->setItem(rowIndex, 1, checkbox); + + rowIndex++; } } diff --git a/src/ShaderNode/Widgets/MainWindow.cpp b/src/ShaderNode/Widgets/MainWindow.cpp index a9bfcc59f..aa01c3c97 100644 --- a/src/ShaderNode/Widgets/MainWindow.cpp +++ b/src/ShaderNode/Widgets/MainWindow.cpp @@ -184,10 +184,10 @@ void MainWindow::OnGenerateGLSL() Nz::GlslWriter writer; Nz::GlslWriter::States states; - for (const auto& condition : m_shaderGraph.GetConditions()) + for (std::size_t i = 0; i < m_shaderGraph.GetConditionCount(); ++i) { - if (condition.enabled) - states.enabledConditions.insert(condition.name); + if (m_shaderGraph.IsConditionEnabled(i)) + states.enabledConditions = Nz::SetBit(states.enabledConditions, i); } std::string glsl = writer.Generate(ToShader(), states); From ef1f4c770ab933be26399d5873fc6bb16d667546 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sun, 3 Jan 2021 10:48:30 +0100 Subject: [PATCH 025/278] Use a better texture for alpha-testing --- examples/GraphicsTest/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/GraphicsTest/main.cpp b/examples/GraphicsTest/main.cpp index 5e09b0b9f..3d2d6e202 100644 --- a/examples/GraphicsTest/main.cpp +++ b/examples/GraphicsTest/main.cpp @@ -76,7 +76,7 @@ int main() } // Texture (alpha-map) - Nz::ImageRef alphaImage = Nz::Image::LoadFromFile("alphatest.png"); + Nz::ImageRef alphaImage = Nz::Image::LoadFromFile("alphatile.png"); if (!alphaImage || !alphaImage->Convert(Nz::PixelFormat_RGBA8)) { NazaraError("Failed to load image"); From a801754f6e16dce8d306cdaee2b717f73a0ae2ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sun, 3 Jan 2021 10:48:47 +0100 Subject: [PATCH 026/278] Remove Material::EnableAlphaTest (superseded by conditions) --- include/Nazara/Graphics/BasicMaterial.inl | 14 +++++++++ include/Nazara/Graphics/Material.hpp | 1 - include/Nazara/Graphics/Material.inl | 30 -------------------- include/Nazara/Graphics/MaterialPipeline.hpp | 1 - include/Nazara/Graphics/MaterialPipeline.inl | 1 - 5 files changed, 14 insertions(+), 33 deletions(-) diff --git a/include/Nazara/Graphics/BasicMaterial.inl b/include/Nazara/Graphics/BasicMaterial.inl index 875dc4b8e..8eb32ff7f 100644 --- a/include/Nazara/Graphics/BasicMaterial.inl +++ b/include/Nazara/Graphics/BasicMaterial.inl @@ -9,6 +9,20 @@ namespace Nz { + /*! + * \brief Enable/Disable alpha test for this material + * + * When enabled, all objects using this material will be rendered using alpha testing, + * rejecting pixels if their alpha component is under a defined threshold. + * This allows some kind of transparency with a much cheaper cost as it doesn't prevent any optimization (as deferred rendering or batching). + * + * \param alphaTest Defines if this material will use alpha testing + * + * \remark Invalidates the pipeline + * + * \see IsAlphaTestEnabled + * \see SetAlphaThreshold + */ inline void BasicMaterial::EnableAlphaTest(bool alphaTest) { NazaraAssert(HasAlphaTest(), "Material has no alpha test condition"); diff --git a/include/Nazara/Graphics/Material.hpp b/include/Nazara/Graphics/Material.hpp index f3e58e271..93493ce14 100644 --- a/include/Nazara/Graphics/Material.hpp +++ b/include/Nazara/Graphics/Material.hpp @@ -38,7 +38,6 @@ namespace Nz inline void Configure(std::shared_ptr pipeline); inline void Configure(const MaterialPipelineInfo& pipelineInfo); - inline void EnableAlphaTest(bool alphaTest); inline void EnableBlending(bool blending); inline void EnableColorWrite(bool colorWrite); inline void EnableCondition(std::size_t conditionIndex, bool enable); diff --git a/include/Nazara/Graphics/Material.inl b/include/Nazara/Graphics/Material.inl index 8a2e56b15..036ad2b6e 100644 --- a/include/Nazara/Graphics/Material.inl +++ b/include/Nazara/Graphics/Material.inl @@ -53,27 +53,6 @@ namespace Nz InvalidatePipeline(); } - /*! - * \brief Enable/Disable alpha test for this material - * - * When enabled, all objects using this material will be rendered using alpha testing, - * rejecting pixels if their alpha component is under a defined threshold. - * This allows some kind of transparency with a much cheaper cost as it doesn't prevent any optimization (as deferred rendering or batching). - * - * \param alphaTest Defines if this material will use alpha testing - * - * \remark Invalidates the pipeline - * - * \see IsAlphaTestEnabled - * \see SetAlphaThreshold - */ - inline void Material::EnableAlphaTest(bool alphaTest) - { - m_pipelineInfo.alphaTest = alphaTest; - - InvalidatePipeline(); - } - /*! * \brief Enable/Disable blending for this material * @@ -489,15 +468,6 @@ namespace Nz return m_pipelineInfo.hasVertexColor; } - /*! - * \brief Checks whether this material has alpha test enabled - * \return true If it is the case - */ - inline bool Material::IsAlphaTestEnabled() const - { - return m_pipelineInfo.alphaTest; - } - /*! * \brief Checks whether this material has blending enabled * \return true If it is the case diff --git a/include/Nazara/Graphics/MaterialPipeline.hpp b/include/Nazara/Graphics/MaterialPipeline.hpp index 9e02828b1..951320269 100644 --- a/include/Nazara/Graphics/MaterialPipeline.hpp +++ b/include/Nazara/Graphics/MaterialPipeline.hpp @@ -27,7 +27,6 @@ namespace Nz Nz::UInt64 enabledConditions = 0; }; - bool alphaTest = false; bool depthSorting = false; bool hasVertexColor = false; bool reflectionMapping = false; diff --git a/include/Nazara/Graphics/MaterialPipeline.inl b/include/Nazara/Graphics/MaterialPipeline.inl index b83e6fc6b..0131b7153 100644 --- a/include/Nazara/Graphics/MaterialPipeline.inl +++ b/include/Nazara/Graphics/MaterialPipeline.inl @@ -76,7 +76,6 @@ namespace std #define NazaraPipelineMember(member) Nz::HashCombine(seed, pipelineInfo.member) #define NazaraPipelineBoolMember(member) parameterHash |= ((pipelineInfo.member) ? 1U : 0U) << (parameterIndex++) - NazaraPipelineBoolMember(alphaTest); NazaraPipelineBoolMember(depthSorting); NazaraPipelineBoolMember(hasVertexColor); NazaraPipelineBoolMember(reflectionMapping); From 079834ca6ac416dd1ad66c038c68d6f04f74804a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sun, 3 Jan 2021 10:52:02 +0100 Subject: [PATCH 027/278] Graphics/UberShader: Fix inline keyword --- include/Nazara/Graphics/UberShader.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/Nazara/Graphics/UberShader.hpp b/include/Nazara/Graphics/UberShader.hpp index ae8221199..a4b9299a2 100644 --- a/include/Nazara/Graphics/UberShader.hpp +++ b/include/Nazara/Graphics/UberShader.hpp @@ -20,7 +20,7 @@ namespace Nz class NAZARA_GRAPHICS_API UberShader { public: - inline UberShader(ShaderAst shaderAst); + UberShader(ShaderAst shaderAst); ~UberShader() = default; UInt64 GetConditionFlagByName(const std::string_view& condition) const; From 44bc86d08234596fa58ce707f328f1d90423440e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sun, 3 Jan 2021 11:11:54 +0100 Subject: [PATCH 028/278] Shader/SpirvWriter: Rename MergeBlocks to MergeSections to avoid confusion with SpirV blocks --- include/Nazara/Shader/SpirvWriter.hpp | 2 +- src/Nazara/Shader/SpirvWriter.cpp | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/Nazara/Shader/SpirvWriter.hpp b/include/Nazara/Shader/SpirvWriter.hpp index 86f3f156b..62227ea4e 100644 --- a/include/Nazara/Shader/SpirvWriter.hpp +++ b/include/Nazara/Shader/SpirvWriter.hpp @@ -84,7 +84,7 @@ namespace Nz void WriteLocalVariable(std::string name, UInt32 resultId); - static void MergeBlocks(std::vector& output, const SpirvSection& from); + static void MergeSections(std::vector& output, const SpirvSection& from); struct Context { diff --git a/src/Nazara/Shader/SpirvWriter.cpp b/src/Nazara/Shader/SpirvWriter.cpp index 535d53297..0e1af9c0b 100644 --- a/src/Nazara/Shader/SpirvWriter.cpp +++ b/src/Nazara/Shader/SpirvWriter.cpp @@ -461,11 +461,11 @@ namespace Nz state.header.Append(SpirvOp::OpExecutionMode, entryFunc.id, SpvExecutionModeOriginUpperLeft); std::vector ret; - MergeBlocks(ret, state.header); - MergeBlocks(ret, state.debugInfo); - MergeBlocks(ret, state.annotations); - MergeBlocks(ret, state.constants); - MergeBlocks(ret, state.instructions); + MergeSections(ret, state.header); + MergeSections(ret, state.debugInfo); + MergeSections(ret, state.annotations); + MergeSections(ret, state.constants); + MergeSections(ret, state.instructions); return ret; } @@ -675,7 +675,7 @@ namespace Nz m_currentState->varToResult.insert_or_assign(std::move(name), resultId); } - void SpirvWriter::MergeBlocks(std::vector& output, const SpirvSection& from) + void SpirvWriter::MergeSections(std::vector& output, const SpirvSection& from) { const std::vector& bytecode = from.GetBytecode(); From 4d63d6e02239eac5e59c2f3e664b4327eceaaaba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Mon, 4 Jan 2021 10:27:08 +0100 Subject: [PATCH 029/278] Shader: Add basic support for Branch node in spir-v --- include/Nazara/Shader/SpirvAstVisitor.hpp | 10 ++- include/Nazara/Shader/SpirvAstVisitor.inl | 4 +- include/Nazara/Shader/SpirvBlock.hpp | 38 ++++++++++ include/Nazara/Shader/SpirvBlock.inl | 22 ++++++ include/Nazara/Shader/SpirvExpressionLoad.hpp | 8 +- include/Nazara/Shader/SpirvExpressionLoad.inl | 3 +- .../Nazara/Shader/SpirvExpressionStore.hpp | 5 +- .../Nazara/Shader/SpirvExpressionStore.inl | 3 +- include/Nazara/Shader/SpirvSection.hpp | 13 ++-- include/Nazara/Shader/SpirvSection.inl | 15 +++- include/Nazara/Shader/SpirvWriter.hpp | 2 +- src/Nazara/Shader/SpirvAstVisitor.cpp | 73 ++++++++++++++++--- src/Nazara/Shader/SpirvConstantCache.cpp | 2 +- src/Nazara/Shader/SpirvExpressionLoad.cpp | 8 +- src/Nazara/Shader/SpirvExpressionStore.cpp | 6 +- src/Nazara/Shader/SpirvWriter.cpp | 22 +++--- 16 files changed, 186 insertions(+), 48 deletions(-) create mode 100644 include/Nazara/Shader/SpirvBlock.hpp create mode 100644 include/Nazara/Shader/SpirvBlock.inl diff --git a/include/Nazara/Shader/SpirvAstVisitor.hpp b/include/Nazara/Shader/SpirvAstVisitor.hpp index 91ad031ad..571af6cc5 100644 --- a/include/Nazara/Shader/SpirvAstVisitor.hpp +++ b/include/Nazara/Shader/SpirvAstVisitor.hpp @@ -4,13 +4,14 @@ #pragma once -#ifndef NAZARA_SPIRVEXPRESSIONLOAD_HPP -#define NAZARA_SPIRVEXPRESSIONLOAD_HPP +#ifndef NAZARA_SPIRVASTVISITOR_HPP +#define NAZARA_SPIRVASTVISITOR_HPP #include #include #include #include +#include #include namespace Nz @@ -20,7 +21,7 @@ namespace Nz class NAZARA_SHADER_API SpirvAstVisitor : public ShaderAstVisitorExcept { public: - inline SpirvAstVisitor(SpirvWriter& writer); + inline SpirvAstVisitor(SpirvWriter& writer, std::vector& blocks); SpirvAstVisitor(const SpirvAstVisitor&) = delete; SpirvAstVisitor(SpirvAstVisitor&&) = delete; ~SpirvAstVisitor() = default; @@ -31,6 +32,7 @@ namespace Nz void Visit(ShaderNodes::AccessMember& node) override; void Visit(ShaderNodes::AssignOp& node) override; void Visit(ShaderNodes::BinaryOp& node) override; + void Visit(ShaderNodes::Branch& node) override; void Visit(ShaderNodes::Cast& node) override; void Visit(ShaderNodes::ConditionalExpression& node) override; void Visit(ShaderNodes::ConditionalStatement& node) override; @@ -51,6 +53,8 @@ namespace Nz void PushResultId(UInt32 value); UInt32 PopResultId(); + SpirvBlock* m_currentBlock; + std::vector& m_blocks; std::vector m_resultIds; SpirvWriter& m_writer; }; diff --git a/include/Nazara/Shader/SpirvAstVisitor.inl b/include/Nazara/Shader/SpirvAstVisitor.inl index 87dc93a54..048f5768e 100644 --- a/include/Nazara/Shader/SpirvAstVisitor.inl +++ b/include/Nazara/Shader/SpirvAstVisitor.inl @@ -7,9 +7,11 @@ namespace Nz { - inline SpirvAstVisitor::SpirvAstVisitor(SpirvWriter& writer) : + inline SpirvAstVisitor::SpirvAstVisitor(SpirvWriter& writer, std::vector& blocks) : + m_blocks(blocks), m_writer(writer) { + m_currentBlock = &m_blocks.back(); } } diff --git a/include/Nazara/Shader/SpirvBlock.hpp b/include/Nazara/Shader/SpirvBlock.hpp new file mode 100644 index 000000000..5fbbe0843 --- /dev/null +++ b/include/Nazara/Shader/SpirvBlock.hpp @@ -0,0 +1,38 @@ +// 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_SPIRVBLOCK_HPP +#define NAZARA_SPIRVBLOCK_HPP + +#include +#include +#include +#include +#include + +namespace Nz +{ + class NAZARA_SHADER_API SpirvBlock : public SpirvSection + { + public: + inline SpirvBlock(SpirvWriter& writer); + SpirvBlock(const SpirvBlock&) = default; + SpirvBlock(SpirvBlock&&) = default; + ~SpirvBlock() = default; + + inline UInt32 GetLabelId() const; + + SpirvBlock& operator=(const SpirvBlock&) = delete; + SpirvBlock& operator=(SpirvBlock&&) = default; + + private: + UInt32 m_labelId; + }; +} + +#include + +#endif diff --git a/include/Nazara/Shader/SpirvBlock.inl b/include/Nazara/Shader/SpirvBlock.inl new file mode 100644 index 000000000..3ce1f3050 --- /dev/null +++ b/include/Nazara/Shader/SpirvBlock.inl @@ -0,0 +1,22 @@ +// 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 +#include + +namespace Nz +{ + inline SpirvBlock::SpirvBlock(SpirvWriter& writer) + { + m_labelId = writer.AllocateResultId(); + Append(SpirvOp::OpLabel, m_labelId); + } + + inline UInt32 SpirvBlock::GetLabelId() const + { + return m_labelId; + } +} + +#include diff --git a/include/Nazara/Shader/SpirvExpressionLoad.hpp b/include/Nazara/Shader/SpirvExpressionLoad.hpp index b237c720a..bb44bba71 100644 --- a/include/Nazara/Shader/SpirvExpressionLoad.hpp +++ b/include/Nazara/Shader/SpirvExpressionLoad.hpp @@ -4,8 +4,8 @@ #pragma once -#ifndef NAZARA_SPIRVEXPRESSIONLOADACCESSMEMBER_HPP -#define NAZARA_SPIRVEXPRESSIONLOADACCESSMEMBER_HPP +#ifndef NAZARA_SPIRVEXPRESSIONLOAD_HPP +#define NAZARA_SPIRVEXPRESSIONLOAD_HPP #include #include @@ -16,12 +16,13 @@ namespace Nz { + class SpirvBlock; class SpirvWriter; class NAZARA_SHADER_API SpirvExpressionLoad : public ShaderAstVisitorExcept, public ShaderVarVisitorExcept { public: - inline SpirvExpressionLoad(SpirvWriter& writer); + inline SpirvExpressionLoad(SpirvWriter& writer, SpirvBlock& block); SpirvExpressionLoad(const SpirvExpressionLoad&) = delete; SpirvExpressionLoad(SpirvExpressionLoad&&) = delete; ~SpirvExpressionLoad() = default; @@ -53,6 +54,7 @@ namespace Nz UInt32 resultId; }; + SpirvBlock& m_block; SpirvWriter& m_writer; std::variant m_value; }; diff --git a/include/Nazara/Shader/SpirvExpressionLoad.inl b/include/Nazara/Shader/SpirvExpressionLoad.inl index 966aae912..6d5aff9cb 100644 --- a/include/Nazara/Shader/SpirvExpressionLoad.inl +++ b/include/Nazara/Shader/SpirvExpressionLoad.inl @@ -7,7 +7,8 @@ namespace Nz { - inline SpirvExpressionLoad::SpirvExpressionLoad(SpirvWriter& writer) : + inline SpirvExpressionLoad::SpirvExpressionLoad(SpirvWriter& writer, SpirvBlock& block) : + m_block(block), m_writer(writer) { } diff --git a/include/Nazara/Shader/SpirvExpressionStore.hpp b/include/Nazara/Shader/SpirvExpressionStore.hpp index d7d37e39d..26c2b5f48 100644 --- a/include/Nazara/Shader/SpirvExpressionStore.hpp +++ b/include/Nazara/Shader/SpirvExpressionStore.hpp @@ -15,13 +15,13 @@ namespace Nz { - class SpirvSection; + class SpirvBlock; class SpirvWriter; class NAZARA_SHADER_API SpirvExpressionStore : public ShaderAstVisitorExcept, public ShaderVarVisitorExcept { public: - inline SpirvExpressionStore(SpirvWriter& writer); + inline SpirvExpressionStore(SpirvWriter& writer, SpirvBlock& block); SpirvExpressionStore(const SpirvExpressionStore&) = delete; SpirvExpressionStore(SpirvExpressionStore&&) = delete; ~SpirvExpressionStore() = default; @@ -53,6 +53,7 @@ namespace Nz UInt32 resultId; }; + SpirvBlock& m_block; SpirvWriter& m_writer; std::variant m_value; }; diff --git a/include/Nazara/Shader/SpirvExpressionStore.inl b/include/Nazara/Shader/SpirvExpressionStore.inl index 558a2aee8..771624788 100644 --- a/include/Nazara/Shader/SpirvExpressionStore.inl +++ b/include/Nazara/Shader/SpirvExpressionStore.inl @@ -7,7 +7,8 @@ namespace Nz { - inline SpirvExpressionStore::SpirvExpressionStore(SpirvWriter& writer) : + inline SpirvExpressionStore::SpirvExpressionStore(SpirvWriter& writer, SpirvBlock& block) : + m_block(block), m_writer(writer) { } diff --git a/include/Nazara/Shader/SpirvSection.hpp b/include/Nazara/Shader/SpirvSection.hpp index b116b212f..b759cbe2e 100644 --- a/include/Nazara/Shader/SpirvSection.hpp +++ b/include/Nazara/Shader/SpirvSection.hpp @@ -22,8 +22,8 @@ namespace Nz struct Raw; SpirvSection() = default; - SpirvSection(const SpirvSection& cache) = default; - SpirvSection(SpirvSection&& cache) = default; + SpirvSection(const SpirvSection&) = default; + SpirvSection(SpirvSection&&) = default; ~SpirvSection() = default; inline std::size_t Append(const char* str); @@ -35,20 +35,21 @@ namespace Nz inline std::size_t Append(std::initializer_list codepoints); template std::size_t Append(SpirvOp opcode, const Args&... args); template std::size_t AppendVariadic(SpirvOp opcode, F&& callback); - template std::size_t Append(T value); + inline std::size_t Append(const SpirvSection& section); + template || std::is_enum_v>> std::size_t Append(T value); inline unsigned int CountWord(const char* str); inline unsigned int CountWord(const std::string_view& str); inline unsigned int CountWord(const std::string& str); inline unsigned int CountWord(const Raw& raw); - template unsigned int CountWord(const T& value); + template || std::is_enum_v>> unsigned int CountWord(const T& value); template unsigned int CountWord(const T1& value, const T2& value2, const Args&... rest); inline const std::vector& GetBytecode() const; inline std::size_t GetOutputOffset() const; - SpirvSection& operator=(const SpirvSection& cache) = delete; - SpirvSection& operator=(SpirvSection&& cache) = default; + SpirvSection& operator=(const SpirvSection&) = delete; + SpirvSection& operator=(SpirvSection&&) = default; struct OpSize { diff --git a/include/Nazara/Shader/SpirvSection.inl b/include/Nazara/Shader/SpirvSection.inl index e86eb59ff..e6a400d06 100644 --- a/include/Nazara/Shader/SpirvSection.inl +++ b/include/Nazara/Shader/SpirvSection.inl @@ -61,6 +61,17 @@ namespace Nz return offset; } + inline std::size_t SpirvSection::Append(const SpirvSection& section) + { + const std::vector& bytecode = section.GetBytecode(); + + std::size_t offset = GetOutputOffset(); + m_bytecode.resize(offset + bytecode.size()); + std::copy(bytecode.begin(), bytecode.end(), m_bytecode.begin() + offset); + + return offset; + } + template std::size_t SpirvSection::Append(SpirvOp opcode, const Args&... args) { @@ -89,13 +100,13 @@ namespace Nz return offset; } - template + template std::size_t SpirvSection::Append(T value) { return Append(static_cast(value)); } - template + template unsigned int SpirvSection::CountWord(const T& /*value*/) { return 1; diff --git a/include/Nazara/Shader/SpirvWriter.hpp b/include/Nazara/Shader/SpirvWriter.hpp index 62227ea4e..37ebc6ea0 100644 --- a/include/Nazara/Shader/SpirvWriter.hpp +++ b/include/Nazara/Shader/SpirvWriter.hpp @@ -26,6 +26,7 @@ namespace Nz class NAZARA_SHADER_API SpirvWriter : public ShaderWriter { friend class SpirvAstVisitor; + friend class SpirvBlock; friend class SpirvExpressionLoad; friend class SpirvExpressionStore; friend class SpirvVisitor; @@ -62,7 +63,6 @@ namespace Nz const ExtVar& GetInputVariable(const std::string& name) const; const ExtVar& GetOutputVariable(const std::string& name) const; const ExtVar& GetUniformVariable(const std::string& name) const; - SpirvSection& GetInstructions(); UInt32 GetPointerTypeId(const ShaderExpressionType& type, SpirvStorageClass storageClass) const; UInt32 GetTypeId(const ShaderExpressionType& type) const; diff --git a/src/Nazara/Shader/SpirvAstVisitor.cpp b/src/Nazara/Shader/SpirvAstVisitor.cpp index e012d6de3..f76c8807c 100644 --- a/src/Nazara/Shader/SpirvAstVisitor.cpp +++ b/src/Nazara/Shader/SpirvAstVisitor.cpp @@ -22,7 +22,7 @@ namespace Nz void SpirvAstVisitor::Visit(ShaderNodes::AccessMember& node) { - SpirvExpressionLoad accessMemberVisitor(m_writer); + SpirvExpressionLoad accessMemberVisitor(m_writer, *m_currentBlock); PushResultId(accessMemberVisitor.Evaluate(node)); } @@ -30,7 +30,7 @@ namespace Nz { UInt32 resultId = EvaluateExpression(node.right); - SpirvExpressionStore storeVisitor(m_writer); + SpirvExpressionStore storeVisitor(m_writer, *m_currentBlock); storeVisitor.Store(node.left, resultId); PushResultId(resultId); @@ -438,10 +438,63 @@ namespace Nz if (swapOperands) std::swap(leftOperand, rightOperand); - m_writer.GetInstructions().Append(op, m_writer.GetTypeId(resultType), resultId, leftOperand, rightOperand); + m_currentBlock->Append(op, m_writer.GetTypeId(resultType), resultId, leftOperand, rightOperand); PushResultId(resultId); } + void SpirvAstVisitor::Visit(ShaderNodes::Branch& node) + { + assert(!node.condStatements.empty()); + auto& firstCond = node.condStatements.front(); + + UInt32 previousConditionId = EvaluateExpression(firstCond.condition); + SpirvBlock previousContentBlock(m_writer); + m_currentBlock = &previousContentBlock; + Visit(firstCond.statement); + + std::optional nextBlock; + for (std::size_t statementIndex = 1; statementIndex < node.condStatements.size(); ++statementIndex) + { + const auto& statement = node.condStatements[statementIndex]; + + SpirvBlock contentBlock(m_writer); + + m_blocks.back().Append(SpirvOp::OpBranchConditional, previousConditionId, previousContentBlock.GetLabelId(), contentBlock.GetLabelId()); + + previousConditionId = EvaluateExpression(statement.condition); + m_blocks.emplace_back(std::move(previousContentBlock)); + previousContentBlock = std::move(contentBlock); + + m_currentBlock = &previousContentBlock; + Visit(statement.statement); + } + + SpirvBlock mergeBlock(m_writer); + + if (node.elseStatement) + { + SpirvBlock elseBlock(m_writer); + + m_currentBlock = &elseBlock; + Visit(node.elseStatement); + + elseBlock.Append(SpirvOp::OpBranch, mergeBlock.GetLabelId()); //< FIXME: Shouldn't terminate twice + + m_blocks.back().Append(SpirvOp::OpBranchConditional, previousConditionId, previousContentBlock.GetLabelId(), elseBlock.GetLabelId()); + m_blocks.emplace_back(std::move(previousContentBlock)); + m_blocks.emplace_back(std::move(elseBlock)); + } + else + { + m_blocks.back().Append(SpirvOp::OpBranchConditional, previousConditionId, previousContentBlock.GetLabelId(), mergeBlock.GetLabelId()); + m_blocks.emplace_back(std::move(previousContentBlock)); + } + + m_blocks.emplace_back(std::move(mergeBlock)); + + m_currentBlock = &m_blocks.back(); + } + void SpirvAstVisitor::Visit(ShaderNodes::Cast& node) { const ShaderExpressionType& targetExprType = node.exprType; @@ -461,7 +514,7 @@ namespace Nz UInt32 resultId = m_writer.AllocateResultId(); - m_writer.GetInstructions().AppendVariadic(SpirvOp::OpCompositeConstruct, [&](const auto& appender) + m_currentBlock->AppendVariadic(SpirvOp::OpCompositeConstruct, [&](const auto& appender) { appender(m_writer.GetTypeId(targetType)); appender(resultId); @@ -508,7 +561,7 @@ namespace Nz void SpirvAstVisitor::Visit(ShaderNodes::Discard& /*node*/) { - m_writer.GetInstructions().Append(SpirvOp::OpKill); + m_currentBlock->Append(SpirvOp::OpKill); } void SpirvAstVisitor::Visit(ShaderNodes::ExpressionStatement& node) @@ -519,7 +572,7 @@ namespace Nz void SpirvAstVisitor::Visit(ShaderNodes::Identifier& node) { - SpirvExpressionLoad loadVisitor(m_writer); + SpirvExpressionLoad loadVisitor(m_writer, *m_currentBlock); PushResultId(loadVisitor.Evaluate(node)); } @@ -541,7 +594,7 @@ namespace Nz UInt32 resultId = m_writer.AllocateResultId(); - m_writer.GetInstructions().Append(SpirvOp::OpDot, typeId, resultId, vec1, vec2); + m_currentBlock->Append(SpirvOp::OpDot, typeId, resultId, vec1, vec2); PushResultId(resultId); break; } @@ -560,7 +613,7 @@ namespace Nz UInt32 coordinatesId = EvaluateExpression(node.coordinates); UInt32 resultId = m_writer.AllocateResultId(); - m_writer.GetInstructions().Append(SpirvOp::OpImageSampleImplicitLod, typeId, resultId, samplerId, coordinatesId); + m_currentBlock->Append(SpirvOp::OpImageSampleImplicitLod, typeId, resultId, samplerId, coordinatesId); PushResultId(resultId); } @@ -583,7 +636,7 @@ namespace Nz if (node.componentCount > 1) { // Swizzling is implemented via SpirvOp::OpVectorShuffle using the same vector twice as operands - m_writer.GetInstructions().AppendVariadic(SpirvOp::OpVectorShuffle, [&](const auto& appender) + m_currentBlock->AppendVariadic(SpirvOp::OpVectorShuffle, [&](const auto& appender) { appender(m_writer.GetTypeId(targetType)); appender(resultId); @@ -599,7 +652,7 @@ namespace Nz // Extract a single component from the vector assert(node.componentCount == 1); - m_writer.GetInstructions().Append(SpirvOp::OpCompositeExtract, m_writer.GetTypeId(targetType), resultId, exprResultId, UInt32(node.components[0]) - UInt32(ShaderNodes::SwizzleComponent::First) ); + m_currentBlock->Append(SpirvOp::OpCompositeExtract, m_writer.GetTypeId(targetType), resultId, exprResultId, UInt32(node.components[0]) - UInt32(ShaderNodes::SwizzleComponent::First) ); } PushResultId(resultId); diff --git a/src/Nazara/Shader/SpirvConstantCache.cpp b/src/Nazara/Shader/SpirvConstantCache.cpp index b8489ce76..e764cbf49 100644 --- a/src/Nazara/Shader/SpirvConstantCache.cpp +++ b/src/Nazara/Shader/SpirvConstantCache.cpp @@ -682,7 +682,7 @@ namespace Nz using ConstantType = std::decay_t; if constexpr (std::is_same_v) - constants.Append((arg.value) ? SpirvOp::OpConstantTrue : SpirvOp::OpConstantFalse, resultId); + constants.Append((arg.value) ? SpirvOp::OpConstantTrue : SpirvOp::OpConstantFalse, GetId({ Bool{} }), resultId); else if constexpr (std::is_same_v) { constants.AppendVariadic(SpirvOp::OpConstantComposite, [&](const auto& appender) diff --git a/src/Nazara/Shader/SpirvExpressionLoad.cpp b/src/Nazara/Shader/SpirvExpressionLoad.cpp index 026fefee8..b82d9b046 100644 --- a/src/Nazara/Shader/SpirvExpressionLoad.cpp +++ b/src/Nazara/Shader/SpirvExpressionLoad.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include #include #include @@ -26,7 +26,7 @@ namespace Nz { UInt32 resultId = m_writer.AllocateResultId(); - m_writer.GetInstructions().Append(SpirvOp::OpLoad, pointer.pointedTypeId, resultId, pointer.resultId); + m_block.Append(SpirvOp::OpLoad, pointer.pointedTypeId, resultId, pointer.resultId); return resultId; }, @@ -53,7 +53,7 @@ namespace Nz UInt32 pointerType = m_writer.RegisterPointerType(node.exprType, pointer.storage); //< FIXME UInt32 typeId = m_writer.GetTypeId(node.exprType); - m_writer.GetInstructions().AppendVariadic(SpirvOp::OpAccessChain, [&](const auto& appender) + m_block.AppendVariadic(SpirvOp::OpAccessChain, [&](const auto& appender) { appender(pointerType); appender(resultId); @@ -70,7 +70,7 @@ namespace Nz UInt32 resultId = m_writer.AllocateResultId(); UInt32 typeId = m_writer.GetTypeId(node.exprType); - m_writer.GetInstructions().AppendVariadic(SpirvOp::OpCompositeExtract, [&](const auto& appender) + m_block.AppendVariadic(SpirvOp::OpCompositeExtract, [&](const auto& appender) { appender(typeId); appender(resultId); diff --git a/src/Nazara/Shader/SpirvExpressionStore.cpp b/src/Nazara/Shader/SpirvExpressionStore.cpp index 9123bdcf4..a0c5511d1 100644 --- a/src/Nazara/Shader/SpirvExpressionStore.cpp +++ b/src/Nazara/Shader/SpirvExpressionStore.cpp @@ -3,7 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include +#include #include #include @@ -23,7 +23,7 @@ namespace Nz { [&](const Pointer& pointer) { - m_writer.GetInstructions().Append(SpirvOp::OpStore, pointer.resultId, resultId); + m_block.Append(SpirvOp::OpStore, pointer.resultId, resultId); }, [&](const LocalVar& value) { @@ -47,7 +47,7 @@ namespace Nz UInt32 resultId = m_writer.AllocateResultId(); UInt32 pointerType = m_writer.RegisterPointerType(node.exprType, pointer.storage); //< FIXME - m_writer.GetInstructions().AppendVariadic(SpirvOp::OpAccessChain, [&](const auto& appender) + m_block.AppendVariadic(SpirvOp::OpAccessChain, [&](const auto& appender) { appender(pointerType); appender(resultId); diff --git a/src/Nazara/Shader/SpirvWriter.cpp b/src/Nazara/Shader/SpirvWriter.cpp index 0e1af9c0b..bdc4c12f3 100644 --- a/src/Nazara/Shader/SpirvWriter.cpp +++ b/src/Nazara/Shader/SpirvWriter.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -395,23 +396,29 @@ namespace Nz state.instructions.Append(SpirvOp::OpFunction, GetTypeId(func.returnType), funcData.id, 0, funcData.typeId); - state.instructions.Append(SpirvOp::OpLabel, AllocateResultId()); + std::vector blocks; + blocks.emplace_back(*this); for (const auto& param : func.parameters) { UInt32 paramResultId = AllocateResultId(); funcData.paramsId.push_back(paramResultId); - state.instructions.Append(SpirvOp::OpFunctionParameter, GetTypeId(param.type), paramResultId); + blocks.back().Append(SpirvOp::OpFunctionParameter, GetTypeId(param.type), paramResultId); } - SpirvAstVisitor visitor(*this); + SpirvAstVisitor visitor(*this, blocks); visitor.Visit(functionStatements[funcIndex]); if (func.returnType == ShaderNodes::BasicType::Void) - state.instructions.Append(SpirvOp::OpReturn); + blocks.back().Append(SpirvOp::OpReturn); + else + throw std::runtime_error("returning values from functions is not yet supported"); //< TODO - state.instructions.Append(SpirvOp::OpFunctionEnd); + blocks.back().Append(SpirvOp::OpFunctionEnd); + + for (SpirvBlock& block : blocks) + state.instructions.Append(block); } assert(entryPointIndex != std::numeric_limits::max()); @@ -552,11 +559,6 @@ namespace Nz return it.value(); } - SpirvSection& SpirvWriter::GetInstructions() - { - return m_currentState->instructions; - } - UInt32 SpirvWriter::GetPointerTypeId(const ShaderExpressionType& type, SpirvStorageClass storageClass) const { return m_currentState->constantTypeCache.GetId(*SpirvConstantCache::BuildPointerType(*m_context.shader, type, storageClass)); From a9f2e05b57748078f61138f44be3608a31835303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 14 Jan 2021 21:56:55 +0100 Subject: [PATCH 030/278] Fix typo in enum --- include/Nazara/Shader/ShaderBuilder.hpp | 5 +++-- include/Nazara/Shader/ShaderEnums.hpp | 2 +- src/Nazara/Shader/GlslWriter.cpp | 2 +- src/Nazara/Shader/ShaderAstValidator.cpp | 2 +- src/Nazara/Shader/ShaderNodes.cpp | 2 +- src/Nazara/Shader/SpirvAstVisitor.cpp | 2 +- src/ShaderNode/DataModels/BinOp.hpp | 4 ++-- src/ShaderNode/DataModels/Mat4BinOp.hpp | 4 ++-- 8 files changed, 12 insertions(+), 11 deletions(-) diff --git a/include/Nazara/Shader/ShaderBuilder.hpp b/include/Nazara/Shader/ShaderBuilder.hpp index 03ac51ac2..61dab693e 100644 --- a/include/Nazara/Shader/ShaderBuilder.hpp +++ b/include/Nazara/Shader/ShaderBuilder.hpp @@ -55,7 +55,7 @@ namespace Nz::ShaderBuilder constexpr GenBuilder Constant; constexpr GenBuilder DeclareVariable; constexpr GenBuilder Discard; - constexpr BinOpBuilder Divide; + constexpr BinOpBuilder Division; constexpr BinOpBuilder Equal; constexpr BinOpBuilder GreaterThan; constexpr BinOpBuilder GreaterThanOrEqual; @@ -71,8 +71,9 @@ namespace Nz::ShaderBuilder constexpr GenBuilder Output; constexpr GenBuilder Parameter; constexpr GenBuilder Sample2D; + constexpr GenBuilder StatementBlock; constexpr GenBuilder Swizzle; - constexpr BinOpBuilder Substract; + constexpr BinOpBuilder Subtract; constexpr GenBuilder Uniform; template std::shared_ptr Cast(Args&&... args); diff --git a/include/Nazara/Shader/ShaderEnums.hpp b/include/Nazara/Shader/ShaderEnums.hpp index ccb2f78d5..557b31ffa 100644 --- a/include/Nazara/Shader/ShaderEnums.hpp +++ b/include/Nazara/Shader/ShaderEnums.hpp @@ -39,7 +39,7 @@ namespace Nz::ShaderNodes enum class BinaryType { Add, //< + - Substract, //< - + Subtract, //< - Multiply, //< * Divide, //< / diff --git a/src/Nazara/Shader/GlslWriter.cpp b/src/Nazara/Shader/GlslWriter.cpp index 0dfe2476c..49fa07aa3 100644 --- a/src/Nazara/Shader/GlslWriter.cpp +++ b/src/Nazara/Shader/GlslWriter.cpp @@ -420,7 +420,7 @@ namespace Nz switch (node.op) { case ShaderNodes::BinaryType::Add: Append(" + "); break; - case ShaderNodes::BinaryType::Substract: Append(" - "); break; + case ShaderNodes::BinaryType::Subtract: Append(" - "); break; case ShaderNodes::BinaryType::Multiply: Append(" * "); break; case ShaderNodes::BinaryType::Divide: Append(" / "); break; diff --git a/src/Nazara/Shader/ShaderAstValidator.cpp b/src/Nazara/Shader/ShaderAstValidator.cpp index e139fa25e..90f8aeef2 100644 --- a/src/Nazara/Shader/ShaderAstValidator.cpp +++ b/src/Nazara/Shader/ShaderAstValidator.cpp @@ -161,7 +161,7 @@ namespace Nz case ShaderNodes::BinaryType::Add: case ShaderNodes::BinaryType::CompEq: case ShaderNodes::BinaryType::CompNe: - case ShaderNodes::BinaryType::Substract: + case ShaderNodes::BinaryType::Subtract: TypeMustMatch(node.left, node.right); break; diff --git a/src/Nazara/Shader/ShaderNodes.cpp b/src/Nazara/Shader/ShaderNodes.cpp index 2aa00ec69..05a59ab96 100644 --- a/src/Nazara/Shader/ShaderNodes.cpp +++ b/src/Nazara/Shader/ShaderNodes.cpp @@ -97,7 +97,7 @@ namespace Nz::ShaderNodes switch (op) { case BinaryType::Add: - case BinaryType::Substract: + case BinaryType::Subtract: exprType = left->GetExpressionType(); break; diff --git a/src/Nazara/Shader/SpirvAstVisitor.cpp b/src/Nazara/Shader/SpirvAstVisitor.cpp index f76c8807c..da172fb44 100644 --- a/src/Nazara/Shader/SpirvAstVisitor.cpp +++ b/src/Nazara/Shader/SpirvAstVisitor.cpp @@ -92,7 +92,7 @@ namespace Nz break; } - case ShaderNodes::BinaryType::Substract: + case ShaderNodes::BinaryType::Subtract: { switch (leftType) { diff --git a/src/ShaderNode/DataModels/BinOp.hpp b/src/ShaderNode/DataModels/BinOp.hpp index 8efb9fc6e..a4ac0a189 100644 --- a/src/ShaderNode/DataModels/BinOp.hpp +++ b/src/ShaderNode/DataModels/BinOp.hpp @@ -65,10 +65,10 @@ class BinMul : public BinOp }; template -class BinSub : public BinOp +class BinSub : public BinOp { public: - using BinOp::BinOp; + using BinOp::BinOp; void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; QString GetOperationString() const final; diff --git a/src/ShaderNode/DataModels/Mat4BinOp.hpp b/src/ShaderNode/DataModels/Mat4BinOp.hpp index 1cd7e06dd..1d6d71eee 100644 --- a/src/ShaderNode/DataModels/Mat4BinOp.hpp +++ b/src/ShaderNode/DataModels/Mat4BinOp.hpp @@ -53,10 +53,10 @@ class Mat4Mul : public Mat4BinOp QString name() const override; }; -class Mat4Sub : public Mat4BinOp +class Mat4Sub : public Mat4BinOp { public: - using Mat4BinOp::Mat4BinOp; + using Mat4BinOp::Mat4BinOp; QString caption() const override; QString name() const override; From acb998f67e652a1780a509187b8b96dc073cc4d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 14 Jan 2021 21:58:06 +0100 Subject: [PATCH 031/278] ShaderAst: Add NoOp node --- include/Nazara/Shader/GlslWriter.hpp | 1 + include/Nazara/Shader/ShaderAstCloner.hpp | 1 + include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp | 1 + include/Nazara/Shader/ShaderAstSerializer.hpp | 1 + include/Nazara/Shader/ShaderAstVisitor.hpp | 1 + include/Nazara/Shader/ShaderAstVisitorExcept.hpp | 1 + include/Nazara/Shader/ShaderEnums.hpp | 1 + include/Nazara/Shader/ShaderNodes.hpp | 9 +++++++++ include/Nazara/Shader/ShaderNodes.inl | 11 +++++++++++ include/Nazara/Shader/SpirvAstVisitor.hpp | 1 + src/Nazara/Shader/GlslWriter.cpp | 7 ++++++- src/Nazara/Shader/ShaderAstCloner.cpp | 5 +++++ src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp | 5 +++++ src/Nazara/Shader/ShaderAstSerializer.cpp | 11 +++++++++++ src/Nazara/Shader/ShaderAstVisitorExcept.cpp | 5 +++++ src/Nazara/Shader/ShaderNodes.cpp | 5 +++++ src/Nazara/Shader/SpirvAstVisitor.cpp | 5 +++++ 17 files changed, 70 insertions(+), 1 deletion(-) diff --git a/include/Nazara/Shader/GlslWriter.hpp b/include/Nazara/Shader/GlslWriter.hpp index d7fb7000a..2584389a2 100644 --- a/include/Nazara/Shader/GlslWriter.hpp +++ b/include/Nazara/Shader/GlslWriter.hpp @@ -79,6 +79,7 @@ namespace Nz void Visit(ShaderNodes::InputVariable& var) override; void Visit(ShaderNodes::IntrinsicCall& node) override; void Visit(ShaderNodes::LocalVariable& var) override; + void Visit(ShaderNodes::NoOp& node) override; void Visit(ShaderNodes::ParameterVariable& var) override; void Visit(ShaderNodes::OutputVariable& var) override; void Visit(ShaderNodes::Sample2D& node) override; diff --git a/include/Nazara/Shader/ShaderAstCloner.hpp b/include/Nazara/Shader/ShaderAstCloner.hpp index 1f5259b51..ddd55e4ba 100644 --- a/include/Nazara/Shader/ShaderAstCloner.hpp +++ b/include/Nazara/Shader/ShaderAstCloner.hpp @@ -46,6 +46,7 @@ namespace Nz void Visit(ShaderNodes::ExpressionStatement& node) override; void Visit(ShaderNodes::Identifier& node) override; void Visit(ShaderNodes::IntrinsicCall& node) override; + void Visit(ShaderNodes::NoOp& node) override; void Visit(ShaderNodes::Sample2D& node) override; void Visit(ShaderNodes::StatementBlock& node) override; void Visit(ShaderNodes::SwizzleOp& node) override; diff --git a/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp b/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp index 9e780e340..ce8ba487c 100644 --- a/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp +++ b/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp @@ -34,6 +34,7 @@ namespace Nz void Visit(ShaderNodes::ExpressionStatement& node) override; void Visit(ShaderNodes::Identifier& node) override; void Visit(ShaderNodes::IntrinsicCall& node) override; + void Visit(ShaderNodes::NoOp& node) override; void Visit(ShaderNodes::Sample2D& node) override; void Visit(ShaderNodes::StatementBlock& node) override; void Visit(ShaderNodes::SwizzleOp& node) override; diff --git a/include/Nazara/Shader/ShaderAstSerializer.hpp b/include/Nazara/Shader/ShaderAstSerializer.hpp index e6e50487a..ad8af504d 100644 --- a/include/Nazara/Shader/ShaderAstSerializer.hpp +++ b/include/Nazara/Shader/ShaderAstSerializer.hpp @@ -40,6 +40,7 @@ namespace Nz void Serialize(ShaderNodes::Identifier& node); void Serialize(ShaderNodes::IntrinsicCall& node); void Serialize(ShaderNodes::NamedVariable& var); + void Serialize(ShaderNodes::NoOp& node); void Serialize(ShaderNodes::Sample2D& node); void Serialize(ShaderNodes::StatementBlock& node); void Serialize(ShaderNodes::SwizzleOp& node); diff --git a/include/Nazara/Shader/ShaderAstVisitor.hpp b/include/Nazara/Shader/ShaderAstVisitor.hpp index f3b0c5bdc..79fb23e9e 100644 --- a/include/Nazara/Shader/ShaderAstVisitor.hpp +++ b/include/Nazara/Shader/ShaderAstVisitor.hpp @@ -35,6 +35,7 @@ namespace Nz virtual void Visit(ShaderNodes::ExpressionStatement& node) = 0; virtual void Visit(ShaderNodes::Identifier& node) = 0; virtual void Visit(ShaderNodes::IntrinsicCall& node) = 0; + virtual void Visit(ShaderNodes::NoOp& node) = 0; virtual void Visit(ShaderNodes::Sample2D& node) = 0; virtual void Visit(ShaderNodes::StatementBlock& node) = 0; virtual void Visit(ShaderNodes::SwizzleOp& node) = 0; diff --git a/include/Nazara/Shader/ShaderAstVisitorExcept.hpp b/include/Nazara/Shader/ShaderAstVisitorExcept.hpp index 3878d522d..65e507062 100644 --- a/include/Nazara/Shader/ShaderAstVisitorExcept.hpp +++ b/include/Nazara/Shader/ShaderAstVisitorExcept.hpp @@ -30,6 +30,7 @@ namespace Nz void Visit(ShaderNodes::ExpressionStatement& node) override; void Visit(ShaderNodes::Identifier& node) override; void Visit(ShaderNodes::IntrinsicCall& node) override; + void Visit(ShaderNodes::NoOp& node) override; void Visit(ShaderNodes::Sample2D& node) override; void Visit(ShaderNodes::StatementBlock& node) override; void Visit(ShaderNodes::SwizzleOp& node) override; diff --git a/include/Nazara/Shader/ShaderEnums.hpp b/include/Nazara/Shader/ShaderEnums.hpp index 557b31ffa..64d8729f3 100644 --- a/include/Nazara/Shader/ShaderEnums.hpp +++ b/include/Nazara/Shader/ShaderEnums.hpp @@ -90,6 +90,7 @@ namespace Nz::ShaderNodes ExpressionStatement, Identifier, IntrinsicCall, + NoOp, Sample2D, SwizzleOp, StatementBlock, diff --git a/include/Nazara/Shader/ShaderNodes.hpp b/include/Nazara/Shader/ShaderNodes.hpp index e519a0b08..5a8f28ce7 100644 --- a/include/Nazara/Shader/ShaderNodes.hpp +++ b/include/Nazara/Shader/ShaderNodes.hpp @@ -161,6 +161,15 @@ namespace Nz static inline std::shared_ptr Build(ExpressionPtr structExpr, std::vector memberIndices, ShaderExpressionType exprType); }; + struct NAZARA_SHADER_API NoOp : public Statement + { + inline NoOp(); + + void Visit(ShaderAstVisitor& visitor) override; + + static inline std::shared_ptr Build(); + }; + ////////////////////////////////////////////////////////////////////////// struct NAZARA_SHADER_API AssignOp : public Expression diff --git a/include/Nazara/Shader/ShaderNodes.inl b/include/Nazara/Shader/ShaderNodes.inl index f3fbecaff..d050a4a31 100644 --- a/include/Nazara/Shader/ShaderNodes.inl +++ b/include/Nazara/Shader/ShaderNodes.inl @@ -194,6 +194,17 @@ namespace Nz::ShaderNodes } + inline ShaderNodes::NoOp::NoOp() : + Statement(NodeType::NoOp) + { + } + + inline std::shared_ptr NoOp::Build() + { + return std::make_shared(); + } + + inline AssignOp::AssignOp() : Expression(NodeType::AssignOp) { diff --git a/include/Nazara/Shader/SpirvAstVisitor.hpp b/include/Nazara/Shader/SpirvAstVisitor.hpp index 571af6cc5..0cac761ca 100644 --- a/include/Nazara/Shader/SpirvAstVisitor.hpp +++ b/include/Nazara/Shader/SpirvAstVisitor.hpp @@ -42,6 +42,7 @@ namespace Nz void Visit(ShaderNodes::ExpressionStatement& node) override; void Visit(ShaderNodes::Identifier& node) override; void Visit(ShaderNodes::IntrinsicCall& node) override; + void Visit(ShaderNodes::NoOp& node) override; void Visit(ShaderNodes::Sample2D& node) override; void Visit(ShaderNodes::StatementBlock& node) override; void Visit(ShaderNodes::SwizzleOp& node) override; diff --git a/src/Nazara/Shader/GlslWriter.cpp b/src/Nazara/Shader/GlslWriter.cpp index 49fa07aa3..6179f094b 100644 --- a/src/Nazara/Shader/GlslWriter.cpp +++ b/src/Nazara/Shader/GlslWriter.cpp @@ -574,6 +574,11 @@ namespace Nz Append(var.name); } + void GlslWriter::Visit(ShaderNodes::NoOp& /*node*/) + { + /* nothing to do */ + } + void GlslWriter::Visit(ShaderNodes::ParameterVariable& var) { Append(var.name); @@ -598,7 +603,7 @@ namespace Nz bool first = true; for (const ShaderNodes::StatementPtr& statement : node.statements) { - if (!first) + if (!first && statement->GetType() != ShaderNodes::NodeType::NoOp) AppendLine(); Visit(statement); diff --git a/src/Nazara/Shader/ShaderAstCloner.cpp b/src/Nazara/Shader/ShaderAstCloner.cpp index 8a07cf1a7..ebbcfa560 100644 --- a/src/Nazara/Shader/ShaderAstCloner.cpp +++ b/src/Nazara/Shader/ShaderAstCloner.cpp @@ -137,6 +137,11 @@ namespace Nz PushExpression(ShaderNodes::IntrinsicCall::Build(node.intrinsic, std::move(parameters))); } + void ShaderAstCloner::Visit(ShaderNodes::NoOp& /*node*/) + { + PushStatement(ShaderNodes::NoOp::Build()); + } + void ShaderAstCloner::Visit(ShaderNodes::Sample2D& node) { PushExpression(ShaderNodes::Sample2D::Build(CloneExpression(node.sampler), CloneExpression(node.coordinates))); diff --git a/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp b/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp index bca595384..d3b404011 100644 --- a/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp +++ b/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp @@ -90,6 +90,11 @@ namespace Nz Visit(param); } + void ShaderAstRecursiveVisitor::Visit(ShaderNodes::NoOp& /*node*/) + { + /* Nothing to do */ + } + void ShaderAstRecursiveVisitor::Visit(ShaderNodes::Sample2D& node) { Visit(node.sampler); diff --git a/src/Nazara/Shader/ShaderAstSerializer.cpp b/src/Nazara/Shader/ShaderAstSerializer.cpp index 7f12ad3b5..66b346a7f 100644 --- a/src/Nazara/Shader/ShaderAstSerializer.cpp +++ b/src/Nazara/Shader/ShaderAstSerializer.cpp @@ -87,6 +87,11 @@ namespace Nz Serialize(node); } + void Visit(ShaderNodes::NoOp& node) override + { + Serialize(node); + } + void Visit(ShaderNodes::Sample2D& node) override { Serialize(node); @@ -276,6 +281,11 @@ namespace Nz Type(node.type); } + void ShaderAstSerializerBase::Serialize(ShaderNodes::NoOp& /*node*/) + { + /* Nothing to do */ + } + void ShaderAstSerializerBase::Serialize(ShaderNodes::Sample2D& node) { Node(node.sampler); @@ -682,6 +692,7 @@ namespace Nz HandleType(ExpressionStatement); HandleType(Identifier); HandleType(IntrinsicCall); + HandleType(NoOp); HandleType(Sample2D); HandleType(SwizzleOp); HandleType(StatementBlock); diff --git a/src/Nazara/Shader/ShaderAstVisitorExcept.cpp b/src/Nazara/Shader/ShaderAstVisitorExcept.cpp index 17671a42c..7843281d4 100644 --- a/src/Nazara/Shader/ShaderAstVisitorExcept.cpp +++ b/src/Nazara/Shader/ShaderAstVisitorExcept.cpp @@ -73,6 +73,11 @@ namespace Nz throw std::runtime_error("unhandled IntrinsicCall node"); } + void ShaderAstVisitorExcept::Visit(ShaderNodes::NoOp& node) + { + throw std::runtime_error("unhandled NoOp node"); + } + void ShaderAstVisitorExcept::Visit(ShaderNodes::Sample2D& /*node*/) { throw std::runtime_error("unhandled Sample2D node"); diff --git a/src/Nazara/Shader/ShaderNodes.cpp b/src/Nazara/Shader/ShaderNodes.cpp index 05a59ab96..8d96c40ea 100644 --- a/src/Nazara/Shader/ShaderNodes.cpp +++ b/src/Nazara/Shader/ShaderNodes.cpp @@ -79,6 +79,11 @@ namespace Nz::ShaderNodes visitor.Visit(*this); } + void NoOp::Visit(ShaderAstVisitor& visitor) + { + visitor.Visit(*this); + } + ShaderExpressionType AssignOp::GetExpressionType() const { return left->GetExpressionType(); diff --git a/src/Nazara/Shader/SpirvAstVisitor.cpp b/src/Nazara/Shader/SpirvAstVisitor.cpp index da172fb44..9c6797ff9 100644 --- a/src/Nazara/Shader/SpirvAstVisitor.cpp +++ b/src/Nazara/Shader/SpirvAstVisitor.cpp @@ -605,6 +605,11 @@ namespace Nz } } + void SpirvAstVisitor::Visit(ShaderNodes::NoOp& /*node*/) + { + // nothing to do + } + void SpirvAstVisitor::Visit(ShaderNodes::Sample2D& node) { UInt32 typeId = m_writer.GetTypeId(ShaderNodes::BasicType::Float4); From 00ac6e8a0a886e16b1161c1c7ae7623c03a779dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 14 Jan 2021 22:01:05 +0100 Subject: [PATCH 032/278] Shader: Add ShaderAstOptimizer --- include/Nazara/Shader/ShaderAstCloner.hpp | 2 + include/Nazara/Shader/ShaderAstOptimizer.hpp | 50 ++ include/Nazara/Shader/ShaderAstOptimizer.inl | 12 + src/Nazara/Shader/ShaderAstOptimizer.cpp | 544 +++++++++++++++++++ 4 files changed, 608 insertions(+) create mode 100644 include/Nazara/Shader/ShaderAstOptimizer.hpp create mode 100644 include/Nazara/Shader/ShaderAstOptimizer.inl create mode 100644 src/Nazara/Shader/ShaderAstOptimizer.cpp diff --git a/include/Nazara/Shader/ShaderAstCloner.hpp b/include/Nazara/Shader/ShaderAstCloner.hpp index ddd55e4ba..94b68cb0a 100644 --- a/include/Nazara/Shader/ShaderAstCloner.hpp +++ b/include/Nazara/Shader/ShaderAstCloner.hpp @@ -33,6 +33,7 @@ namespace Nz ShaderNodes::StatementPtr CloneStatement(const ShaderNodes::StatementPtr& statement); ShaderNodes::VariablePtr CloneVariable(const ShaderNodes::VariablePtr& statement); + using ShaderAstVisitor::Visit; void Visit(ShaderNodes::AccessMember& node) override; void Visit(ShaderNodes::AssignOp& node) override; void Visit(ShaderNodes::BinaryOp& node) override; @@ -51,6 +52,7 @@ namespace Nz void Visit(ShaderNodes::StatementBlock& node) override; void Visit(ShaderNodes::SwizzleOp& node) override; + using ShaderVarVisitor::Visit; void Visit(ShaderNodes::BuiltinVariable& var) override; void Visit(ShaderNodes::InputVariable& var) override; void Visit(ShaderNodes::LocalVariable& var) override; diff --git a/include/Nazara/Shader/ShaderAstOptimizer.hpp b/include/Nazara/Shader/ShaderAstOptimizer.hpp new file mode 100644 index 000000000..d7d56b7cf --- /dev/null +++ b/include/Nazara/Shader/ShaderAstOptimizer.hpp @@ -0,0 +1,50 @@ +// 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_SHADERASTOPTIMISER_HPP +#define NAZARA_SHADERASTOPTIMISER_HPP + +#include +#include +#include +#include + +namespace Nz +{ + class ShaderAst; + + class NAZARA_SHADER_API ShaderAstOptimizer : public ShaderAstCloner + { + public: + ShaderAstOptimizer() = default; + ShaderAstOptimizer(const ShaderAstOptimizer&) = delete; + ShaderAstOptimizer(ShaderAstOptimizer&&) = delete; + ~ShaderAstOptimizer() = default; + + ShaderNodes::StatementPtr Optimise(const ShaderNodes::StatementPtr& statement); + ShaderNodes::StatementPtr Optimise(const ShaderNodes::StatementPtr& statement, const ShaderAst& shader, UInt64 enabledConditions); + + ShaderAstOptimizer& operator=(const ShaderAstOptimizer&) = delete; + ShaderAstOptimizer& operator=(ShaderAstOptimizer&&) = delete; + + protected: + using ShaderAstCloner::Visit; + void Visit(ShaderNodes::BinaryOp& node) override; + void Visit(ShaderNodes::Branch& node) override; + void Visit(ShaderNodes::ConditionalExpression& node) override; + void Visit(ShaderNodes::ConditionalStatement& node) override; + + template void PropagateConstant(const std::shared_ptr& lhs, const std::shared_ptr& rhs); + + private: + const ShaderAst* m_shaderAst; + UInt64 m_enabledConditions; + }; +} + +#include + +#endif diff --git a/include/Nazara/Shader/ShaderAstOptimizer.inl b/include/Nazara/Shader/ShaderAstOptimizer.inl new file mode 100644 index 000000000..17cd14c12 --- /dev/null +++ b/include/Nazara/Shader/ShaderAstOptimizer.inl @@ -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 +#include + +namespace Nz +{ +} + +#include diff --git a/src/Nazara/Shader/ShaderAstOptimizer.cpp b/src/Nazara/Shader/ShaderAstOptimizer.cpp new file mode 100644 index 000000000..6bc61c1e4 --- /dev/null +++ b/src/Nazara/Shader/ShaderAstOptimizer.cpp @@ -0,0 +1,544 @@ +// 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 +#include +#include +#include +#include +#include + +namespace Nz +{ + namespace + { + template + struct is_complete_helper + { + template static auto test(U*)->std::integral_constant; + static auto test(...) -> std::false_type; + + using type = decltype(test((T*)0)); + }; + + template + struct is_complete : is_complete_helper::type {}; + + template + inline constexpr bool is_complete_v = is_complete::value; + + + template + struct PropagateConstantType; + + // CompEq + template + struct CompEqBase + { + ShaderNodes::ExpressionPtr operator()(const T1& lhs, const T2& rhs) + { + return ShaderBuilder::Constant(lhs == rhs); + } + }; + + template + struct CompEq; + + template + struct PropagateConstantType + { + using Op = typename CompEq; + }; + + // CompGe + template + struct CompGeBase + { + ShaderNodes::ExpressionPtr operator()(const T1& lhs, const T2& rhs) + { + return ShaderBuilder::Constant(lhs >= rhs); + } + }; + + template + struct CompGe; + + template + struct PropagateConstantType + { + using Op = typename CompGe; + }; + + // CompGt + template + struct CompGtBase + { + ShaderNodes::ExpressionPtr operator()(const T1& lhs, const T2& rhs) + { + return ShaderBuilder::Constant(lhs > rhs); + } + }; + + template + struct CompGt; + + template + struct PropagateConstantType + { + using Op = typename CompGt; + }; + + // CompLe + template + struct CompLeBase + { + ShaderNodes::ExpressionPtr operator()(const T1& lhs, const T2& rhs) + { + return ShaderBuilder::Constant(lhs <= rhs); + } + }; + + template + struct CompLe; + + template + struct PropagateConstantType + { + using Op = typename CompLe; + }; + + // CompLt + template + struct CompLtBase + { + ShaderNodes::ExpressionPtr operator()(const T1& lhs, const T2& rhs) + { + return ShaderBuilder::Constant(lhs < rhs); + } + }; + + template + struct CompLt; + + template + struct PropagateConstantType + { + using Op = typename CompLe; + }; + + // CompNe + template + struct CompNeBase + { + ShaderNodes::ExpressionPtr operator()(const T1& lhs, const T2& rhs) + { + return ShaderBuilder::Constant(lhs != rhs); + } + }; + + template + struct CompNe; + + template + struct PropagateConstantType + { + using Op = typename CompNe; + }; + + // Addition + template + struct AdditionBase + { + ShaderNodes::ExpressionPtr operator()(const T1& lhs, const T2& rhs) + { + return ShaderBuilder::Constant(lhs + rhs); + } + }; + + template + struct Addition; + + template + struct PropagateConstantType + { + using Op = typename Addition; + }; + + // Division + template + struct DivisionBase + { + ShaderNodes::ExpressionPtr operator()(const T1& lhs, const T2& rhs) + { + return ShaderBuilder::Constant(lhs / rhs); + } + }; + + template + struct Division; + + template + struct PropagateConstantType + { + using Op = typename Division; + }; + + // Multiplication + template + struct MultiplicationBase + { + ShaderNodes::ExpressionPtr operator()(const T1& lhs, const T2& rhs) + { + return ShaderBuilder::Constant(lhs * rhs); + } + }; + + template + struct Multiplication; + + template + struct PropagateConstantType + { + using Op = typename Multiplication; + }; + + // Subtraction + template + struct SubtractionBase + { + ShaderNodes::ExpressionPtr operator()(const T1& lhs, const T2& rhs) + { + return ShaderBuilder::Constant(lhs - rhs); + } + }; + + template + struct Subtraction; + + template + struct PropagateConstantType + { + using Op = typename Subtraction; + }; + +#define EnableOptimisation(Op, T1, T2) template<> struct Op : Op##Base {} + + EnableOptimisation(CompEq, bool, bool); + EnableOptimisation(CompEq, double, double); + EnableOptimisation(CompEq, float, float); + EnableOptimisation(CompEq, Nz::Int32, Nz::Int32); + EnableOptimisation(CompEq, Nz::Vector2f, Nz::Vector2f); + EnableOptimisation(CompEq, Nz::Vector3f, Nz::Vector3f); + EnableOptimisation(CompEq, Nz::Vector4f, Nz::Vector4f); + EnableOptimisation(CompEq, Nz::Vector2i32, Nz::Vector2i32); + EnableOptimisation(CompEq, Nz::Vector3i32, Nz::Vector3i32); + EnableOptimisation(CompEq, Nz::Vector4i32, Nz::Vector4i32); + + EnableOptimisation(CompGe, bool, bool); + EnableOptimisation(CompGe, double, double); + EnableOptimisation(CompGe, float, float); + EnableOptimisation(CompGe, Nz::Int32, Nz::Int32); + EnableOptimisation(CompGe, Nz::Vector2f, Nz::Vector2f); + EnableOptimisation(CompGe, Nz::Vector3f, Nz::Vector3f); + EnableOptimisation(CompGe, Nz::Vector4f, Nz::Vector4f); + EnableOptimisation(CompGe, Nz::Vector2i32, Nz::Vector2i32); + EnableOptimisation(CompGe, Nz::Vector3i32, Nz::Vector3i32); + EnableOptimisation(CompGe, Nz::Vector4i32, Nz::Vector4i32); + + EnableOptimisation(CompGt, bool, bool); + EnableOptimisation(CompGt, double, double); + EnableOptimisation(CompGt, float, float); + EnableOptimisation(CompGt, Nz::Int32, Nz::Int32); + EnableOptimisation(CompGt, Nz::Vector2f, Nz::Vector2f); + EnableOptimisation(CompGt, Nz::Vector3f, Nz::Vector3f); + EnableOptimisation(CompGt, Nz::Vector4f, Nz::Vector4f); + EnableOptimisation(CompGt, Nz::Vector2i32, Nz::Vector2i32); + EnableOptimisation(CompGt, Nz::Vector3i32, Nz::Vector3i32); + EnableOptimisation(CompGt, Nz::Vector4i32, Nz::Vector4i32); + + EnableOptimisation(CompLe, bool, bool); + EnableOptimisation(CompLe, double, double); + EnableOptimisation(CompLe, float, float); + EnableOptimisation(CompLe, Nz::Int32, Nz::Int32); + EnableOptimisation(CompLe, Nz::Vector2f, Nz::Vector2f); + EnableOptimisation(CompLe, Nz::Vector3f, Nz::Vector3f); + EnableOptimisation(CompLe, Nz::Vector4f, Nz::Vector4f); + EnableOptimisation(CompLe, Nz::Vector2i32, Nz::Vector2i32); + EnableOptimisation(CompLe, Nz::Vector3i32, Nz::Vector3i32); + EnableOptimisation(CompLe, Nz::Vector4i32, Nz::Vector4i32); + + EnableOptimisation(CompLt, bool, bool); + EnableOptimisation(CompLt, double, double); + EnableOptimisation(CompLt, float, float); + EnableOptimisation(CompLt, Nz::Int32, Nz::Int32); + EnableOptimisation(CompLt, Nz::Vector2f, Nz::Vector2f); + EnableOptimisation(CompLt, Nz::Vector3f, Nz::Vector3f); + EnableOptimisation(CompLt, Nz::Vector4f, Nz::Vector4f); + EnableOptimisation(CompLt, Nz::Vector2i32, Nz::Vector2i32); + EnableOptimisation(CompLt, Nz::Vector3i32, Nz::Vector3i32); + EnableOptimisation(CompLt, Nz::Vector4i32, Nz::Vector4i32); + + EnableOptimisation(CompNe, bool, bool); + EnableOptimisation(CompNe, double, double); + EnableOptimisation(CompNe, float, float); + EnableOptimisation(CompNe, Nz::Int32, Nz::Int32); + EnableOptimisation(CompNe, Nz::Vector2f, Nz::Vector2f); + EnableOptimisation(CompNe, Nz::Vector3f, Nz::Vector3f); + EnableOptimisation(CompNe, Nz::Vector4f, Nz::Vector4f); + EnableOptimisation(CompNe, Nz::Vector2i32, Nz::Vector2i32); + EnableOptimisation(CompNe, Nz::Vector3i32, Nz::Vector3i32); + EnableOptimisation(CompNe, Nz::Vector4i32, Nz::Vector4i32); + + EnableOptimisation(Addition, double, double); + EnableOptimisation(Addition, float, float); + EnableOptimisation(Addition, Nz::Int32, Nz::Int32); + EnableOptimisation(Addition, Nz::Vector2f, Nz::Vector2f); + EnableOptimisation(Addition, Nz::Vector3f, Nz::Vector3f); + EnableOptimisation(Addition, Nz::Vector4f, Nz::Vector4f); + EnableOptimisation(Addition, Nz::Vector2i32, Nz::Vector2i32); + EnableOptimisation(Addition, Nz::Vector3i32, Nz::Vector3i32); + EnableOptimisation(Addition, Nz::Vector4i32, Nz::Vector4i32); + + EnableOptimisation(Division, double, double); + EnableOptimisation(Division, double, Nz::Vector2d); + EnableOptimisation(Division, double, Nz::Vector3d); + EnableOptimisation(Division, double, Nz::Vector4d); + EnableOptimisation(Division, float, float); + EnableOptimisation(Division, float, Nz::Vector2f); + EnableOptimisation(Division, float, Nz::Vector3f); + EnableOptimisation(Division, float, Nz::Vector4f); + EnableOptimisation(Division, Nz::Int32, Nz::Int32); + EnableOptimisation(Division, Nz::Int32, Nz::Vector2i32); + EnableOptimisation(Division, Nz::Int32, Nz::Vector3i32); + EnableOptimisation(Division, Nz::Int32, Nz::Vector4i32); + EnableOptimisation(Division, Nz::Vector2f, float); + EnableOptimisation(Division, Nz::Vector2f, Nz::Vector2f); + EnableOptimisation(Division, Nz::Vector3f, float); + EnableOptimisation(Division, Nz::Vector3f, Nz::Vector3f); + EnableOptimisation(Division, Nz::Vector4f, float); + EnableOptimisation(Division, Nz::Vector4f, Nz::Vector4f); + EnableOptimisation(Division, Nz::Vector2d, double); + EnableOptimisation(Division, Nz::Vector2d, Nz::Vector2d); + EnableOptimisation(Division, Nz::Vector3d, double); + EnableOptimisation(Division, Nz::Vector3d, Nz::Vector3d); + EnableOptimisation(Division, Nz::Vector4d, double); + EnableOptimisation(Division, Nz::Vector4d, Nz::Vector4d); + EnableOptimisation(Division, Nz::Vector2i32, Nz::Int32); + EnableOptimisation(Division, Nz::Vector2i32, Nz::Vector2i32); + EnableOptimisation(Division, Nz::Vector3i32, Nz::Int32); + EnableOptimisation(Division, Nz::Vector3i32, Nz::Vector3i32); + EnableOptimisation(Division, Nz::Vector4i32, Nz::Int32); + EnableOptimisation(Division, Nz::Vector4i32, Nz::Vector4i32); + + EnableOptimisation(Multiplication, double, double); + EnableOptimisation(Multiplication, double, Nz::Vector2d); + EnableOptimisation(Multiplication, double, Nz::Vector3d); + EnableOptimisation(Multiplication, double, Nz::Vector4d); + EnableOptimisation(Multiplication, float, float); + EnableOptimisation(Multiplication, float, Nz::Vector2f); + EnableOptimisation(Multiplication, float, Nz::Vector3f); + EnableOptimisation(Multiplication, float, Nz::Vector4f); + EnableOptimisation(Multiplication, Nz::Int32, Nz::Int32); + EnableOptimisation(Multiplication, Nz::Int32, Nz::Vector2i32); + EnableOptimisation(Multiplication, Nz::Int32, Nz::Vector3i32); + EnableOptimisation(Multiplication, Nz::Int32, Nz::Vector4i32); + EnableOptimisation(Multiplication, Nz::Vector2f, float); + EnableOptimisation(Multiplication, Nz::Vector2f, Nz::Vector2f); + EnableOptimisation(Multiplication, Nz::Vector3f, float); + EnableOptimisation(Multiplication, Nz::Vector3f, Nz::Vector3f); + EnableOptimisation(Multiplication, Nz::Vector4f, float); + EnableOptimisation(Multiplication, Nz::Vector4f, Nz::Vector4f); + EnableOptimisation(Multiplication, Nz::Vector2d, double); + EnableOptimisation(Multiplication, Nz::Vector2d, Nz::Vector2d); + EnableOptimisation(Multiplication, Nz::Vector3d, double); + EnableOptimisation(Multiplication, Nz::Vector3d, Nz::Vector3d); + EnableOptimisation(Multiplication, Nz::Vector4d, double); + EnableOptimisation(Multiplication, Nz::Vector4d, Nz::Vector4d); + EnableOptimisation(Multiplication, Nz::Vector2i32, Nz::Int32); + EnableOptimisation(Multiplication, Nz::Vector2i32, Nz::Vector2i32); + EnableOptimisation(Multiplication, Nz::Vector3i32, Nz::Int32); + EnableOptimisation(Multiplication, Nz::Vector3i32, Nz::Vector3i32); + EnableOptimisation(Multiplication, Nz::Vector4i32, Nz::Int32); + EnableOptimisation(Multiplication, Nz::Vector4i32, Nz::Vector4i32); + + EnableOptimisation(Subtraction, double, double); + EnableOptimisation(Subtraction, float, float); + EnableOptimisation(Subtraction, Nz::Int32, Nz::Int32); + EnableOptimisation(Subtraction, Nz::Vector2f, Nz::Vector2f); + EnableOptimisation(Subtraction, Nz::Vector3f, Nz::Vector3f); + EnableOptimisation(Subtraction, Nz::Vector4f, Nz::Vector4f); + EnableOptimisation(Subtraction, Nz::Vector2i32, Nz::Vector2i32); + EnableOptimisation(Subtraction, Nz::Vector3i32, Nz::Vector3i32); + EnableOptimisation(Subtraction, Nz::Vector4i32, Nz::Vector4i32); + +#undef EnableOptimisation + } + + ShaderNodes::StatementPtr ShaderAstOptimizer::Optimise(const ShaderNodes::StatementPtr& statement) + { + m_shaderAst = nullptr; + + return CloneStatement(statement); + } + + ShaderNodes::StatementPtr ShaderAstOptimizer::Optimise(const ShaderNodes::StatementPtr& statement, const ShaderAst& shader, UInt64 enabledConditions) + { + m_shaderAst = &shader; + m_enabledConditions = enabledConditions; + + return CloneStatement(statement); + } + + void ShaderAstOptimizer::Visit(ShaderNodes::BinaryOp& node) + { + auto lhs = CloneExpression(node.left); + auto rhs = CloneExpression(node.right); + + if (lhs->GetType() == ShaderNodes::NodeType::Constant && rhs->GetType() == ShaderNodes::NodeType::Constant) + { + auto lhsConstant = std::static_pointer_cast(lhs); + auto rhsConstant = std::static_pointer_cast(rhs); + + switch (node.op) + { + case ShaderNodes::BinaryType::Add: + return PropagateConstant(lhsConstant, rhsConstant); + + case ShaderNodes::BinaryType::Subtract: + return PropagateConstant(lhsConstant, rhsConstant); + + case ShaderNodes::BinaryType::Multiply: + return PropagateConstant(lhsConstant, rhsConstant); + + case ShaderNodes::BinaryType::Divide: + return PropagateConstant(lhsConstant, rhsConstant); + + case ShaderNodes::BinaryType::CompEq: + return PropagateConstant(lhsConstant, rhsConstant); + + case ShaderNodes::BinaryType::CompGe: + return PropagateConstant(lhsConstant, rhsConstant); + + case ShaderNodes::BinaryType::CompGt: + return PropagateConstant(lhsConstant, rhsConstant); + + case ShaderNodes::BinaryType::CompLe: + return PropagateConstant(lhsConstant, rhsConstant); + + case ShaderNodes::BinaryType::CompLt: + return PropagateConstant(lhsConstant, rhsConstant); + + case ShaderNodes::BinaryType::CompNe: + return PropagateConstant(lhsConstant, rhsConstant); + } + } + + ShaderAstCloner::Visit(node); + } + + void ShaderAstOptimizer::Visit(ShaderNodes::Branch& node) + { + std::vector statements; + ShaderNodes::StatementPtr elseStatement; + + for (auto& condStatement : node.condStatements) + { + auto cond = CloneExpression(condStatement.condition); + + if (cond->GetType() == ShaderNodes::NodeType::Constant) + { + auto constant = std::static_pointer_cast(cond); + + assert(IsBasicType(cond->GetExpressionType())); + assert(std::get(cond->GetExpressionType()) == ShaderNodes::BasicType::Boolean); + + bool cValue = std::get(constant->value); + if (!cValue) + continue; + + if (statements.empty()) + { + // First condition is true, dismiss the branch + Visit(condStatement.statement); + return; + } + else + { + // Some condition after the first one is true, make it the else statement and stop there + elseStatement = CloneStatement(condStatement.statement); + break; + } + } + } + + if (statements.empty()) + { + // All conditions have been removed, replace by else statement or no-op + if (node.elseStatement) + return Visit(node.elseStatement); + else + return PushStatement(ShaderNodes::NoOp::Build()); + } + + if (!elseStatement) + elseStatement = CloneStatement(node.elseStatement); + + PushStatement(ShaderNodes::Branch::Build(std::move(statements), std::move(elseStatement))); + } + + void ShaderAstOptimizer::Visit(ShaderNodes::ConditionalExpression& node) + { + if (!m_shaderAst) + return ShaderAstCloner::Visit(node); + + std::size_t conditionIndex = m_shaderAst->FindConditionByName(node.conditionName); + assert(conditionIndex != ShaderAst::InvalidCondition); + + if (TestBit(m_enabledConditions, conditionIndex)) + Visit(node.truePath); + else + Visit(node.falsePath); + } + + void ShaderAstOptimizer::Visit(ShaderNodes::ConditionalStatement& node) + { + if (!m_shaderAst) + return ShaderAstCloner::Visit(node); + + std::size_t conditionIndex = m_shaderAst->FindConditionByName(node.conditionName); + assert(conditionIndex != ShaderAst::InvalidCondition); + + if (TestBit(m_enabledConditions, conditionIndex)) + Visit(node.statement); + } + + template + void ShaderAstOptimizer::PropagateConstant(const std::shared_ptr& lhs, const std::shared_ptr& rhs) + { + ShaderNodes::ExpressionPtr optimized; + std::visit([&](auto&& arg1) + { + using T1 = std::decay_t; + + std::visit([&](auto&& arg2) + { + using T2 = std::decay_t; + using PCType = PropagateConstantType; + + if constexpr (is_complete_v) + { + using Op = typename PCType::Op; + if constexpr (is_complete_v) + optimized = Op{}(arg1, arg2); + } + + }, rhs->value); + }, lhs->value); + + if (optimized) + PushExpression(optimized); + else + PushExpression(ShaderNodes::BinaryOp::Build(Type, lhs, rhs)); + } +} From a037eef4c9d2dad31daf35e9000d0f9df7b7c36d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 14 Jan 2021 22:01:53 +0100 Subject: [PATCH 033/278] Shader: Remove ShaderNode::GetExpressionType (replaced by visitor) and minor stuff --- include/Nazara/Shader/ShaderAstUtils.hpp | 54 +++++++++++++++++ include/Nazara/Shader/ShaderAstUtils.inl | 17 ++++++ include/Nazara/Shader/ShaderNodes.hpp | 9 +-- src/Nazara/Shader/GlslWriter.cpp | 4 +- src/Nazara/Shader/ShaderAstUtils.cpp | 73 +++++++++++++++++++++++ src/Nazara/Shader/ShaderAstValidator.cpp | 8 ++- src/Nazara/Shader/ShaderNodes.cpp | 20 ------- src/Nazara/Shader/SpirvExpressionLoad.cpp | 2 +- src/ShaderNode/ShaderGraph.cpp | 2 +- 9 files changed, 157 insertions(+), 32 deletions(-) create mode 100644 include/Nazara/Shader/ShaderAstUtils.hpp create mode 100644 include/Nazara/Shader/ShaderAstUtils.inl create mode 100644 src/Nazara/Shader/ShaderAstUtils.cpp diff --git a/include/Nazara/Shader/ShaderAstUtils.hpp b/include/Nazara/Shader/ShaderAstUtils.hpp new file mode 100644 index 000000000..e78ee657f --- /dev/null +++ b/include/Nazara/Shader/ShaderAstUtils.hpp @@ -0,0 +1,54 @@ +// 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_SHADERASTUTILS_HPP +#define NAZARA_SHADERASTUTILS_HPP + +#include +#include +#include +#include +#include + +namespace Nz +{ + class ShaderAst; + + class NAZARA_SHADER_API ShaderAstValueCategory final : public ShaderAstVisitorExcept + { + public: + ShaderAstValueCategory() = default; + ShaderAstValueCategory(const ShaderAstValueCategory&) = delete; + ShaderAstValueCategory(ShaderAstValueCategory&&) = delete; + ~ShaderAstValueCategory() = default; + + ShaderNodes::ExpressionCategory GetExpressionCategory(const ShaderNodes::ExpressionPtr& expression); + + ShaderAstValueCategory& operator=(const ShaderAstValueCategory&) = delete; + ShaderAstValueCategory& operator=(ShaderAstValueCategory&&) = delete; + + private: + using ShaderAstVisitorExcept::Visit; + void Visit(ShaderNodes::AccessMember& node) override; + void Visit(ShaderNodes::AssignOp& node) override; + void Visit(ShaderNodes::BinaryOp& node) override; + void Visit(ShaderNodes::Cast& node) override; + void Visit(ShaderNodes::ConditionalExpression& node) override; + void Visit(ShaderNodes::Constant& node) override; + void Visit(ShaderNodes::Identifier& node) override; + void Visit(ShaderNodes::IntrinsicCall& node) override; + void Visit(ShaderNodes::Sample2D& node) override; + void Visit(ShaderNodes::SwizzleOp& node) override; + + ShaderNodes::ExpressionCategory m_expressionCategory; + }; + + inline ShaderNodes::ExpressionCategory GetExpressionCategory(const ShaderNodes::ExpressionPtr& expression); +} + +#include + +#endif diff --git a/include/Nazara/Shader/ShaderAstUtils.inl b/include/Nazara/Shader/ShaderAstUtils.inl new file mode 100644 index 000000000..852b2e685 --- /dev/null +++ b/include/Nazara/Shader/ShaderAstUtils.inl @@ -0,0 +1,17 @@ +// 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 +#include + +namespace Nz +{ + ShaderNodes::ExpressionCategory GetExpressionCategory(const ShaderNodes::ExpressionPtr& expression) + { + ShaderAstValueCategory visitor; + return visitor.GetExpressionCategory(expression); + } +} + +#include diff --git a/include/Nazara/Shader/ShaderNodes.hpp b/include/Nazara/Shader/ShaderNodes.hpp index 5a8f28ce7..e2e082b97 100644 --- a/include/Nazara/Shader/ShaderNodes.hpp +++ b/include/Nazara/Shader/ShaderNodes.hpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -55,12 +56,11 @@ namespace Nz using ExpressionPtr = std::shared_ptr; - class NAZARA_SHADER_API Expression : public Node + class NAZARA_SHADER_API Expression : public Node, public std::enable_shared_from_this { public: inline Expression(NodeType type); - virtual ExpressionCategory GetExpressionCategory() const; virtual ShaderExpressionType GetExpressionType() const = 0; }; @@ -68,7 +68,7 @@ namespace Nz using StatementPtr = std::shared_ptr; - class NAZARA_SHADER_API Statement : public Node + class NAZARA_SHADER_API Statement : public Node, public std::enable_shared_from_this { public: inline Statement(NodeType type); @@ -136,7 +136,6 @@ namespace Nz { inline Identifier(); - ExpressionCategory GetExpressionCategory() const override; ShaderExpressionType GetExpressionType() const override; void Visit(ShaderAstVisitor& visitor) override; @@ -149,7 +148,6 @@ namespace Nz { inline AccessMember(); - ExpressionCategory GetExpressionCategory() const override; ShaderExpressionType GetExpressionType() const override; void Visit(ShaderAstVisitor& visitor) override; @@ -265,7 +263,6 @@ namespace Nz { inline SwizzleOp(); - ExpressionCategory GetExpressionCategory() const override; ShaderExpressionType GetExpressionType() const override; void Visit(ShaderAstVisitor& visitor) override; diff --git a/src/Nazara/Shader/GlslWriter.cpp b/src/Nazara/Shader/GlslWriter.cpp index 6179f094b..e1f32d414 100644 --- a/src/Nazara/Shader/GlslWriter.cpp +++ b/src/Nazara/Shader/GlslWriter.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -349,7 +350,7 @@ namespace Nz void GlslWriter::Visit(ShaderNodes::ExpressionPtr& expr, bool encloseIfRequired) { - bool enclose = encloseIfRequired && (expr->GetExpressionCategory() != ShaderNodes::ExpressionCategory::LValue); + bool enclose = encloseIfRequired && (GetExpressionCategory(expr) != ShaderNodes::ExpressionCategory::LValue); if (enclose) Append("("); @@ -461,7 +462,6 @@ namespace Nz Append(")"); } - void GlslWriter::Visit(ShaderNodes::ConditionalExpression& node) { std::size_t conditionIndex = m_context.shader->FindConditionByName(node.conditionName); diff --git a/src/Nazara/Shader/ShaderAstUtils.cpp b/src/Nazara/Shader/ShaderAstUtils.cpp new file mode 100644 index 000000000..d13571ded --- /dev/null +++ b/src/Nazara/Shader/ShaderAstUtils.cpp @@ -0,0 +1,73 @@ +// 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 +#include + +namespace Nz +{ + ShaderNodes::ExpressionCategory ShaderAstValueCategory::GetExpressionCategory(const ShaderNodes::ExpressionPtr& expression) + { + Visit(expression); + return m_expressionCategory; + } + + void ShaderAstValueCategory::Visit(ShaderNodes::AccessMember& node) + { + Visit(node.structExpr); + } + + void ShaderAstValueCategory::Visit(ShaderNodes::AssignOp& node) + { + m_expressionCategory = ShaderNodes::ExpressionCategory::RValue; + } + + void ShaderAstValueCategory::Visit(ShaderNodes::BinaryOp& node) + { + m_expressionCategory = ShaderNodes::ExpressionCategory::RValue; + } + + void ShaderAstValueCategory::Visit(ShaderNodes::Cast& node) + { + m_expressionCategory = ShaderNodes::ExpressionCategory::RValue; + } + + void ShaderAstValueCategory::Visit(ShaderNodes::ConditionalExpression& node) + { + Visit(node.truePath); + ShaderNodes::ExpressionCategory trueExprCategory = m_expressionCategory; + Visit(node.falsePath); + ShaderNodes::ExpressionCategory falseExprCategory = m_expressionCategory; + + if (trueExprCategory == ShaderNodes::ExpressionCategory::RValue || falseExprCategory == ShaderNodes::ExpressionCategory::RValue) + m_expressionCategory = ShaderNodes::ExpressionCategory::RValue; + else + m_expressionCategory = ShaderNodes::ExpressionCategory::LValue; + } + + void ShaderAstValueCategory::Visit(ShaderNodes::Constant& node) + { + m_expressionCategory = ShaderNodes::ExpressionCategory::RValue; + } + + void ShaderAstValueCategory::Visit(ShaderNodes::Identifier& node) + { + m_expressionCategory = ShaderNodes::ExpressionCategory::LValue; + } + + void ShaderAstValueCategory::Visit(ShaderNodes::IntrinsicCall& node) + { + m_expressionCategory = ShaderNodes::ExpressionCategory::RValue; + } + + void ShaderAstValueCategory::Visit(ShaderNodes::Sample2D& node) + { + m_expressionCategory = ShaderNodes::ExpressionCategory::RValue; + } + + void ShaderAstValueCategory::Visit(ShaderNodes::SwizzleOp& node) + { + Visit(node.expression); + } +} diff --git a/src/Nazara/Shader/ShaderAstValidator.cpp b/src/Nazara/Shader/ShaderAstValidator.cpp index 90f8aeef2..ec2d9a7d7 100644 --- a/src/Nazara/Shader/ShaderAstValidator.cpp +++ b/src/Nazara/Shader/ShaderAstValidator.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -126,7 +127,7 @@ namespace Nz MandatoryNode(node.right); TypeMustMatch(node.left, node.right); - if (node.left->GetExpressionCategory() != ShaderNodes::ExpressionCategory::LValue) + if (GetExpressionCategory(node.left) != ShaderNodes::ExpressionCategory::LValue) throw AstError { "Assignation is only possible with a l-value" }; ShaderAstRecursiveVisitor::Visit(node); @@ -221,7 +222,10 @@ namespace Nz { for (const auto& condStatement : node.condStatements) { - MandatoryNode(condStatement.condition); + const ShaderExpressionType& condType = MandatoryExpr(condStatement.condition)->GetExpressionType(); + if (!IsBasicType(condType) || std::get(condType) != ShaderNodes::BasicType::Boolean) + throw AstError{ "if expression must resolve to boolean type" }; + MandatoryNode(condStatement.statement); } diff --git a/src/Nazara/Shader/ShaderNodes.cpp b/src/Nazara/Shader/ShaderNodes.cpp index 8d96c40ea..0e617297a 100644 --- a/src/Nazara/Shader/ShaderNodes.cpp +++ b/src/Nazara/Shader/ShaderNodes.cpp @@ -13,11 +13,6 @@ namespace Nz::ShaderNodes { Node::~Node() = default; - ExpressionCategory Expression::GetExpressionCategory() const - { - return ExpressionCategory::RValue; - } - void ExpressionStatement::Visit(ShaderAstVisitor& visitor) { visitor.Visit(*this); @@ -48,11 +43,6 @@ namespace Nz::ShaderNodes } - ExpressionCategory Identifier::GetExpressionCategory() const - { - return ExpressionCategory::LValue; - } - ShaderExpressionType Identifier::GetExpressionType() const { assert(var); @@ -64,11 +54,6 @@ namespace Nz::ShaderNodes visitor.Visit(*this); } - ExpressionCategory AccessMember::GetExpressionCategory() const - { - return structExpr->GetExpressionCategory(); - } - ShaderExpressionType AccessMember::GetExpressionType() const { return exprType; @@ -231,11 +216,6 @@ namespace Nz::ShaderNodes } - ExpressionCategory SwizzleOp::GetExpressionCategory() const - { - return expression->GetExpressionCategory(); - } - ShaderExpressionType SwizzleOp::GetExpressionType() const { const ShaderExpressionType& exprType = expression->GetExpressionType(); diff --git a/src/Nazara/Shader/SpirvExpressionLoad.cpp b/src/Nazara/Shader/SpirvExpressionLoad.cpp index b82d9b046..93af139e0 100644 --- a/src/Nazara/Shader/SpirvExpressionLoad.cpp +++ b/src/Nazara/Shader/SpirvExpressionLoad.cpp @@ -13,7 +13,7 @@ namespace Nz namespace { template struct overloaded : Ts... { using Ts::operator()...; }; - template overloaded(Ts...)->overloaded; + template overloaded(Ts...) -> overloaded; } UInt32 SpirvExpressionLoad::Evaluate(ShaderNodes::Expression& node) diff --git a/src/ShaderNode/ShaderGraph.cpp b/src/ShaderNode/ShaderGraph.cpp index d385b098d..21be5ec9a 100644 --- a/src/ShaderNode/ShaderGraph.cpp +++ b/src/ShaderNode/ShaderGraph.cpp @@ -531,7 +531,7 @@ Nz::ShaderNodes::StatementPtr ShaderGraph::ToAst() auto expression = std::static_pointer_cast(astNode); Nz::ShaderNodes::ExpressionPtr varExpression; - if (expression->GetExpressionCategory() == Nz::ShaderNodes::ExpressionCategory::RValue) + if (Nz::GetExpressionCategory(expression) == Nz::ShaderNodes::ExpressionCategory::RValue) { std::string name; if (variableName.empty()) From c8f4e53244572ef9ce7142e84f494c4ee2e01140 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 14 Jan 2021 22:02:34 +0100 Subject: [PATCH 034/278] ShaderNode: Add code output window --- src/ShaderNode/ShaderGraph.cpp | 59 +++++++- src/ShaderNode/ShaderGraph.hpp | 6 +- src/ShaderNode/Widgets/CodeOutputWidget.cpp | 105 ++++++++++++++ src/ShaderNode/Widgets/CodeOutputWidget.hpp | 32 +++++ src/ShaderNode/Widgets/CodeOutputWidget.inl | 1 + src/ShaderNode/Widgets/MainWindow.cpp | 145 ++++++-------------- src/ShaderNode/Widgets/MainWindow.hpp | 4 - 7 files changed, 245 insertions(+), 107 deletions(-) create mode 100644 src/ShaderNode/Widgets/CodeOutputWidget.cpp create mode 100644 src/ShaderNode/Widgets/CodeOutputWidget.hpp create mode 100644 src/ShaderNode/Widgets/CodeOutputWidget.inl diff --git a/src/ShaderNode/ShaderGraph.cpp b/src/ShaderNode/ShaderGraph.cpp index 21be5ec9a..4900c5893 100644 --- a/src/ShaderNode/ShaderGraph.cpp +++ b/src/ShaderNode/ShaderGraph.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -62,6 +63,7 @@ m_type(ShaderType::NotSet) }); // Test + m_type = ShaderType::Fragment; AddInput("UV", PrimitiveType::Float2, InputRole::TexCoord, 0, 0); AddOutput("RenderTarget0", PrimitiveType::Float4, 0); AddTexture("Potato", TextureType::Sampler2D, 1); @@ -440,7 +442,7 @@ QJsonObject ShaderGraph::Save() return sceneJson; } -Nz::ShaderNodes::StatementPtr ShaderGraph::ToAst() +Nz::ShaderNodes::StatementPtr ShaderGraph::ToAst() const { std::vector statements; @@ -580,6 +582,61 @@ Nz::ShaderNodes::StatementPtr ShaderGraph::ToAst() return Nz::ShaderNodes::StatementBlock::Build(std::move(statements)); } +Nz::ShaderAst ShaderGraph::ToShader() const +{ + Nz::ShaderAst shader(ShaderGraph::ToShaderStageType(m_type)); //< FIXME + for (const auto& condition : m_conditions) + shader.AddCondition(condition.name); + + for (const auto& input : m_inputs) + shader.AddInput(input.name, ToShaderExpressionType(input.type), input.locationIndex); + + for (const auto& output : m_outputs) + shader.AddOutput(output.name, ToShaderExpressionType(output.type), output.locationIndex); + + for (const auto& buffer : m_buffers) + { + if (buffer.structIndex >= m_structs.size()) + throw std::runtime_error("buffer " + buffer.name + " references out-of-bounds struct #" + std::to_string(buffer.structIndex)); + + const auto& structInfo = m_structs[buffer.structIndex]; + shader.AddUniform(buffer.name, structInfo.name, buffer.bindingIndex, Nz::ShaderNodes::MemoryLayout::Std140); + } + + for (const auto& uniform : m_textures) + shader.AddUniform(uniform.name, ToShaderExpressionType(uniform.type), uniform.bindingIndex, {}); + + for (const auto& s : m_structs) + { + std::vector members; + for (const auto& sMember : s.members) + { + auto& member = members.emplace_back(); + member.name = sMember.name; + + std::visit([&](auto&& arg) + { + using T = std::decay_t; + if constexpr (std::is_same_v) + member.type = ToShaderExpressionType(arg); + else if constexpr (std::is_same_v) + { + if (arg >= m_structs.size()) + throw std::runtime_error("struct " + s.name + " references out-of-bounds struct #" + std::to_string(arg)); + + member.type = m_structs[arg].name; + } + else + static_assert(AlwaysFalse::value, "non-exhaustive visitor"); + }, sMember.type); + } + + shader.AddStruct(s.name, std::move(members)); + } + + return shader; +} + Nz::ShaderExpressionType ShaderGraph::ToShaderExpressionType(const std::variant& type) const { return std::visit([&](auto&& arg) -> Nz::ShaderExpressionType diff --git a/src/ShaderNode/ShaderGraph.hpp b/src/ShaderNode/ShaderGraph.hpp index 44fb4bf77..1ca776305 100644 --- a/src/ShaderNode/ShaderGraph.hpp +++ b/src/ShaderNode/ShaderGraph.hpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -66,7 +67,8 @@ class ShaderGraph void Load(const QJsonObject& data); QJsonObject Save(); - Nz::ShaderNodes::StatementPtr ToAst(); + Nz::ShaderNodes::StatementPtr ToAst() const; + Nz::ShaderAst ToShader() const; Nz::ShaderExpressionType ToShaderExpressionType(const std::variant& type) const; void UpdateBuffer(std::size_t bufferIndex, std::string name, BufferType bufferType, std::size_t structIndex, std::size_t bindingIndex); @@ -152,7 +154,7 @@ class ShaderGraph private: std::shared_ptr BuildRegistry(); - QtNodes::FlowScene m_flowScene; + mutable QtNodes::FlowScene m_flowScene; std::vector m_buffers; std::vector m_conditions; std::vector m_inputs; diff --git a/src/ShaderNode/Widgets/CodeOutputWidget.cpp b/src/ShaderNode/Widgets/CodeOutputWidget.cpp new file mode 100644 index 000000000..73e9c7d3f --- /dev/null +++ b/src/ShaderNode/Widgets/CodeOutputWidget.cpp @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum class OutputLanguage +{ + GLSL, + SpirV +}; + +CodeOutputWidget::CodeOutputWidget(const ShaderGraph& shaderGraph) : +m_shaderGraph(shaderGraph) +{ + m_textOutput = new QTextEdit; + + m_outputLang = new QComboBox; + m_outputLang->addItem("GLSL", int(OutputLanguage::GLSL)); + m_outputLang->addItem("SPIR-V", int(OutputLanguage::SpirV)); + connect(m_outputLang, qOverload(&QComboBox::currentIndexChanged), [this](int) + { + Refresh(); + }); + + m_optimisationCheckbox = new QCheckBox; + m_optimisationCheckbox->setText("Enable optimisation"); + connect(m_optimisationCheckbox, &QCheckBox::stateChanged, [this](int) + { + Refresh(); + }); + + QVBoxLayout* verticalLayout = new QVBoxLayout; + verticalLayout->addWidget(m_textOutput); + verticalLayout->addWidget(m_outputLang); + verticalLayout->addWidget(m_optimisationCheckbox); + + setLayout(verticalLayout); + + Refresh(); +} + +void CodeOutputWidget::Refresh() +{ + try + { + Nz::UInt64 enabledConditions = 0; + for (std::size_t i = 0; i < m_shaderGraph.GetConditionCount(); ++i) + { + if (m_shaderGraph.IsConditionEnabled(i)) + enabledConditions = Nz::SetBit(enabledConditions, i); + } + + Nz::ShaderAst shaderAst = m_shaderGraph.ToShader(); + + Nz::ShaderNodes::StatementPtr mainAst = m_shaderGraph.ToAst(); + if (m_optimisationCheckbox->isChecked()) + { + Nz::ShaderAstOptimizer optimiser; + mainAst = optimiser.Optimise(mainAst, shaderAst, enabledConditions); + } + + shaderAst.AddFunction("main", mainAst); + + Nz::ShaderWriter::States states; + states.enabledConditions = enabledConditions; + + std::string output; + OutputLanguage outputLang = static_cast(m_outputLang->currentIndex()); + switch (outputLang) + { + case OutputLanguage::GLSL: + { + Nz::GlslWriter writer; + output = writer.Generate(shaderAst, states); + break; + } + + case OutputLanguage::SpirV: + { + Nz::SpirvWriter writer; + std::vector spirv = writer.Generate(shaderAst, states); + + Nz::SpirvPrinter printer; + output = printer.Print(spirv.data(), spirv.size()); + break; + } + } + + int scrollValue = m_textOutput->verticalScrollBar()->value(); + m_textOutput->setText(QString::fromStdString(output)); + m_textOutput->verticalScrollBar()->setValue(scrollValue); + } + catch (const std::exception& e) + { + m_textOutput->setText("Generation failed: " + QString::fromStdString(e.what())); + } +} diff --git a/src/ShaderNode/Widgets/CodeOutputWidget.hpp b/src/ShaderNode/Widgets/CodeOutputWidget.hpp new file mode 100644 index 000000000..ecea4d54b --- /dev/null +++ b/src/ShaderNode/Widgets/CodeOutputWidget.hpp @@ -0,0 +1,32 @@ +#pragma once + +#ifndef NAZARA_SHADERNODES_CODEOUTPUTWIDGET_HPP +#define NAZARA_SHADERNODES_CODEOUTPUTWIDGET_HPP + +#include +#include +#include + +class QCheckBox; +class QComboBox; +class QTextEdit; +class ShaderGraph; + +class CodeOutputWidget : public QWidget +{ + public: + CodeOutputWidget(const ShaderGraph& shaderGraph); + ~CodeOutputWidget() = default; + + void Refresh(); + + private: + const ShaderGraph& m_shaderGraph; + QCheckBox* m_optimisationCheckbox; + QComboBox* m_outputLang; + QTextEdit* m_textOutput; +}; + +#include + +#endif diff --git a/src/ShaderNode/Widgets/CodeOutputWidget.inl b/src/ShaderNode/Widgets/CodeOutputWidget.inl new file mode 100644 index 000000000..26a824b63 --- /dev/null +++ b/src/ShaderNode/Widgets/CodeOutputWidget.inl @@ -0,0 +1 @@ +#include diff --git a/src/ShaderNode/Widgets/MainWindow.cpp b/src/ShaderNode/Widgets/MainWindow.cpp index aa01c3c97..c131a123c 100644 --- a/src/ShaderNode/Widgets/MainWindow.cpp +++ b/src/ShaderNode/Widgets/MainWindow.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -14,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -35,7 +37,6 @@ m_shaderGraph(graph) InputEditor* inputEditor = new InputEditor(m_shaderGraph); QDockWidget* inputDock = new QDockWidget(tr("Inputs")); - inputDock->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable); inputDock->setWidget(inputEditor); addDockWidget(Qt::LeftDockWidgetArea, inputDock); @@ -44,7 +45,6 @@ m_shaderGraph(graph) OutputEditor* outputEditor = new OutputEditor(m_shaderGraph); QDockWidget* outputDock = new QDockWidget(tr("Outputs")); - outputDock->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable); outputDock->setWidget(outputEditor); addDockWidget(Qt::LeftDockWidgetArea, outputDock); @@ -53,7 +53,6 @@ m_shaderGraph(graph) TextureEditor* textureEditor = new TextureEditor(m_shaderGraph); QDockWidget* textureDock = new QDockWidget(tr("Textures")); - textureDock->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable); textureDock->setWidget(textureEditor); addDockWidget(Qt::LeftDockWidgetArea, textureDock); @@ -62,7 +61,6 @@ m_shaderGraph(graph) m_nodeEditor = new NodeEditor; QDockWidget* nodeEditorDock = new QDockWidget(tr("Node editor")); - nodeEditorDock->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable); nodeEditorDock->setWidget(m_nodeEditor); addDockWidget(Qt::RightDockWidgetArea, nodeEditorDock); @@ -71,7 +69,6 @@ m_shaderGraph(graph) BufferEditor* bufferEditor = new BufferEditor(m_shaderGraph); QDockWidget* bufferDock = new QDockWidget(tr("Buffers")); - bufferDock->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable); bufferDock->setWidget(bufferEditor); addDockWidget(Qt::RightDockWidgetArea, bufferDock); @@ -80,7 +77,6 @@ m_shaderGraph(graph) StructEditor* structEditor = new StructEditor(m_shaderGraph); QDockWidget* structDock = new QDockWidget(tr("Structs")); - structDock->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable); structDock->setWidget(structEditor); addDockWidget(Qt::RightDockWidgetArea, structDock); @@ -89,11 +85,18 @@ m_shaderGraph(graph) ConditionEditor* conditionEditor = new ConditionEditor(m_shaderGraph); QDockWidget* conditionDock = new QDockWidget(tr("Conditions")); - conditionDock->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable); conditionDock->setWidget(conditionEditor); addDockWidget(Qt::RightDockWidgetArea, conditionDock); + // Code output + CodeOutputWidget* codeOutput = new CodeOutputWidget(m_shaderGraph); + + QDockWidget* codeOutputDock = new QDockWidget(tr("Code output")); + codeOutputDock->setWidget(codeOutput); + + addDockWidget(Qt::BottomDockWidgetArea, codeOutputDock); + m_onSelectedNodeUpdate.Connect(m_shaderGraph.OnSelectedNodeUpdate, [&](ShaderGraph*, ShaderNode* node) { if (node) @@ -109,21 +112,46 @@ m_shaderGraph(graph) BuildMenu(); - - m_codeOutput = new QTextEdit; - m_codeOutput->setReadOnly(true); - m_codeOutput->setWindowTitle("GLSL Output"); - - m_onConditionUpdate.Connect(m_shaderGraph.OnConditionUpdate, [&](ShaderGraph*, std::size_t conditionIndex) { - if (m_codeOutput->isVisible()) - OnGenerateGLSL(); + QMenu* view = menuBar()->addMenu("View"); + view->addAction(inputDock->toggleViewAction()); + view->addAction(outputDock->toggleViewAction()); + view->addAction(textureDock->toggleViewAction()); + view->addAction(nodeEditorDock->toggleViewAction()); + view->addAction(bufferDock->toggleViewAction()); + view->addAction(structDock->toggleViewAction()); + view->addAction(conditionDock->toggleViewAction()); + view->addAction(codeOutputDock->toggleViewAction()); + } + + connect(scene, &QtNodes::FlowScene::connectionCreated, [=](const QtNodes::Connection& /*connection*/) + { + QTimer::singleShot(0, [=] + { + if (codeOutput->isVisible()) + codeOutput->Refresh(); + }); + }); + + connect(scene, &QtNodes::FlowScene::connectionDeleted, [=](const QtNodes::Connection& /*connection*/) + { + QTimer::singleShot(0, [=] + { + if (codeOutput->isVisible()) + codeOutput->Refresh(); + }); + }); + + m_onConditionUpdate.Connect(m_shaderGraph.OnConditionUpdate, [=](ShaderGraph*, std::size_t /*conditionIndex*/) + { + if (codeOutput->isVisible()) + codeOutput->Refresh(); }); } MainWindow::~MainWindow() { - delete m_codeOutput; + m_shaderGraph.Clear(); } void MainWindow::BuildMenu() @@ -147,19 +175,13 @@ void MainWindow::BuildMenu() 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(); }); - } } void MainWindow::OnCompile() { try { - auto shader = ToShader(); + auto shader = m_shaderGraph.ToShader(); QString fileName = QFileDialog::getSaveFileName(nullptr, tr("Save shader"), QString(), tr("Shader Files (*.shader)")); if (fileName.isEmpty()) @@ -177,32 +199,6 @@ void MainWindow::OnCompile() } } -void MainWindow::OnGenerateGLSL() -{ - try - { - Nz::GlslWriter writer; - - Nz::GlslWriter::States states; - for (std::size_t i = 0; i < m_shaderGraph.GetConditionCount(); ++i) - { - if (m_shaderGraph.IsConditionEnabled(i)) - states.enabledConditions = Nz::SetBit(states.enabledConditions, i); - } - - std::string glsl = writer.Generate(ToShader(), states); - - std::cout << glsl << std::endl; - - m_codeOutput->setText(QString::fromStdString(glsl)); - m_codeOutput->show(); - } - catch (const std::exception& e) - { - QMessageBox::critical(this, tr("Generation failed"), QString("Generation failed: ") + e.what()); - } -} - void MainWindow::OnLoad() { QString fileName = QFileDialog::getOpenFileName(this, tr("Open shader flow"), QString(), tr("Shader Flow Files (*.shaderflow)")); @@ -263,54 +259,3 @@ void MainWindow::OnUpdateInfo() dialog->open(); } - -Nz::ShaderAst MainWindow::ToShader() -{ - Nz::ShaderNodes::StatementPtr shaderAst = m_shaderGraph.ToAst(); - - Nz::ShaderAst shader(ShaderGraph::ToShaderStageType(m_shaderGraph.GetType())); //< FIXME - for (const auto& condition : m_shaderGraph.GetConditions()) - shader.AddCondition(condition.name); - - for (const auto& input : m_shaderGraph.GetInputs()) - shader.AddInput(input.name, m_shaderGraph.ToShaderExpressionType(input.type), input.locationIndex); - - for (const auto& output : m_shaderGraph.GetOutputs()) - shader.AddOutput(output.name, m_shaderGraph.ToShaderExpressionType(output.type), output.locationIndex); - - for (const auto& buffer : m_shaderGraph.GetBuffers()) - { - const auto& structInfo = m_shaderGraph.GetStruct(buffer.structIndex); - shader.AddUniform(buffer.name, structInfo.name, buffer.bindingIndex, Nz::ShaderNodes::MemoryLayout::Std140); - } - - for (const auto& uniform : m_shaderGraph.GetTextures()) - shader.AddUniform(uniform.name, m_shaderGraph.ToShaderExpressionType(uniform.type), uniform.bindingIndex, {}); - - for (const auto& s : m_shaderGraph.GetStructs()) - { - std::vector members; - for (const auto& sMember : s.members) - { - auto& member = members.emplace_back(); - member.name = sMember.name; - - std::visit([&](auto&& arg) - { - using T = std::decay_t; - if constexpr (std::is_same_v) - member.type = m_shaderGraph.ToShaderExpressionType(arg); - else if constexpr (std::is_same_v) - member.type = m_shaderGraph.GetStruct(arg).name; - else - static_assert(AlwaysFalse::value, "non-exhaustive visitor"); - }, sMember.type); - } - - shader.AddStruct(s.name, std::move(members)); - } - - shader.AddFunction("main", shaderAst); - - return shader; -} diff --git a/src/ShaderNode/Widgets/MainWindow.hpp b/src/ShaderNode/Widgets/MainWindow.hpp index 10d925190..1031eca9a 100644 --- a/src/ShaderNode/Widgets/MainWindow.hpp +++ b/src/ShaderNode/Widgets/MainWindow.hpp @@ -8,7 +8,6 @@ #include class NodeEditor; -class QTextEdit; namespace Nz { @@ -24,18 +23,15 @@ class MainWindow : public QMainWindow private: void BuildMenu(); void OnCompile(); - void OnGenerateGLSL(); void OnLoad(); void OnSave(); void OnUpdateInfo(); - Nz::ShaderAst ToShader(); NazaraSlot(ShaderGraph, OnConditionUpdate, m_onConditionUpdate); NazaraSlot(ShaderGraph, OnSelectedNodeUpdate, m_onSelectedNodeUpdate); NodeEditor* m_nodeEditor; ShaderGraph& m_shaderGraph; - QTextEdit* m_codeOutput; }; #include From 96d7b9424b1c99b19dd9ffe5132014b85d818b88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 14 Jan 2021 22:03:01 +0100 Subject: [PATCH 035/278] Renderer: Handle null textures in shader binding --- .../OpenGLRenderer/OpenGLShaderBinding.cpp | 73 ++++++++++++------- .../VulkanRenderer/VulkanShaderBinding.cpp | 14 ++-- 2 files changed, 51 insertions(+), 36 deletions(-) diff --git a/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp b/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp index adca247e9..492331cc0 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp @@ -65,38 +65,49 @@ namespace Nz const TextureBinding& texBinding = std::get(binding.content); - OpenGLTexture& glTexture = static_cast(*texBinding.texture); - OpenGLTextureSampler& glSampler = static_cast(*texBinding.sampler); - auto& textureDescriptor = m_owner.GetTextureDescriptor(m_poolIndex, m_bindingIndex, resourceIndex); textureDescriptor.bindingIndex = binding.bindingIndex; - textureDescriptor.texture = glTexture.GetTexture().GetObjectId(); - textureDescriptor.sampler = glSampler.GetSampler(glTexture.GetLevelCount() > 1).GetObjectId(); - - switch (glTexture.GetType()) + if (OpenGLTexture* glTexture = static_cast(texBinding.texture)) { - case ImageType_2D: - textureDescriptor.textureTarget = GL::TextureTarget::Target2D; - break; + textureDescriptor.texture = glTexture->GetTexture().GetObjectId(); - case ImageType_2D_Array: - textureDescriptor.textureTarget = GL::TextureTarget::Target2D_Array; - break; + if (OpenGLTextureSampler* glSampler = static_cast(texBinding.sampler)) + textureDescriptor.sampler = glSampler->GetSampler(glTexture->GetLevelCount() > 1).GetObjectId(); + else + textureDescriptor.sampler = 0; - case ImageType_3D: - textureDescriptor.textureTarget = GL::TextureTarget::Target3D; - break; + switch (glTexture->GetType()) + { + case ImageType_2D: + textureDescriptor.textureTarget = GL::TextureTarget::Target2D; + break; - case ImageType_Cubemap: - textureDescriptor.textureTarget = GL::TextureTarget::Cubemap; - break; + case ImageType_2D_Array: + textureDescriptor.textureTarget = GL::TextureTarget::Target2D_Array; + break; - case ImageType_1D: - case ImageType_1D_Array: - default: - throw std::runtime_error("unsupported texture type"); + case ImageType_3D: + textureDescriptor.textureTarget = GL::TextureTarget::Target3D; + break; + + case ImageType_Cubemap: + textureDescriptor.textureTarget = GL::TextureTarget::Cubemap; + break; + + case ImageType_1D: + case ImageType_1D_Array: + default: + throw std::runtime_error("unsupported texture type"); + } } + else + { + textureDescriptor.sampler = 0; + textureDescriptor.texture = 0; + textureDescriptor.textureTarget = GL::TextureTarget::Target2D; + } + break; } @@ -107,15 +118,21 @@ namespace Nz const UniformBufferBinding& uboBinding = std::get(binding.content); - OpenGLBuffer& glBuffer = *static_cast(uboBinding.buffer); - if (glBuffer.GetType() != BufferType_Uniform) - throw std::runtime_error("expected uniform buffer"); - auto& uboDescriptor = m_owner.GetUniformBufferDescriptor(m_poolIndex, m_bindingIndex, resourceIndex); uboDescriptor.bindingIndex = binding.bindingIndex; - uboDescriptor.buffer = glBuffer.GetBuffer().GetObjectId(); uboDescriptor.offset = uboBinding.offset; uboDescriptor.size = uboBinding.range; + + if (OpenGLBuffer* glBuffer = static_cast(uboBinding.buffer)) + { + if (glBuffer->GetType() != BufferType_Uniform) + throw std::runtime_error("expected uniform buffer"); + + uboDescriptor.buffer = glBuffer->GetBuffer().GetObjectId(); + } + else + uboDescriptor.buffer = 0; + break; } } diff --git a/src/Nazara/VulkanRenderer/VulkanShaderBinding.cpp b/src/Nazara/VulkanRenderer/VulkanShaderBinding.cpp index 58f9731ac..bf86a2989 100644 --- a/src/Nazara/VulkanRenderer/VulkanShaderBinding.cpp +++ b/src/Nazara/VulkanRenderer/VulkanShaderBinding.cpp @@ -32,31 +32,29 @@ namespace Nz if constexpr (std::is_same_v) { - VulkanTexture& vkTexture = *static_cast(arg.texture); - VulkanTextureSampler& vkSampler = *static_cast(arg.sampler); + VulkanTexture* vkTexture = static_cast(arg.texture); + VulkanTextureSampler* vkSampler = static_cast(arg.sampler); VkDescriptorImageInfo& imageInfo = imageBinding.emplace_back(); imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - imageInfo.imageView = vkTexture.GetImageView(); - imageInfo.sampler = vkSampler.GetSampler(); + imageInfo.imageView = (vkTexture) ? vkTexture->GetImageView() : VK_NULL_HANDLE; + imageInfo.sampler = (vkSampler) ? vkSampler->GetSampler() : VK_NULL_HANDLE; writeOp.descriptorCount = 1; writeOp.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - writeOp.pImageInfo = &imageInfo; } else if constexpr (std::is_same_v) { - VulkanBuffer& vkBuffer = *static_cast(arg.buffer); + VulkanBuffer* vkBuffer = static_cast(arg.buffer); VkDescriptorBufferInfo& bufferInfo = bufferBinding.emplace_back(); - bufferInfo.buffer = vkBuffer.GetBuffer(); + bufferInfo.buffer = (vkBuffer) ? vkBuffer->GetBuffer() : VK_NULL_HANDLE; bufferInfo.offset = arg.offset; bufferInfo.range = arg.range; writeOp.descriptorCount = 1; writeOp.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - writeOp.pBufferInfo = &bufferInfo; } else From bb18ca13ca3133f12426a8e8091e5fa9af0f45fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 15 Jan 2021 19:19:05 +0100 Subject: [PATCH 036/278] Fix shader generation --- .../basicmaterial.vert.shaderflow | 16 +++++++++------- .../Shaders/basicmaterial.frag.shader | Bin 1745 -> 1745 bytes .../Shaders/basicmaterial.frag.shader.h | 2 +- .../Shaders/basicmaterial.vert.shader | Bin 1050 -> 1050 bytes .../Shaders/basicmaterial.vert.shader.h | 2 +- src/ShaderNode/Widgets/MainWindow.cpp | 1 + 6 files changed, 12 insertions(+), 9 deletions(-) diff --git a/shaders/BasicMaterial/basicmaterial.vert.shaderflow b/shaders/BasicMaterial/basicmaterial.vert.shaderflow index 4ba3f2125..4f51428e2 100644 --- a/shaders/BasicMaterial/basicmaterial.vert.shaderflow +++ b/shaders/BasicMaterial/basicmaterial.vert.shaderflow @@ -19,6 +19,8 @@ "type": "UniformBufferObject" } ], + "conditions": [ + ], "connections": [ { "in_id": "{1bb9712b-8bff-4398-9e4e-fba79a04df0e}", @@ -44,6 +46,12 @@ "out_id": "{33840c70-4e37-4127-bab0-23c4a4cb6d7f}", "out_index": 0 }, + { + "in_id": "{63bb13f0-55e3-451b-860e-568b65e09b04}", + "in_index": 0, + "out_id": "{62731a4b-f054-4f78-82da-08d2584e51ab}", + "out_index": 0 + }, { "in_id": "{7ac65f09-7f55-4a6e-9380-1bee5213f079}", "in_index": 0, @@ -62,12 +70,6 @@ "out_id": "{d8f4d14a-c67a-470f-87bf-8f60d9513c3b}", "out_index": 0 }, - { - "in_id": "{63bb13f0-55e3-451b-860e-568b65e09b04}", - "in_index": 0, - "out_id": "{62731a4b-f054-4f78-82da-08d2584e51ab}", - "out_index": 0 - }, { "in_id": "{0fc53363-dbce-4874-8de5-5ca05ae038b7}", "in_index": 0, @@ -326,7 +328,7 @@ }, { "name": "DiffuseColor", - "type": "Float3" + "type": "Float4" } ], "name": "BasicSettings" diff --git a/src/Nazara/Graphics/Resources/Shaders/basicmaterial.frag.shader b/src/Nazara/Graphics/Resources/Shaders/basicmaterial.frag.shader index 70cdc4d2b1d52a3468c1d90ddbec8d2df18d90ec..b789061b34422e7e9b735af10d87e53e0151a760 100644 GIT binary patch delta 91 zcmcb}dy#j;PbNlz$-kJsF!D`)&-{>)fAU2Z9WbfE%E-XL0OD&%G67jI%nxLP07#Z^ Vat^CKMD^q=tlnUj@ML4Qc>qgT6(#@x delta 91 zcmcb}dy#j;PbNnG$-kJsF!D}*&-{>)Z}LSJ9WbfE%E-XL0OD&%G67jI%m-wH07#a1 Vat^CKMD^q=tlnUj@ML4Qc>qbD6&(No diff --git a/src/Nazara/Graphics/Resources/Shaders/basicmaterial.frag.shader.h b/src/Nazara/Graphics/Resources/Shaders/basicmaterial.frag.shader.h index 7e0653fc3..b75d536e2 100644 --- a/src/Nazara/Graphics/Resources/Shaders/basicmaterial.frag.shader.h +++ b/src/Nazara/Graphics/Resources/Shaders/basicmaterial.frag.shader.h @@ -1 +1 @@ -78,83,72,82,0,0,0,1,0,0,0,0,0,0,0,3,0,0,0,19,72,65,83,95,68,73,70,70,85,83,69,95,84,69,88,84,85,82,69,0,0,0,17,72,65,83,95,65,76,80,72,65,95,84,69,88,84,85,82,69,0,0,0,10,65,76,80,72,65,95,84,69,83,84,0,0,0,3,0,0,0,13,66,97,115,105,99,83,101,116,116,105,110,103,115,0,0,0,2,0,0,0,14,65,108,112,104,97,84,104,114,101,115,104,111,108,100,0,0,0,0,1,0,0,0,12,68,105,102,102,117,115,101,67,111,108,111,114,0,0,0,0,4,0,0,0,12,73,110,115,116,97,110,99,101,68,97,116,97,0,0,0,2,0,0,0,11,119,111,114,108,100,77,97,116,114,105,120,0,0,0,0,9,0,0,0,14,105,110,118,87,111,114,108,100,77,97,116,114,105,120,0,0,0,0,9,0,0,0,10,86,105,101,119,101,114,68,97,116,97,0,0,0,9,0,0,0,16,112,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,0,0,0,0,9,0,0,0,19,105,110,118,80,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,0,0,0,0,9,0,0,0,10,118,105,101,119,77,97,116,114,105,120,0,0,0,0,9,0,0,0,13,105,110,118,86,105,101,119,77,97,116,114,105,120,0,0,0,0,9,0,0,0,14,118,105,101,119,80,114,111,106,77,97,116,114,105,120,0,0,0,0,9,0,0,0,17,105,110,118,86,105,101,119,80,114,111,106,77,97,116,114,105,120,0,0,0,0,9,0,0,0,16,114,101,110,100,101,114,84,97,114,103,101,116,83,105,122,101,0,0,0,0,2,0,0,0,19,105,110,118,82,101,110,100,101,114,84,97,114,103,101,116,83,105,122,101,0,0,0,0,2,0,0,0,11,101,121,101,80,111,115,105,116,105,111,110,0,0,0,0,3,0,0,0,2,0,0,0,10,118,101,114,116,78,111,114,109,97,108,0,0,0,0,3,1,0,0,0,0,0,0,0,6,118,101,114,116,85,86,0,0,0,0,2,1,0,0,0,1,0,0,0,1,0,0,0,13,82,101,110,100,101,114,84,97,114,103,101,116,48,0,0,0,0,4,1,0,0,0,0,0,0,0,6,0,0,0,10,118,105,101,119,101,114,68,97,116,97,1,0,0,0,10,86,105,101,119,101,114,68,97,116,97,1,0,0,0,5,1,0,0,0,0,0,0,0,12,105,110,115,116,97,110,99,101,68,97,116,97,1,0,0,0,12,73,110,115,116,97,110,99,101,68,97,116,97,1,0,0,0,4,1,0,0,0,0,0,0,0,8,115,101,116,116,105,110,103,115,1,0,0,0,13,66,97,115,105,99,83,101,116,116,105,110,103,115,1,0,0,0,3,1,0,0,0,0,0,0,0,16,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,0,0,0,0,10,1,0,0,0,0,0,0,0,0,18,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,0,0,0,0,10,1,0,0,0,1,0,0,0,0,14,84,101,120,116,117,114,101,79,118,101,114,108,97,121,0,0,0,0,10,1,0,0,0,2,0,0,0,0,1,0,0,0,4,109,97,105,110,0,0,0,11,0,0,0,0,0,0,0,15,0,0,0,6,0,0,0,8,0,0,0,2,0,0,0,8,108,105,103,104,116,68,105,114,0,0,0,0,3,0,0,0,5,0,0,0,5,0,0,0,0,191,52,253,244,63,52,253,244,0,0,0,8,0,0,0,2,0,0,0,11,108,105,103,104,116,70,97,99,116,111,114,0,0,0,0,1,0,0,0,12,0,0,0,1,0,0,0,2,0,0,0,11,0,0,0,1,0,0,0,10,118,101,114,116,78,111,114,109,97,108,0,0,0,0,3,0,0,0,11,0,0,0,2,0,0,0,8,108,105,103,104,116,68,105,114,0,0,0,0,3,0,0,0,8,0,0,0,2,0,0,0,12,116,101,120,116,117,114,101,67,111,108,111,114,0,0,0,0,4,0,0,0,2,0,0,0,2,0,0,0,11,0,0,0,2,0,0,0,11,108,105,103,104,116,70,97,99,116,111,114,0,0,0,0,1,0,0,0,6,0,0,0,19,72,65,83,95,68,73,70,70,85,83,69,95,84,69,88,84,85,82,69,0,0,0,2,0,0,0,2,0,0,0,13,0,0,0,11,0,0,0,5,0,0,0,18,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,0,0,0,0,10,0,0,0,11,0,0,0,1,0,0,0,6,118,101,114,116,85,86,0,0,0,0,2,0,0,0,0,0,0,0,11,0,0,0,5,0,0,0,8,115,101,116,116,105,110,103,115,1,0,0,0,13,66,97,115,105,99,83,101,116,116,105,110,103,115,0,0,0,0,4,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,11,0,0,0,5,0,0,0,8,115,101,116,116,105,110,103,115,1,0,0,0,13,66,97,115,105,99,83,101,116,116,105,110,103,115,0,0,0,0,4,0,0,0,1,0,0,0,1,0,0,0,8,0,0,0,2,0,0,0,4,118,97,114,48,0,0,0,0,4,0,0,0,6,0,0,0,17,72,65,83,95,65,76,80,72,65,95,84,69,88,84,85,82,69,0,0,0,4,0,0,0,4,0,0,0,14,0,0,0,0,0,0,0,1,0,0,0,11,0,0,0,2,0,0,0,12,116,101,120,116,117,114,101,67,111,108,111,114,0,0,0,0,4,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,1,0,0,0,11,0,0,0,2,0,0,0,12,116,101,120,116,117,114,101,67,111,108,111,114,0,0,0,0,4,0,0,0,1,0,0,0,14,0,0,0,0,0,0,0,1,0,0,0,11,0,0,0,2,0,0,0,12,116,101,120,116,117,114,101,67,111,108,111,114,0,0,0,0,4,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,14,0,0,0,0,0,0,0,1,0,0,0,13,0,0,0,11,0,0,0,5,0,0,0,16,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,0,0,0,0,10,0,0,0,11,0,0,0,1,0,0,0,6,118,101,114,116,85,86,0,0,0,0,2,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,1,0,0,0,11,0,0,0,2,0,0,0,12,116,101,120,116,117,114,101,67,111,108,111,114,0,0,0,0,4,0,0,0,3,0,0,0,11,0,0,0,2,0,0,0,12,116,101,120,116,117,114,101,67,111,108,111,114,0,0,0,0,4,0,0,0,3,0,0,0,1,0,0,0,2,0,0,0,4,0,0,0,6,0,0,0,10,65,76,80,72,65,95,84,69,83,84,0,0,0,2,0,0,0,8,0,0,0,14,0,0,0,0,0,0,0,1,0,0,0,11,0,0,0,2,0,0,0,4,118,97,114,48,0,0,0,0,4,0,0,0,3,0,0,0,0,0,0,0,11,0,0,0,5,0,0,0,8,115,101,116,116,105,110,103,115,1,0,0,0,13,66,97,115,105,99,83,101,116,116,105,110,103,115,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,5,0,0,0,0,1,0,0,0,9,255,255,255,255,0,0,0,10,0,0,0,1,0,0,0,0,0,0,0,11,0,0,0,3,0,0,0,13,82,101,110,100,101,114,84,97,114,103,101,116,48,0,0,0,0,4,0,0,0,11,0,0,0,2,0,0,0,4,118,97,114,48,0,0,0,0,4, \ No newline at end of file +78,83,72,82,0,0,0,1,0,0,0,0,0,0,0,3,0,0,0,19,72,65,83,95,68,73,70,70,85,83,69,95,84,69,88,84,85,82,69,0,0,0,17,72,65,83,95,65,76,80,72,65,95,84,69,88,84,85,82,69,0,0,0,10,65,76,80,72,65,95,84,69,83,84,0,0,0,3,0,0,0,13,66,97,115,105,99,83,101,116,116,105,110,103,115,0,0,0,2,0,0,0,14,65,108,112,104,97,84,104,114,101,115,104,111,108,100,0,0,0,0,1,0,0,0,12,68,105,102,102,117,115,101,67,111,108,111,114,0,0,0,0,4,0,0,0,12,73,110,115,116,97,110,99,101,68,97,116,97,0,0,0,2,0,0,0,11,119,111,114,108,100,77,97,116,114,105,120,0,0,0,0,9,0,0,0,14,105,110,118,87,111,114,108,100,77,97,116,114,105,120,0,0,0,0,9,0,0,0,10,86,105,101,119,101,114,68,97,116,97,0,0,0,9,0,0,0,16,112,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,0,0,0,0,9,0,0,0,19,105,110,118,80,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,0,0,0,0,9,0,0,0,10,118,105,101,119,77,97,116,114,105,120,0,0,0,0,9,0,0,0,13,105,110,118,86,105,101,119,77,97,116,114,105,120,0,0,0,0,9,0,0,0,14,118,105,101,119,80,114,111,106,77,97,116,114,105,120,0,0,0,0,9,0,0,0,17,105,110,118,86,105,101,119,80,114,111,106,77,97,116,114,105,120,0,0,0,0,9,0,0,0,16,114,101,110,100,101,114,84,97,114,103,101,116,83,105,122,101,0,0,0,0,2,0,0,0,19,105,110,118,82,101,110,100,101,114,84,97,114,103,101,116,83,105,122,101,0,0,0,0,2,0,0,0,11,101,121,101,80,111,115,105,116,105,111,110,0,0,0,0,3,0,0,0,2,0,0,0,10,118,101,114,116,78,111,114,109,97,108,0,0,0,0,3,1,0,0,0,0,0,0,0,6,118,101,114,116,85,86,0,0,0,0,2,1,0,0,0,1,0,0,0,1,0,0,0,13,82,101,110,100,101,114,84,97,114,103,101,116,48,0,0,0,0,4,1,0,0,0,0,0,0,0,6,0,0,0,10,118,105,101,119,101,114,68,97,116,97,1,0,0,0,10,86,105,101,119,101,114,68,97,116,97,1,0,0,0,5,1,0,0,0,0,0,0,0,12,105,110,115,116,97,110,99,101,68,97,116,97,1,0,0,0,12,73,110,115,116,97,110,99,101,68,97,116,97,1,0,0,0,4,1,0,0,0,0,0,0,0,8,115,101,116,116,105,110,103,115,1,0,0,0,13,66,97,115,105,99,83,101,116,116,105,110,103,115,1,0,0,0,3,1,0,0,0,0,0,0,0,16,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,0,0,0,0,10,1,0,0,0,0,0,0,0,0,18,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,0,0,0,0,10,1,0,0,0,1,0,0,0,0,14,84,101,120,116,117,114,101,79,118,101,114,108,97,121,0,0,0,0,10,1,0,0,0,2,0,0,0,0,1,0,0,0,4,109,97,105,110,0,0,0,11,0,0,0,0,0,0,0,16,0,0,0,6,0,0,0,8,0,0,0,2,0,0,0,8,108,105,103,104,116,68,105,114,0,0,0,0,3,0,0,0,5,0,0,0,5,0,0,0,0,191,52,253,244,63,52,253,244,0,0,0,8,0,0,0,2,0,0,0,11,108,105,103,104,116,70,97,99,116,111,114,0,0,0,0,1,0,0,0,12,0,0,0,1,0,0,0,2,0,0,0,11,0,0,0,1,0,0,0,10,118,101,114,116,78,111,114,109,97,108,0,0,0,0,3,0,0,0,11,0,0,0,2,0,0,0,8,108,105,103,104,116,68,105,114,0,0,0,0,3,0,0,0,8,0,0,0,2,0,0,0,12,116,101,120,116,117,114,101,67,111,108,111,114,0,0,0,0,4,0,0,0,2,0,0,0,2,0,0,0,11,0,0,0,2,0,0,0,11,108,105,103,104,116,70,97,99,116,111,114,0,0,0,0,1,0,0,0,6,0,0,0,19,72,65,83,95,68,73,70,70,85,83,69,95,84,69,88,84,85,82,69,0,0,0,2,0,0,0,2,0,0,0,14,0,0,0,11,0,0,0,5,0,0,0,18,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,0,0,0,0,10,0,0,0,11,0,0,0,1,0,0,0,6,118,101,114,116,85,86,0,0,0,0,2,0,0,0,0,0,0,0,11,0,0,0,5,0,0,0,8,115,101,116,116,105,110,103,115,1,0,0,0,13,66,97,115,105,99,83,101,116,116,105,110,103,115,0,0,0,0,4,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,11,0,0,0,5,0,0,0,8,115,101,116,116,105,110,103,115,1,0,0,0,13,66,97,115,105,99,83,101,116,116,105,110,103,115,0,0,0,0,4,0,0,0,1,0,0,0,1,0,0,0,8,0,0,0,2,0,0,0,4,118,97,114,48,0,0,0,0,4,0,0,0,6,0,0,0,17,72,65,83,95,65,76,80,72,65,95,84,69,88,84,85,82,69,0,0,0,4,0,0,0,4,0,0,0,15,0,0,0,0,0,0,0,1,0,0,0,11,0,0,0,2,0,0,0,12,116,101,120,116,117,114,101,67,111,108,111,114,0,0,0,0,4,0,0,0,0,0,0,0,15,0,0,0,0,0,0,0,1,0,0,0,11,0,0,0,2,0,0,0,12,116,101,120,116,117,114,101,67,111,108,111,114,0,0,0,0,4,0,0,0,1,0,0,0,15,0,0,0,0,0,0,0,1,0,0,0,11,0,0,0,2,0,0,0,12,116,101,120,116,117,114,101,67,111,108,111,114,0,0,0,0,4,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,15,0,0,0,0,0,0,0,1,0,0,0,14,0,0,0,11,0,0,0,5,0,0,0,16,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,0,0,0,0,10,0,0,0,11,0,0,0,1,0,0,0,6,118,101,114,116,85,86,0,0,0,0,2,0,0,0,0,0,0,0,15,0,0,0,0,0,0,0,1,0,0,0,11,0,0,0,2,0,0,0,12,116,101,120,116,117,114,101,67,111,108,111,114,0,0,0,0,4,0,0,0,3,0,0,0,11,0,0,0,2,0,0,0,12,116,101,120,116,117,114,101,67,111,108,111,114,0,0,0,0,4,0,0,0,3,0,0,0,1,0,0,0,2,0,0,0,4,0,0,0,6,0,0,0,10,65,76,80,72,65,95,84,69,83,84,0,0,0,2,0,0,0,8,0,0,0,15,0,0,0,0,0,0,0,1,0,0,0,11,0,0,0,2,0,0,0,4,118,97,114,48,0,0,0,0,4,0,0,0,3,0,0,0,0,0,0,0,11,0,0,0,5,0,0,0,8,115,101,116,116,105,110,103,115,1,0,0,0,13,66,97,115,105,99,83,101,116,116,105,110,103,115,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,5,0,0,0,0,1,0,0,0,9,255,255,255,255,0,0,0,10,0,0,0,1,0,0,0,0,0,0,0,11,0,0,0,3,0,0,0,13,82,101,110,100,101,114,84,97,114,103,101,116,48,0,0,0,0,4,0,0,0,11,0,0,0,2,0,0,0,4,118,97,114,48,0,0,0,0,4, \ No newline at end of file diff --git a/src/Nazara/Graphics/Resources/Shaders/basicmaterial.vert.shader b/src/Nazara/Graphics/Resources/Shaders/basicmaterial.vert.shader index 0cb002264d4f231155b0d90967c08770d9fdc2fa..8194d50220e353edcf8771f84d326492fea47272 100644 GIT binary patch delta 14 VcmbQmF^gkECljN<<}RiQi~u8O1YrOG delta 14 VcmbQmF^gkECle$8<}RiQi~u8I1YiIF diff --git a/src/Nazara/Graphics/Resources/Shaders/basicmaterial.vert.shader.h b/src/Nazara/Graphics/Resources/Shaders/basicmaterial.vert.shader.h index d5f0cbb3e..8a5556626 100644 --- a/src/Nazara/Graphics/Resources/Shaders/basicmaterial.vert.shader.h +++ b/src/Nazara/Graphics/Resources/Shaders/basicmaterial.vert.shader.h @@ -1 +1 @@ -78,83,72,82,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,3,0,0,0,13,66,97,115,105,99,83,101,116,116,105,110,103,115,0,0,0,2,0,0,0,14,65,108,112,104,97,84,104,114,101,115,104,111,108,100,0,0,0,0,1,0,0,0,12,68,105,102,102,117,115,101,67,111,108,111,114,0,0,0,0,4,0,0,0,12,73,110,115,116,97,110,99,101,68,97,116,97,0,0,0,2,0,0,0,11,119,111,114,108,100,77,97,116,114,105,120,0,0,0,0,9,0,0,0,14,105,110,118,87,111,114,108,100,77,97,116,114,105,120,0,0,0,0,9,0,0,0,10,86,105,101,119,101,114,68,97,116,97,0,0,0,9,0,0,0,16,112,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,0,0,0,0,9,0,0,0,19,105,110,118,80,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,0,0,0,0,9,0,0,0,10,118,105,101,119,77,97,116,114,105,120,0,0,0,0,9,0,0,0,13,105,110,118,86,105,101,119,77,97,116,114,105,120,0,0,0,0,9,0,0,0,14,118,105,101,119,80,114,111,106,77,97,116,114,105,120,0,0,0,0,9,0,0,0,17,105,110,118,86,105,101,119,80,114,111,106,77,97,116,114,105,120,0,0,0,0,9,0,0,0,16,114,101,110,100,101,114,84,97,114,103,101,116,83,105,122,101,0,0,0,0,2,0,0,0,19,105,110,118,82,101,110,100,101,114,84,97,114,103,101,116,83,105,122,101,0,0,0,0,2,0,0,0,11,101,121,101,80,111,115,105,116,105,111,110,0,0,0,0,3,0,0,0,3,0,0,0,5,105,110,80,111,115,0,0,0,0,3,1,0,0,0,0,0,0,0,9,105,110,78,111,114,109,97,108,115,0,0,0,0,3,1,0,0,0,1,0,0,0,10,105,110,84,101,120,67,111,111,114,100,0,0,0,0,2,1,0,0,0,2,0,0,0,2,0,0,0,10,118,101,114,116,78,111,114,109,97,108,0,0,0,0,3,1,0,0,0,0,0,0,0,6,118,101,114,116,85,86,0,0,0,0,2,1,0,0,0,1,0,0,0,3,0,0,0,10,118,105,101,119,101,114,68,97,116,97,1,0,0,0,10,86,105,101,119,101,114,68,97,116,97,1,0,0,0,5,1,0,0,0,0,0,0,0,12,105,110,115,116,97,110,99,101,68,97,116,97,1,0,0,0,12,73,110,115,116,97,110,99,101,68,97,116,97,1,0,0,0,4,1,0,0,0,0,0,0,0,8,115,101,116,116,105,110,103,115,1,0,0,0,13,66,97,115,105,99,83,101,116,116,105,110,103,115,1,0,0,0,3,1,0,0,0,0,0,0,0,1,0,0,0,4,109,97,105,110,0,0,0,11,0,0,0,0,0,0,0,15,0,0,0,3,0,0,0,10,0,0,0,1,0,0,0,0,0,0,0,11,0,0,0,3,0,0,0,6,118,101,114,116,85,86,0,0,0,0,2,0,0,0,11,0,0,0,1,0,0,0,10,105,110,84,101,120,67,111,111,114,100,0,0,0,0,2,0,0,0,10,0,0,0,1,0,0,0,0,0,0,0,11,0,0,0,3,0,0,0,10,118,101,114,116,78,111,114,109,97,108,0,0,0,0,3,0,0,0,11,0,0,0,1,0,0,0,9,105,110,78,111,114,109,97,108,115,0,0,0,0,3,0,0,0,10,0,0,0,1,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,11,0,0,0,5,0,0,0,10,118,105,101,119,101,114,68,97,116,97,1,0,0,0,10,86,105,101,119,101,114,68,97,116,97,0,0,0,0,9,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,5,0,0,0,10,118,105,101,119,101,114,68,97,116,97,1,0,0,0,10,86,105,101,119,101,114,68,97,116,97,0,0,0,0,9,0,0,0,1,0,0,0,2,0,0,0,0,0,0,0,11,0,0,0,5,0,0,0,12,105,110,115,116,97,110,99,101,68,97,116,97,1,0,0,0,12,73,110,115,116,97,110,99,101,68,97,116,97,0,0,0,0,9,0,0,0,1,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,11,0,0,0,1,0,0,0,5,105,110,80,111,115,0,0,0,0,3,0,0,0,5,0,0,0,1,63,128,0,0,255,255,255,255,255,255,255,255, \ No newline at end of file +78,83,72,82,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,3,0,0,0,13,66,97,115,105,99,83,101,116,116,105,110,103,115,0,0,0,2,0,0,0,14,65,108,112,104,97,84,104,114,101,115,104,111,108,100,0,0,0,0,1,0,0,0,12,68,105,102,102,117,115,101,67,111,108,111,114,0,0,0,0,4,0,0,0,12,73,110,115,116,97,110,99,101,68,97,116,97,0,0,0,2,0,0,0,11,119,111,114,108,100,77,97,116,114,105,120,0,0,0,0,9,0,0,0,14,105,110,118,87,111,114,108,100,77,97,116,114,105,120,0,0,0,0,9,0,0,0,10,86,105,101,119,101,114,68,97,116,97,0,0,0,9,0,0,0,16,112,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,0,0,0,0,9,0,0,0,19,105,110,118,80,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,0,0,0,0,9,0,0,0,10,118,105,101,119,77,97,116,114,105,120,0,0,0,0,9,0,0,0,13,105,110,118,86,105,101,119,77,97,116,114,105,120,0,0,0,0,9,0,0,0,14,118,105,101,119,80,114,111,106,77,97,116,114,105,120,0,0,0,0,9,0,0,0,17,105,110,118,86,105,101,119,80,114,111,106,77,97,116,114,105,120,0,0,0,0,9,0,0,0,16,114,101,110,100,101,114,84,97,114,103,101,116,83,105,122,101,0,0,0,0,2,0,0,0,19,105,110,118,82,101,110,100,101,114,84,97,114,103,101,116,83,105,122,101,0,0,0,0,2,0,0,0,11,101,121,101,80,111,115,105,116,105,111,110,0,0,0,0,3,0,0,0,3,0,0,0,5,105,110,80,111,115,0,0,0,0,3,1,0,0,0,0,0,0,0,9,105,110,78,111,114,109,97,108,115,0,0,0,0,3,1,0,0,0,1,0,0,0,10,105,110,84,101,120,67,111,111,114,100,0,0,0,0,2,1,0,0,0,2,0,0,0,2,0,0,0,10,118,101,114,116,78,111,114,109,97,108,0,0,0,0,3,1,0,0,0,0,0,0,0,6,118,101,114,116,85,86,0,0,0,0,2,1,0,0,0,1,0,0,0,3,0,0,0,10,118,105,101,119,101,114,68,97,116,97,1,0,0,0,10,86,105,101,119,101,114,68,97,116,97,1,0,0,0,5,1,0,0,0,0,0,0,0,12,105,110,115,116,97,110,99,101,68,97,116,97,1,0,0,0,12,73,110,115,116,97,110,99,101,68,97,116,97,1,0,0,0,4,1,0,0,0,0,0,0,0,8,115,101,116,116,105,110,103,115,1,0,0,0,13,66,97,115,105,99,83,101,116,116,105,110,103,115,1,0,0,0,3,1,0,0,0,0,0,0,0,1,0,0,0,4,109,97,105,110,0,0,0,11,0,0,0,0,0,0,0,16,0,0,0,3,0,0,0,10,0,0,0,1,0,0,0,0,0,0,0,11,0,0,0,3,0,0,0,6,118,101,114,116,85,86,0,0,0,0,2,0,0,0,11,0,0,0,1,0,0,0,10,105,110,84,101,120,67,111,111,114,100,0,0,0,0,2,0,0,0,10,0,0,0,1,0,0,0,0,0,0,0,11,0,0,0,3,0,0,0,10,118,101,114,116,78,111,114,109,97,108,0,0,0,0,3,0,0,0,11,0,0,0,1,0,0,0,9,105,110,78,111,114,109,97,108,115,0,0,0,0,3,0,0,0,10,0,0,0,1,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,11,0,0,0,5,0,0,0,10,118,105,101,119,101,114,68,97,116,97,1,0,0,0,10,86,105,101,119,101,114,68,97,116,97,0,0,0,0,9,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,5,0,0,0,10,118,105,101,119,101,114,68,97,116,97,1,0,0,0,10,86,105,101,119,101,114,68,97,116,97,0,0,0,0,9,0,0,0,1,0,0,0,2,0,0,0,0,0,0,0,11,0,0,0,5,0,0,0,12,105,110,115,116,97,110,99,101,68,97,116,97,1,0,0,0,12,73,110,115,116,97,110,99,101,68,97,116,97,0,0,0,0,9,0,0,0,1,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,11,0,0,0,1,0,0,0,5,105,110,80,111,115,0,0,0,0,3,0,0,0,5,0,0,0,1,63,128,0,0,255,255,255,255,255,255,255,255, \ No newline at end of file diff --git a/src/ShaderNode/Widgets/MainWindow.cpp b/src/ShaderNode/Widgets/MainWindow.cpp index c131a123c..67b50dd91 100644 --- a/src/ShaderNode/Widgets/MainWindow.cpp +++ b/src/ShaderNode/Widgets/MainWindow.cpp @@ -182,6 +182,7 @@ void MainWindow::OnCompile() try { auto shader = m_shaderGraph.ToShader(); + shader.AddFunction("main", m_shaderGraph.ToAst()); QString fileName = QFileDialog::getSaveFileName(nullptr, tr("Save shader"), QString(), tr("Shader Files (*.shader)")); if (fileName.isEmpty()) From 711199fe51cfd1354cdfaa54911f77717b07ef7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 15 Jan 2021 19:19:19 +0100 Subject: [PATCH 037/278] Shader/ShaderAstOptimizer: Fix branch optimization --- src/Nazara/Shader/ShaderAstOptimizer.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Nazara/Shader/ShaderAstOptimizer.cpp b/src/Nazara/Shader/ShaderAstOptimizer.cpp index 6bc61c1e4..b2e5acf96 100644 --- a/src/Nazara/Shader/ShaderAstOptimizer.cpp +++ b/src/Nazara/Shader/ShaderAstOptimizer.cpp @@ -470,6 +470,12 @@ namespace Nz break; } } + else + { + auto& c = statements.emplace_back(); + c.condition = std::move(cond); + c.statement = CloneStatement(condStatement.statement); + } } if (statements.empty()) From e6ada6846d5a7f01e1e40b27e795242c989d1538 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 22 Jan 2021 18:04:58 +0100 Subject: [PATCH 038/278] Graphics: Fix PredefinedViewerData size --- include/Nazara/Utility/FieldOffsets.hpp | 1 + include/Nazara/Utility/FieldOffsets.inl | 8 ++++++++ src/Nazara/Graphics/PredefinedShaderStructs.cpp | 8 ++++---- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/include/Nazara/Utility/FieldOffsets.hpp b/include/Nazara/Utility/FieldOffsets.hpp index 266f82cd7..9ba1301d7 100644 --- a/include/Nazara/Utility/FieldOffsets.hpp +++ b/include/Nazara/Utility/FieldOffsets.hpp @@ -27,6 +27,7 @@ namespace Nz std::size_t AddStruct(const FieldOffsets& fieldStruct); std::size_t AddStructArray(const FieldOffsets& fieldStruct, std::size_t arraySize); + inline std::size_t GetAlignedSize() const; inline std::size_t GetLargestFieldAlignement() const; inline std::size_t GetSize() const; diff --git a/include/Nazara/Utility/FieldOffsets.inl b/include/Nazara/Utility/FieldOffsets.inl index 5ca15e88f..42baacd2c 100644 --- a/include/Nazara/Utility/FieldOffsets.inl +++ b/include/Nazara/Utility/FieldOffsets.inl @@ -22,6 +22,14 @@ namespace Nz return m_largestFieldAlignment; } + inline std::size_t FieldOffsets::GetAlignedSize() const + { + if (m_layout == StructLayout_Std140) + return Align(m_size, m_largestFieldAlignment); + else + return m_size; + } + inline std::size_t FieldOffsets::GetSize() const { return m_size; diff --git a/src/Nazara/Graphics/PredefinedShaderStructs.cpp b/src/Nazara/Graphics/PredefinedShaderStructs.cpp index d8b81a249..5280202f2 100644 --- a/src/Nazara/Graphics/PredefinedShaderStructs.cpp +++ b/src/Nazara/Graphics/PredefinedShaderStructs.cpp @@ -21,13 +21,13 @@ namespace Nz lightData.innerOffsets.parameter3 = lightStruct.AddField(StructFieldType_Float2); lightData.innerOffsets.shadowMappingFlag = lightStruct.AddField(StructFieldType_Bool1); - lightData.innerOffsets.totalSize = lightStruct.GetSize(); + lightData.innerOffsets.totalSize = lightStruct.GetAlignedSize(); FieldOffsets lightDataStruct(StructLayout_Std140); for (std::size_t& lightOffset : lightData.lightArray) lightOffset = lightDataStruct.AddStruct(lightStruct); - lightData.lightArraySize = lightDataStruct.GetSize(); + lightData.lightArraySize = lightDataStruct.GetAlignedSize(); return lightData; } @@ -62,7 +62,7 @@ namespace Nz instanceData.worldMatrixOffset = viewerStruct.AddMatrix(StructFieldType_Float1, 4, 4, true); instanceData.invWorldMatrixOffset = viewerStruct.AddMatrix(StructFieldType_Float1, 4, 4, true); - instanceData.totalSize = viewerStruct.GetSize(); + instanceData.totalSize = viewerStruct.GetAlignedSize(); return instanceData; } @@ -107,7 +107,7 @@ namespace Nz viewerData.invTargetSizeOffset = viewerStruct.AddField(StructFieldType_Float2); viewerData.eyePositionOffset = viewerStruct.AddField(StructFieldType_Float3); - viewerData.totalSize = viewerStruct.GetSize(); + viewerData.totalSize = viewerStruct.GetAlignedSize(); return viewerData; } From c76d6505b0004565cdf51118290913b7f14f5171 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 22 Jan 2021 23:15:31 +0100 Subject: [PATCH 039/278] Renderer/ShaderBinder: Make Update take a pointer and size --- .../Nazara/OpenGLRenderer/OpenGLShaderBinding.hpp | 2 +- include/Nazara/Renderer/ShaderBinding.hpp | 3 ++- include/Nazara/Renderer/ShaderBinding.inl | 5 +++++ .../Nazara/VulkanRenderer/VulkanShaderBinding.hpp | 2 +- src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp | 6 ++++-- src/Nazara/VulkanRenderer/VulkanShaderBinding.cpp | 12 +++++++----- 6 files changed, 20 insertions(+), 10 deletions(-) diff --git a/include/Nazara/OpenGLRenderer/OpenGLShaderBinding.hpp b/include/Nazara/OpenGLRenderer/OpenGLShaderBinding.hpp index 33fb89f40..dc7d144ef 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLShaderBinding.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLShaderBinding.hpp @@ -30,7 +30,7 @@ namespace Nz inline std::size_t GetPoolIndex() const; inline const OpenGLRenderPipelineLayout& GetOwner() const; - void Update(std::initializer_list bindings) override; + void Update(const Binding* bindings, std::size_t bindingCount) override; OpenGLShaderBinding& operator=(const OpenGLShaderBinding&) = delete; OpenGLShaderBinding& operator=(OpenGLShaderBinding&&) = delete; diff --git a/include/Nazara/Renderer/ShaderBinding.hpp b/include/Nazara/Renderer/ShaderBinding.hpp index 4105974bc..53f38b128 100644 --- a/include/Nazara/Renderer/ShaderBinding.hpp +++ b/include/Nazara/Renderer/ShaderBinding.hpp @@ -34,7 +34,8 @@ namespace Nz ShaderBinding(ShaderBinding&&) = delete; virtual ~ShaderBinding(); - virtual void Update(std::initializer_list bindings) = 0; + virtual void Update(const Binding* bindings, std::size_t bindingCount) = 0; + inline void Update(std::initializer_list bindings); ShaderBinding& operator=(const ShaderBinding&) = delete; ShaderBinding& operator=(ShaderBinding&&) = delete; diff --git a/include/Nazara/Renderer/ShaderBinding.inl b/include/Nazara/Renderer/ShaderBinding.inl index 6d1f7f3d0..971be9ffd 100644 --- a/include/Nazara/Renderer/ShaderBinding.inl +++ b/include/Nazara/Renderer/ShaderBinding.inl @@ -7,6 +7,11 @@ namespace Nz { + inline void ShaderBinding::Update(std::initializer_list bindings) + { + Update(bindings.begin(), bindings.size()); + } + inline void ShaderBindingDeleter::operator()(ShaderBinding* binding) { binding->Release(); diff --git a/include/Nazara/VulkanRenderer/VulkanShaderBinding.hpp b/include/Nazara/VulkanRenderer/VulkanShaderBinding.hpp index ee97ec66f..8d38b92dd 100644 --- a/include/Nazara/VulkanRenderer/VulkanShaderBinding.hpp +++ b/include/Nazara/VulkanRenderer/VulkanShaderBinding.hpp @@ -28,7 +28,7 @@ namespace Nz inline std::size_t GetPoolIndex() const; inline const VulkanRenderPipelineLayout& GetOwner() const; - void Update(std::initializer_list bindings) override; + void Update(const Binding* bindings, std::size_t bindingCount) override; VulkanShaderBinding& operator=(const VulkanShaderBinding&) = delete; VulkanShaderBinding& operator=(VulkanShaderBinding&&) = delete; diff --git a/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp b/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp index 492331cc0..d8fd7fa44 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp @@ -39,12 +39,14 @@ namespace Nz } } - void OpenGLShaderBinding::Update(std::initializer_list bindings) + void OpenGLShaderBinding::Update(const Binding* bindings, std::size_t bindingCount) { const auto& layoutInfo = m_owner.GetLayoutInfo(); - for (const Binding& binding : bindings) + for (std::size_t i = 0; i < bindingCount; ++i) { + const Binding& binding = bindings[i]; + assert(binding.bindingIndex < layoutInfo.bindings.size()); const auto& bindingDesc = layoutInfo.bindings[binding.bindingIndex]; diff --git a/src/Nazara/VulkanRenderer/VulkanShaderBinding.cpp b/src/Nazara/VulkanRenderer/VulkanShaderBinding.cpp index bf86a2989..abec596e4 100644 --- a/src/Nazara/VulkanRenderer/VulkanShaderBinding.cpp +++ b/src/Nazara/VulkanRenderer/VulkanShaderBinding.cpp @@ -13,14 +13,16 @@ namespace Nz { - void VulkanShaderBinding::Update(std::initializer_list bindings) + void VulkanShaderBinding::Update(const Binding* bindings, std::size_t bindingCount) { - StackVector bufferBinding = NazaraStackVector(VkDescriptorBufferInfo, bindings.size()); - StackVector imageBinding = NazaraStackVector(VkDescriptorImageInfo, bindings.size()); - StackVector writeOps = NazaraStackVector(VkWriteDescriptorSet, bindings.size()); + StackVector bufferBinding = NazaraStackVector(VkDescriptorBufferInfo, bindingCount); + StackVector imageBinding = NazaraStackVector(VkDescriptorImageInfo, bindingCount); + StackVector writeOps = NazaraStackVector(VkWriteDescriptorSet, bindingCount); - for (const Binding& binding : bindings) + for (std::size_t i = 0; i < bindingCount; ++i) { + const Binding& binding = bindings[i]; + VkWriteDescriptorSet& writeOp = writeOps.emplace_back(); writeOp.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; writeOp.dstSet = m_descriptorSet; From dbcb4a61d06246eb85bfafeeb54463ab7585e422 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 22 Jan 2021 23:17:55 +0100 Subject: [PATCH 040/278] OpenGLRenderer: Fix context not being shared on OpenGL ES --- src/Nazara/OpenGLRenderer/Wrapper/WGL/WGLContext.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nazara/OpenGLRenderer/Wrapper/WGL/WGLContext.cpp b/src/Nazara/OpenGLRenderer/Wrapper/WGL/WGLContext.cpp index 052c0f63a..eb356f779 100644 --- a/src/Nazara/OpenGLRenderer/Wrapper/WGL/WGLContext.cpp +++ b/src/Nazara/OpenGLRenderer/Wrapper/WGL/WGLContext.cpp @@ -133,7 +133,7 @@ namespace Nz::GL WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_ES_PROFILE_BIT_EXT }; - m_handle = baseContext->wglCreateContextAttribsARB(m_deviceContext, nullptr, attributes.data()); + m_handle = baseContext->wglCreateContextAttribsARB(m_deviceContext, (shareContext) ? shareContext->m_handle : nullptr, attributes.data()); if (m_handle) break; } From d52be87fd5463108d3c28df2ce4110f312a5ae3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 22 Jan 2021 23:18:35 +0100 Subject: [PATCH 041/278] OpenGLRenderer: Fix Draw[Indexed]Data states --- src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp b/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp index b5ccbd0ed..3308adf01 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp @@ -80,12 +80,12 @@ namespace Nz } else if constexpr (std::is_same_v) { - ApplyStates(*context, m_currentStates); + ApplyStates(*context, command.states); context->glDrawArraysInstanced(GL_TRIANGLES, command.firstVertex, command.vertexCount, command.instanceCount); } else if constexpr (std::is_same_v) { - ApplyStates(*context, m_currentStates); + ApplyStates(*context, command.states); context->glDrawElementsInstanced(GL_TRIANGLES, command.indexCount, GL_UNSIGNED_SHORT, nullptr, command.instanceCount); } else if constexpr (std::is_same_v) From a6ff64106e906559e7584e3989dbbbeef848c772 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 22 Jan 2021 23:23:28 +0100 Subject: [PATCH 042/278] Minor stuff --- examples/GraphicsTest/main.cpp | 4 ++-- examples/bin/test.spirv | Bin 1360 -> 0 bytes include/Nazara/Graphics/Material.hpp | 2 +- include/Nazara/OpenGLRenderer/Utils.inl | 5 ++++- .../Nazara/OpenGLRenderer/Wrapper/Texture.inl | 1 - include/Nazara/Renderer/Texture.hpp | 2 +- include/Nazara/Utility/Enums.hpp | 2 ++ src/Nazara/OpenGLRenderer/OpenGLShaderStage.cpp | 3 --- src/Nazara/OpenGLRenderer/OpenGLVaoCache.cpp | 2 +- src/Nazara/VulkanRenderer/VulkanTexture.cpp | 15 +++++++++++++++ 10 files changed, 26 insertions(+), 10 deletions(-) delete mode 100644 examples/bin/test.spirv diff --git a/examples/GraphicsTest/main.cpp b/examples/GraphicsTest/main.cpp index 3d2d6e202..6575a1724 100644 --- a/examples/GraphicsTest/main.cpp +++ b/examples/GraphicsTest/main.cpp @@ -105,10 +105,10 @@ int main() material.EnableDepthBuffer(true); Nz::BasicMaterial basicMat(material); - basicMat.EnableAlphaTest(true); + basicMat.EnableAlphaTest(false); basicMat.SetAlphaMap(alphaTexture); basicMat.SetAlphaSampler(textureSampler); - basicMat.SetDiffuseMap(alphaTexture); + basicMat.SetDiffuseMap(texture); basicMat.SetDiffuseSampler(textureSampler); Nz::PredefinedInstanceData instanceUboOffsets = Nz::PredefinedInstanceData::GetOffsets(); diff --git a/examples/bin/test.spirv b/examples/bin/test.spirv deleted file mode 100644 index b8858477532b82cee40f28bcdb11a8b7aa1776b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1360 zcmZ9LNpBND5QRH-#)K^)ge+{qj@ffZNQg}w$O+|uxFU!6Fv#(siA{3MUw~iB1&QzL zOrcR)DtEtE^{T3C+TG6ZQc4TSwVQuaT1}nIET?W}^sc0<`Fxk(qft2(+``te4QvzJ z!fslQ4%K{i z9+5V4<_`Y(L6tsI&sm&LC}nK@ZOo^Ir%SKk`D^~@pevm2{^7rfA5w*T08W5RE3*P diff --git a/include/Nazara/Graphics/Material.hpp b/include/Nazara/Graphics/Material.hpp index 93493ce14..3a7223a62 100644 --- a/include/Nazara/Graphics/Material.hpp +++ b/include/Nazara/Graphics/Material.hpp @@ -115,7 +115,7 @@ namespace Nz std::vector m_textures; std::vector m_uniformBuffers; mutable std::shared_ptr m_pipeline; - UInt32 m_enabledConditions; + UInt64 m_enabledConditions; mutable MaterialPipelineInfo m_pipelineInfo; mutable bool m_pipelineUpdated; bool m_shadowCastingEnabled; diff --git a/include/Nazara/OpenGLRenderer/Utils.inl b/include/Nazara/OpenGLRenderer/Utils.inl index bd44b5e13..fcae4116a 100644 --- a/include/Nazara/OpenGLRenderer/Utils.inl +++ b/include/Nazara/OpenGLRenderer/Utils.inl @@ -12,10 +12,13 @@ namespace Nz { inline std::optional DescribeTextureFormat(PixelFormat pixelFormat) { + // TODO: Fill this switch switch (pixelFormat) { case PixelFormat_A8: return GLTextureFormat { GL_R8, GL_RED, GL_UNSIGNED_BYTE, GL_ZERO, GL_ZERO, GL_ZERO, GL_RED }; - case PixelFormat_RGB8: return GLTextureFormat { GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE, GL_RED, GL_GREEN, GL_BLUE, GL_ZERO }; + case PixelFormat_BGR8: return GLTextureFormat { GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE, GL_BLUE, GL_GREEN, GL_RED, GL_ONE }; + case PixelFormat_BGRA8: return GLTextureFormat { GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA }; + case PixelFormat_RGB8: return GLTextureFormat { GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE, GL_RED, GL_GREEN, GL_BLUE, GL_ONE }; case PixelFormat_RGBA8: return GLTextureFormat { GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; default: break; } diff --git a/include/Nazara/OpenGLRenderer/Wrapper/Texture.inl b/include/Nazara/OpenGLRenderer/Wrapper/Texture.inl index 62de24b8d..a345ac6f4 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/Texture.inl +++ b/include/Nazara/OpenGLRenderer/Wrapper/Texture.inl @@ -56,7 +56,6 @@ namespace Nz::GL const Context& context = EnsureDeviceContext(); context.BindTexture(m_target, m_objectId); context.glTexImage2D(ToOpenGL(m_target), level, internalFormat, width, height, border, format, type, data); - //< TODO: Handle errors } inline void Texture::TexSubImage2D(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* data) diff --git a/include/Nazara/Renderer/Texture.hpp b/include/Nazara/Renderer/Texture.hpp index 4fa0ebc75..8f185fe21 100644 --- a/include/Nazara/Renderer/Texture.hpp +++ b/include/Nazara/Renderer/Texture.hpp @@ -19,9 +19,9 @@ namespace Nz { PixelFormat pixelFormat; ImageType type; + UInt8 mipmapLevel = 1; unsigned int depth = 1; unsigned int height; - unsigned int mipmapLevel = 1; unsigned int width; }; diff --git a/include/Nazara/Utility/Enums.hpp b/include/Nazara/Utility/Enums.hpp index f68fb3ea6..6f556da16 100644 --- a/include/Nazara/Utility/Enums.hpp +++ b/include/Nazara/Utility/Enums.hpp @@ -146,6 +146,8 @@ namespace Nz ImageType_Max = ImageType_Cubemap }; + constexpr std::size_t ImageTypeCount = static_cast(ImageType_Max) + 1; + enum NodeType { NodeType_Default, // Node diff --git a/src/Nazara/OpenGLRenderer/OpenGLShaderStage.cpp b/src/Nazara/OpenGLRenderer/OpenGLShaderStage.cpp index dd7a69e5b..0f24f524f 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLShaderStage.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLShaderStage.cpp @@ -3,7 +3,6 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include #include #include #include @@ -89,8 +88,6 @@ namespace Nz std::string code = writer.Generate(shaderAst, states); - NazaraError(code); - m_shader.SetSource(code.data(), code.size()); m_shader.Compile(); } diff --git a/src/Nazara/OpenGLRenderer/OpenGLVaoCache.cpp b/src/Nazara/OpenGLRenderer/OpenGLVaoCache.cpp index 62f3f0166..172872e69 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLVaoCache.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLVaoCache.cpp @@ -30,7 +30,7 @@ namespace Nz::GL if (setup.indexBuffer != 0) m_context.BindBuffer(BufferTarget::ElementArray, setup.indexBuffer, true); - std::size_t bindingIndex = 0; + GLuint bindingIndex = 0; for (const auto& attribOpt : setup.vertexAttribs) { if (attribOpt) diff --git a/src/Nazara/VulkanRenderer/VulkanTexture.cpp b/src/Nazara/VulkanRenderer/VulkanTexture.cpp index 20900d81f..5574bb755 100644 --- a/src/Nazara/VulkanRenderer/VulkanTexture.cpp +++ b/src/Nazara/VulkanRenderer/VulkanTexture.cpp @@ -227,8 +227,23 @@ namespace Nz VK_COMPONENT_SWIZZLE_A }; + // TODO: Fill this switch switch (pixelFormat) { + case PixelFormat_BGR8: + { + createImage.format = VK_FORMAT_B8G8R8_SRGB; + createImageView.format = createImage.format; + break; + } + + case PixelFormat_BGRA8: + { + createImage.format = VK_FORMAT_B8G8R8A8_SRGB; + createImageView.format = createImage.format; + break; + } + case PixelFormat_L8: { createImage.format = VK_FORMAT_R8_SRGB; From a0d5750ec8c79274105e3df2d279dcb87ab97810 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 22 Jan 2021 23:27:11 +0100 Subject: [PATCH 043/278] Graphics: Add GetViewerDataUBO --- include/Nazara/Graphics/Graphics.hpp | 3 +++ include/Nazara/Graphics/Graphics.inl | 5 +++++ src/Nazara/Graphics/Graphics.cpp | 7 +++++++ 3 files changed, 15 insertions(+) diff --git a/include/Nazara/Graphics/Graphics.hpp b/include/Nazara/Graphics/Graphics.hpp index d1f988f04..954719f15 100644 --- a/include/Nazara/Graphics/Graphics.hpp +++ b/include/Nazara/Graphics/Graphics.hpp @@ -14,6 +14,7 @@ namespace Nz { + class AbstractBuffer; class RenderDevice; class NAZARA_GRAPHICS_API Graphics : public ModuleBase @@ -29,6 +30,7 @@ namespace Nz ~Graphics(); inline RenderDevice& GetRenderDevice(); + inline const std::shared_ptr& GetViewerDataUBO(); struct Config { @@ -36,6 +38,7 @@ namespace Nz }; private: + std::shared_ptr m_viewerDataUBO; std::shared_ptr m_renderDevice; static Graphics* s_instance; diff --git a/include/Nazara/Graphics/Graphics.inl b/include/Nazara/Graphics/Graphics.inl index ba9766953..35023cfc5 100644 --- a/include/Nazara/Graphics/Graphics.inl +++ b/include/Nazara/Graphics/Graphics.inl @@ -11,6 +11,11 @@ namespace Nz { return *m_renderDevice; } + + inline const std::shared_ptr& Graphics::GetViewerDataUBO() + { + return m_viewerDataUBO; + } } #include diff --git a/src/Nazara/Graphics/Graphics.cpp b/src/Nazara/Graphics/Graphics.cpp index 05d56f911..aa2deb383 100644 --- a/src/Nazara/Graphics/Graphics.cpp +++ b/src/Nazara/Graphics/Graphics.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -39,6 +40,12 @@ namespace Nz throw std::runtime_error("failed to instantiate render device"); MaterialPipeline::Initialize(); + + Nz::PredefinedViewerData viewerUboOffsets = Nz::PredefinedViewerData::GetOffsets(); + + m_viewerDataUBO = m_renderDevice->InstantiateBuffer(Nz::BufferType_Uniform); + if (!m_viewerDataUBO->Initialize(viewerUboOffsets.totalSize, Nz::BufferUsage_DeviceLocal | Nz::BufferUsage_Dynamic)) + throw std::runtime_error("failed to initialize viewer data UBO"); } Graphics::~Graphics() From 19783f775541633862cb3f41b1acc98dab0c8a3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 22 Jan 2021 23:31:54 +0100 Subject: [PATCH 044/278] Graphics/Material: Rework UBO handling --- include/Nazara/Graphics/Material.hpp | 20 ++++++-- include/Nazara/Graphics/Material.inl | 42 +++++++++++++--- src/Nazara/Graphics/BasicMaterial.cpp | 18 ++++--- src/Nazara/Graphics/Material.cpp | 50 +++++++++++++++++-- src/Nazara/Graphics/PhongLightingMaterial.cpp | 36 ++++++------- 5 files changed, 123 insertions(+), 43 deletions(-) diff --git a/include/Nazara/Graphics/Material.hpp b/include/Nazara/Graphics/Material.hpp index 3a7223a62..13569061c 100644 --- a/include/Nazara/Graphics/Material.hpp +++ b/include/Nazara/Graphics/Material.hpp @@ -67,13 +67,13 @@ namespace Nz inline BlendFunc GetSrcBlend() const; inline const std::shared_ptr& GetTexture(std::size_t textureIndex) const; inline const std::shared_ptr& GetTextureSampler(std::size_t textureIndex) const; - inline UniformBufferRef& GetUniformBuffer(std::size_t bufferIndex); - inline const UniformBufferRef& GetUniformBuffer(std::size_t bufferIndex) const; + inline const std::shared_ptr& GetUniformBuffer(std::size_t bufferIndex) const; + inline std::vector& GetUniformBufferData(std::size_t bufferIndex); + inline const std::vector& GetUniformBufferConstData(std::size_t bufferIndex); inline bool HasTexture(std::size_t textureIndex) const; inline bool HasVertexColor() const; - inline bool IsAlphaTestEnabled() const; inline bool IsBlendingEnabled() const; inline bool IsColorWriteEnabled() const; inline bool IsConditionEnabled(std::size_t conditionIndex) const; @@ -93,16 +93,19 @@ namespace Nz inline void SetFaceFilling(FaceFilling filling); inline void SetLineWidth(float lineWidth); inline void SetPointSize(float pointSize); - inline void SetUniformBuffer(std::size_t bufferIndex, UniformBufferRef uniformBuffer); + inline void SetUniformBuffer(std::size_t bufferIndex, std::shared_ptr uniformBuffer); inline void SetSrcBlend(BlendFunc func); inline void SetTexture(std::size_t textureIndex, std::shared_ptr texture); inline void SetTextureSampler(std::size_t textureIndex, std::shared_ptr sampler); + void UpdateShaderBinding(ShaderBinding& shaderBinding) const; + // Signals: NazaraSignal(OnMaterialRelease, const Material* /*material*/); private: inline void InvalidatePipeline(); + inline void InvalidateShaderBinding(); inline void UpdatePipeline() const; struct MaterialTexture @@ -111,9 +114,16 @@ namespace Nz std::shared_ptr texture; }; + struct UniformBuffer + { + std::shared_ptr buffer; + std::vector data; + bool dataInvalidated = true; + }; + std::shared_ptr m_settings; std::vector m_textures; - std::vector m_uniformBuffers; + std::vector m_uniformBuffers; mutable std::shared_ptr m_pipeline; UInt64 m_enabledConditions; mutable MaterialPipelineInfo m_pipelineInfo; diff --git a/include/Nazara/Graphics/Material.inl b/include/Nazara/Graphics/Material.inl index 036ad2b6e..4d16ec19e 100644 --- a/include/Nazara/Graphics/Material.inl +++ b/include/Nazara/Graphics/Material.inl @@ -442,16 +442,24 @@ namespace Nz return m_textures[textureIndex].sampler; } - inline UniformBufferRef& Material::GetUniformBuffer(std::size_t bufferIndex) + inline const std::shared_ptr& Material::GetUniformBuffer(std::size_t bufferIndex) const { NazaraAssert(bufferIndex < m_uniformBuffers.size(), "Invalid uniform buffer index"); - return m_uniformBuffers[bufferIndex]; + return m_uniformBuffers[bufferIndex].buffer; } - inline const UniformBufferRef& Material::GetUniformBuffer(std::size_t bufferIndex) const + inline std::vector& Material::GetUniformBufferData(std::size_t bufferIndex) { NazaraAssert(bufferIndex < m_uniformBuffers.size(), "Invalid uniform buffer index"); - return m_uniformBuffers[bufferIndex]; + UniformBuffer& uboEntry = m_uniformBuffers[bufferIndex]; + uboEntry.dataInvalidated = true; + return uboEntry.data; + } + + inline const std::vector& Material::GetUniformBufferConstData(std::size_t bufferIndex) + { + NazaraAssert(bufferIndex < m_uniformBuffers.size(), "Invalid uniform buffer index"); + return m_uniformBuffers[bufferIndex].data; } inline bool Material::HasTexture(std::size_t textureIndex) const @@ -666,22 +674,35 @@ namespace Nz InvalidatePipeline(); } - inline void Material::SetUniformBuffer(std::size_t bufferIndex, UniformBufferRef uniformBuffer) + inline void Material::SetUniformBuffer(std::size_t bufferIndex, std::shared_ptr uniformBuffer) { NazaraAssert(bufferIndex < m_uniformBuffers.size(), "Invalid shared uniform buffer index"); - m_uniformBuffers[bufferIndex] = std::move(uniformBuffer); + if (m_uniformBuffers[bufferIndex].buffer != uniformBuffer) + { + m_uniformBuffers[bufferIndex].buffer = std::move(uniformBuffer); + m_uniformBuffers[bufferIndex].dataInvalidated = true; + InvalidateShaderBinding(); + } } inline void Material::SetTexture(std::size_t textureIndex, std::shared_ptr texture) { NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index"); - m_textures[textureIndex].texture = std::move(texture); + if (m_textures[textureIndex].texture != texture) + { + m_textures[textureIndex].texture = std::move(texture); + InvalidateShaderBinding(); + } } inline void Material::SetTextureSampler(std::size_t textureIndex, std::shared_ptr sampler) { NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index"); - m_textures[textureIndex].sampler = std::move(sampler); + if (m_textures[textureIndex].sampler != sampler) + { + m_textures[textureIndex].sampler = std::move(sampler); + InvalidateShaderBinding(); + } } /*! @@ -705,6 +726,11 @@ namespace Nz m_pipelineUpdated = false; } + inline void Material::InvalidateShaderBinding() + { + //TODO + } + inline void Material::UpdatePipeline() const { for (auto& shader : m_pipelineInfo.shaders) diff --git a/src/Nazara/Graphics/BasicMaterial.cpp b/src/Nazara/Graphics/BasicMaterial.cpp index f92e61f7f..089438336 100644 --- a/src/Nazara/Graphics/BasicMaterial.cpp +++ b/src/Nazara/Graphics/BasicMaterial.cpp @@ -60,17 +60,18 @@ namespace Nz { NazaraAssert(HasAlphaTestThreshold(), "Material has no alpha threshold uniform"); - BufferMapper mapper(m_material.GetUniformBuffer(m_uniformBlockIndex), BufferAccess_ReadOnly); - return AccessByOffset(mapper.GetPointer(), m_uniformOffsets.alphaThreshold); + const std::vector& bufferData = m_material.GetUniformBufferConstData(m_uniformBlockIndex); + + return AccessByOffset(bufferData.data(), m_uniformOffsets.alphaThreshold); } Color BasicMaterial::GetDiffuseColor() const { NazaraAssert(HasDiffuseColor(), "Material has no diffuse color uniform"); - BufferMapper mapper(m_material.GetUniformBuffer(m_uniformBlockIndex), BufferAccess_ReadOnly); + const std::vector& bufferData = m_material.GetUniformBufferConstData(m_uniformBlockIndex); - const float* colorPtr = AccessByOffset(mapper.GetPointer(), m_uniformOffsets.diffuseColor); + const float* colorPtr = AccessByOffset(bufferData.data(), m_uniformOffsets.diffuseColor); return Color(colorPtr[0] * 255, colorPtr[1] * 255, colorPtr[2] * 255, colorPtr[3] * 255); //< TODO: Make color able to use float } @@ -78,16 +79,17 @@ namespace Nz { NazaraAssert(HasAlphaTestThreshold(), "Material has no alpha threshold uniform"); - BufferMapper mapper(m_material.GetUniformBuffer(m_uniformBlockIndex), BufferAccess_WriteOnly); - AccessByOffset(mapper.GetPointer(), m_uniformOffsets.alphaThreshold) = alphaThreshold; + std::vector& bufferData = m_material.GetUniformBufferData(m_uniformBlockIndex); + AccessByOffset(bufferData.data(), m_uniformOffsets.alphaThreshold) = alphaThreshold; } void BasicMaterial::SetDiffuseColor(const Color& diffuse) { NazaraAssert(HasDiffuseColor(), "Material has no diffuse color uniform"); - BufferMapper mapper(m_material.GetUniformBuffer(m_uniformBlockIndex), BufferAccess_WriteOnly); - float* colorPtr = AccessByOffset(mapper.GetPointer(), m_uniformOffsets.diffuseColor); + std::vector& bufferData = m_material.GetUniformBufferData(m_uniformBlockIndex); + + float* colorPtr = AccessByOffset(bufferData.data(), m_uniformOffsets.diffuseColor); colorPtr[0] = diffuse.r / 255.f; colorPtr[1] = diffuse.g / 255.f; colorPtr[2] = diffuse.b / 255.f; diff --git a/src/Nazara/Graphics/Material.cpp b/src/Nazara/Graphics/Material.cpp index 7a51c9ba2..4f12980b7 100644 --- a/src/Nazara/Graphics/Material.cpp +++ b/src/Nazara/Graphics/Material.cpp @@ -39,11 +39,53 @@ namespace Nz m_uniformBuffers.reserve(m_settings->GetUniformBlocks().size()); for (const auto& uniformBufferInfo : m_settings->GetUniformBlocks()) { - //TODO: Use pools - UniformBufferRef ubo = UniformBuffer::New(static_cast(uniformBufferInfo.blockSize), DataStorage_Hardware, BufferUsage_Dynamic); - ubo->Fill(uniformBufferInfo.defaultValues.data(), 0, uniformBufferInfo.defaultValues.size()); + auto& uniformBuffer = m_uniformBuffers.emplace_back(); - m_uniformBuffers.emplace_back(std::move(ubo)); + uniformBuffer.buffer = Graphics::Instance()->GetRenderDevice().InstantiateBuffer(Nz::BufferType_Uniform); + if (!uniformBuffer.buffer->Initialize(uniformBufferInfo.blockSize, BufferUsage_Dynamic)) + throw std::runtime_error("failed to initialize UBO memory"); + + assert(uniformBufferInfo.defaultValues.size() <= uniformBufferInfo.blockSize); + + uniformBuffer.buffer->Fill(uniformBufferInfo.defaultValues.data(), 0, uniformBufferInfo.defaultValues.size()); + uniformBuffer.data.resize(uniformBufferInfo.blockSize); + std::memcpy(uniformBuffer.data.data(), uniformBufferInfo.defaultValues.data(), uniformBufferInfo.defaultValues.size()); } } + + void Material::UpdateShaderBinding(ShaderBinding& shaderBinding) const + { + // TODO: Use StackVector + std::vector bindings; + + + std::size_t bindingIndex = 0; + + for (const auto& textureSlot : m_textures) + { + if (textureSlot.texture && textureSlot.sampler) + { + bindings.push_back({ + bindingIndex, + ShaderBinding::TextureBinding { + textureSlot.texture.get(), textureSlot.sampler.get() + } + }); + } + + bindingIndex++; + } + + for (const auto& ubo : m_uniformBuffers) + { + bindings.push_back({ + bindingIndex++, + ShaderBinding::UniformBufferBinding { + ubo.buffer.get(), 0, ubo.buffer->GetSize() + } + }); + } + + shaderBinding.Update(bindings.data(), bindings.size()); + } } diff --git a/src/Nazara/Graphics/PhongLightingMaterial.cpp b/src/Nazara/Graphics/PhongLightingMaterial.cpp index d8258c55a..c6d8f4297 100644 --- a/src/Nazara/Graphics/PhongLightingMaterial.cpp +++ b/src/Nazara/Graphics/PhongLightingMaterial.cpp @@ -49,17 +49,17 @@ namespace Nz { NazaraAssert(HasAlphaThreshold(), "Material has no alpha threshold uniform"); - BufferMapper mapper(m_material.GetUniformBuffer(m_phongUniformIndex), BufferAccess_ReadOnly); - return AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.alphaThreshold); + const std::vector& bufferData = m_material.GetUniformBufferConstData(m_phongUniformIndex); + return AccessByOffset(bufferData.data(), m_phongUniformOffsets.alphaThreshold); } Color PhongLightingMaterial::GetAmbientColor() const { NazaraAssert(HasAmbientColor(), "Material has no ambient color uniform"); - BufferMapper mapper(m_material.GetUniformBuffer(m_phongUniformIndex), BufferAccess_ReadOnly); + const std::vector& bufferData = m_material.GetUniformBufferConstData(m_phongUniformIndex); - const float* colorPtr = AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.ambientColor); + const float* colorPtr = AccessByOffset(bufferData.data(), m_phongUniformOffsets.ambientColor); return Color(colorPtr[0] * 255, colorPtr[1] * 255, colorPtr[2] * 255, colorPtr[3] * 255); //< TODO: Make color able to use float } @@ -67,9 +67,9 @@ namespace Nz { NazaraAssert(HasDiffuseColor(), "Material has no diffuse color uniform"); - BufferMapper mapper(m_material.GetUniformBuffer(m_phongUniformIndex), BufferAccess_ReadOnly); + const std::vector& bufferData = m_material.GetUniformBufferConstData(m_phongUniformIndex); - const float* colorPtr = AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.diffuseColor); + const float* colorPtr = AccessByOffset(bufferData.data(), m_phongUniformOffsets.diffuseColor); return Color(colorPtr[0] * 255, colorPtr[1] * 255, colorPtr[2] * 255, colorPtr[3] * 255); //< TODO: Make color able to use float } @@ -77,17 +77,17 @@ namespace Nz { NazaraAssert(HasShininess(), "Material has no shininess uniform"); - BufferMapper mapper(m_material.GetUniformBuffer(m_phongUniformIndex), BufferAccess_ReadOnly); - return AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.shininess); + const std::vector& bufferData = m_material.GetUniformBufferConstData(m_phongUniformIndex); + return AccessByOffset(bufferData.data(), m_phongUniformOffsets.shininess); } Color PhongLightingMaterial::GetSpecularColor() const { NazaraAssert(HasSpecularColor(), "Material has no specular color uniform"); - BufferMapper mapper(m_material.GetUniformBuffer(m_phongUniformIndex), BufferAccess_ReadOnly); + const std::vector& bufferData = m_material.GetUniformBufferConstData(m_phongUniformIndex); - const float* colorPtr = AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.specularColor); + const float* colorPtr = AccessByOffset(bufferData.data(), m_phongUniformOffsets.specularColor); return Color(colorPtr[0] * 255, colorPtr[1] * 255, colorPtr[2] * 255, colorPtr[3] * 255); //< TODO: Make color able to use float } @@ -95,16 +95,16 @@ namespace Nz { NazaraAssert(HasAlphaThreshold(), "Material has no alpha threshold uniform"); - BufferMapper mapper(m_material.GetUniformBuffer(m_phongUniformIndex), BufferAccess_WriteOnly); - AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.alphaThreshold) = alphaThreshold; + std::vector& bufferData = m_material.GetUniformBufferData(m_phongUniformIndex); + AccessByOffset(bufferData.data(), m_phongUniformOffsets.alphaThreshold) = alphaThreshold; } void PhongLightingMaterial::SetAmbientColor(const Color& ambient) { NazaraAssert(HasAmbientColor(), "Material has no ambient color uniform"); - BufferMapper mapper(m_material.GetUniformBuffer(m_phongUniformIndex), BufferAccess_WriteOnly); - float* colorPtr = AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.ambientColor); + std::vector& bufferData = m_material.GetUniformBufferData(m_phongUniformIndex); + float* colorPtr = AccessByOffset(bufferData.data(), m_phongUniformOffsets.ambientColor); colorPtr[0] = ambient.r / 255.f; colorPtr[1] = ambient.g / 255.f; colorPtr[2] = ambient.b / 255.f; @@ -115,8 +115,8 @@ namespace Nz { NazaraAssert(HasDiffuseColor(), "Material has no diffuse color uniform"); - BufferMapper mapper(m_material.GetUniformBuffer(m_phongUniformIndex), BufferAccess_WriteOnly); - float* colorPtr = AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.diffuseColor); + std::vector& bufferData = m_material.GetUniformBufferData(m_phongUniformIndex); + float* colorPtr = AccessByOffset(bufferData.data(), m_phongUniformOffsets.diffuseColor); colorPtr[0] = diffuse.r / 255.f; colorPtr[1] = diffuse.g / 255.f; colorPtr[2] = diffuse.b / 255.f; @@ -127,8 +127,8 @@ namespace Nz { NazaraAssert(HasSpecularColor(), "Material has no specular color uniform"); - BufferMapper mapper(m_material.GetUniformBuffer(m_phongUniformIndex), BufferAccess_WriteOnly); - float* colorPtr = AccessByOffset(mapper.GetPointer(), m_phongUniformOffsets.specularColor); + std::vector& bufferData = m_material.GetUniformBufferData(m_phongUniformIndex); + float* colorPtr = AccessByOffset(bufferData.data(), m_phongUniformOffsets.specularColor); colorPtr[0] = diffuse.r / 255.f; colorPtr[1] = diffuse.g / 255.f; colorPtr[2] = diffuse.b / 255.f; From e3e5c4ba8f98503887011569a1739c763889971c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 22 Jan 2021 23:32:32 +0100 Subject: [PATCH 045/278] Graphics: Add ModelInstance class --- examples/GraphicsTest/main.cpp | 89 +++++++++-------------- include/Nazara/Graphics/ModelInstance.hpp | 43 +++++++++++ include/Nazara/Graphics/ModelInstance.inl | 26 +++++++ src/Nazara/Graphics/ModelInstance.cpp | 52 +++++++++++++ 4 files changed, 154 insertions(+), 56 deletions(-) create mode 100644 include/Nazara/Graphics/ModelInstance.hpp create mode 100644 include/Nazara/Graphics/ModelInstance.inl create mode 100644 src/Nazara/Graphics/ModelInstance.cpp diff --git a/examples/GraphicsTest/main.cpp b/examples/GraphicsTest/main.cpp index 6575a1724..503d18936 100644 --- a/examples/GraphicsTest/main.cpp +++ b/examples/GraphicsTest/main.cpp @@ -115,13 +115,11 @@ int main() Nz::PredefinedViewerData viewerUboOffsets = Nz::PredefinedViewerData::GetOffsets(); const Nz::BasicMaterial::UniformOffsets& materialSettingOffsets = Nz::BasicMaterial::GetOffsets(); - std::vector instanceDataBuffer(instanceUboOffsets.totalSize); std::vector viewerDataBuffer(viewerUboOffsets.totalSize); std::vector materialSettings(materialSettingOffsets.totalSize); Nz::Vector2ui windowSize = window.GetSize(); - Nz::AccessByOffset(instanceDataBuffer.data(), instanceUboOffsets.worldMatrixOffset) = Nz::Matrix4f::Translate(Nz::Vector3f::Forward() * 2 + Nz::Vector3f::Right()); Nz::AccessByOffset(viewerDataBuffer.data(), viewerUboOffsets.viewMatrixOffset) = Nz::Matrix4f::Translate(Nz::Vector3f::Backward() * 1); Nz::AccessByOffset(viewerDataBuffer.data(), viewerUboOffsets.projMatrixOffset) = Nz::Matrix4f::Perspective(70.f, float(windowSize.x) / windowSize.y, 0.1f, 1000.f); @@ -130,22 +128,6 @@ int main() std::shared_ptr renderPipelineLayout = material.GetSettings()->GetRenderPipelineLayout(); - std::shared_ptr instanceDataUbo = device->InstantiateBuffer(Nz::BufferType_Uniform); - if (!instanceDataUbo->Initialize(instanceDataBuffer.size(), Nz::BufferUsage_DeviceLocal | Nz::BufferUsage_Dynamic)) - { - NazaraError("Failed to create instance UBO"); - return __LINE__; - } - - instanceDataUbo->Fill(instanceDataBuffer.data(), 0, instanceDataBuffer.size()); - - std::shared_ptr viewerDataUbo = device->InstantiateBuffer(Nz::BufferType_Uniform); - if (!viewerDataUbo->Initialize(viewerDataBuffer.size(), Nz::BufferUsage_DeviceLocal | Nz::BufferUsage_Dynamic)) - { - NazaraError("Failed to create viewer UBO"); - return __LINE__; - } - std::shared_ptr matSettingUBO = device->InstantiateBuffer(Nz::BufferType_Uniform); if (!matSettingUBO->Initialize(materialSettings.size(), Nz::BufferUsage_DeviceLocal | Nz::BufferUsage_Dynamic)) { @@ -155,40 +137,6 @@ int main() matSettingUBO->Fill(materialSettings.data(), 0, materialSettings.size()); - Nz::ShaderBindingPtr shaderBinding = renderPipelineLayout->AllocateShaderBinding(); - shaderBinding->Update({ - { - material.GetSettings()->GetPredefinedBindingIndex(Nz::PredefinedShaderBinding::UboViewerData), - Nz::ShaderBinding::UniformBufferBinding { - viewerDataUbo.get(), 0, viewerDataBuffer.size() - } - }, - { - material.GetSettings()->GetPredefinedBindingIndex(Nz::PredefinedShaderBinding::UboInstanceData), - Nz::ShaderBinding::UniformBufferBinding { - instanceDataUbo.get(), 0, instanceDataBuffer.size() - } - }, - { - 3, - Nz::ShaderBinding::UniformBufferBinding { - matSettingUBO.get(), 0, materialSettings.size() - } - }, - { - 0, - Nz::ShaderBinding::TextureBinding { - alphaTexture.get(), textureSampler.get() - } - }, - { - 1, - Nz::ShaderBinding::TextureBinding { - texture.get(), textureSampler.get() - } - } - }); - std::vector vertexBuffers = { { 0, @@ -196,6 +144,30 @@ int main() } }; + std::vector instanceDataBuffer(instanceUboOffsets.totalSize); + + Nz::ModelInstance modelInstance(material.GetSettings()); + { + material.UpdateShaderBinding(modelInstance.GetShaderBinding()); + + Nz::AccessByOffset(instanceDataBuffer.data(), instanceUboOffsets.worldMatrixOffset) = Nz::Matrix4f::Translate(Nz::Vector3f::Forward() * 2 + Nz::Vector3f::Right()); + + std::shared_ptr& instanceDataUBO = modelInstance.GetInstanceBuffer(); + instanceDataUBO->Fill(instanceDataBuffer.data(), 0, instanceDataBuffer.size()); + } + + Nz::ModelInstance modelInstance2(material.GetSettings()); + { + material.UpdateShaderBinding(modelInstance2.GetShaderBinding()); + + Nz::AccessByOffset(instanceDataBuffer.data(), instanceUboOffsets.worldMatrixOffset) = Nz::Matrix4f::Translate(Nz::Vector3f::Forward() * 2 + Nz::Vector3f::Right() * 3.f); + + std::shared_ptr& instanceDataUBO = modelInstance2.GetInstanceBuffer(); + instanceDataUBO->Fill(instanceDataBuffer.data(), 0, instanceDataBuffer.size()); + } + + std::shared_ptr viewerDataUBO = Nz::Graphics::Instance()->GetViewerDataUBO(); + std::shared_ptr pipeline = material.GetPipeline()->GetRenderPipeline(vertexBuffers); Nz::RenderDevice* renderDevice = window.GetRenderDevice().get(); @@ -239,13 +211,18 @@ int main() { builder.BeginRenderPass(windowImpl->GetFramebuffer(), windowImpl->GetRenderPass(), renderRect, { clearValues[0], clearValues[1] }); { + builder.SetScissor(Nz::Recti{ 0, 0, int(windowSize.x), int(windowSize.y) }); + builder.SetViewport(Nz::Recti{ 0, 0, int(windowSize.x), int(windowSize.y) }); + builder.BindIndexBuffer(indexBufferImpl); builder.BindPipeline(*pipeline); builder.BindVertexBuffer(0, vertexBufferImpl); - builder.BindShaderBinding(*shaderBinding); - builder.SetScissor(Nz::Recti{ 0, 0, int(windowSize.x), int(windowSize.y) }); - builder.SetViewport(Nz::Recti{ 0, 0, int(windowSize.x), int(windowSize.y) }); + builder.BindShaderBinding(modelInstance.GetShaderBinding()); + + builder.DrawIndexed(drfreakIB->GetIndexCount()); + + builder.BindShaderBinding(modelInstance2.GetShaderBinding()); builder.DrawIndexed(drfreakIB->GetIndexCount()); } @@ -363,7 +340,7 @@ int main() builder.BeginDebugRegion("UBO Update", Nz::Color::Yellow); { builder.PreTransferBarrier(); - builder.CopyBuffer(allocation, viewerDataUbo.get()); + builder.CopyBuffer(allocation, viewerDataUBO.get()); builder.PostTransferBarrier(); } builder.EndDebugRegion(); diff --git a/include/Nazara/Graphics/ModelInstance.hpp b/include/Nazara/Graphics/ModelInstance.hpp new file mode 100644 index 000000000..4067249e4 --- /dev/null +++ b/include/Nazara/Graphics/ModelInstance.hpp @@ -0,0 +1,43 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_MODELINSTANCE_HPP +#define NAZARA_MODELINSTANCE_HPP + +#include +#include +#include +#include + +namespace Nz +{ + class AbstractBuffer; + class MaterialSettings; + + class NAZARA_GRAPHICS_API ModelInstance + { + public: + ModelInstance(const std::shared_ptr& settings); + ModelInstance(const ModelInstance&) = delete; + ModelInstance(ModelInstance&&) noexcept = default; + ~ModelInstance() = default; + + inline std::shared_ptr& GetInstanceBuffer(); + inline const std::shared_ptr& GetInstanceBuffer() const; + inline ShaderBinding& GetShaderBinding(); + + ModelInstance& operator=(const ModelInstance&) = delete; + ModelInstance& operator=(ModelInstance&&) noexcept = default; + + private: + std::shared_ptr m_instanceDataBuffer; + ShaderBindingPtr m_shaderBinding; + }; +} + +#include + +#endif // NAZARA_MODELINSTANCE_HPP diff --git a/include/Nazara/Graphics/ModelInstance.inl b/include/Nazara/Graphics/ModelInstance.inl new file mode 100644 index 000000000..2c87c6ecf --- /dev/null +++ b/include/Nazara/Graphics/ModelInstance.inl @@ -0,0 +1,26 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + inline std::shared_ptr& ModelInstance::GetInstanceBuffer() + { + return m_instanceDataBuffer; + } + + inline const std::shared_ptr& ModelInstance::GetInstanceBuffer() const + { + return m_instanceDataBuffer; + } + + inline ShaderBinding& ModelInstance::GetShaderBinding() + { + return *m_shaderBinding; + } +} + +#include diff --git a/src/Nazara/Graphics/ModelInstance.cpp b/src/Nazara/Graphics/ModelInstance.cpp new file mode 100644 index 000000000..96479ea0b --- /dev/null +++ b/src/Nazara/Graphics/ModelInstance.cpp @@ -0,0 +1,52 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + ModelInstance::ModelInstance(const std::shared_ptr& settings) + { + Nz::PredefinedInstanceData instanceUboOffsets = Nz::PredefinedInstanceData::GetOffsets(); + + m_instanceDataBuffer = Graphics::Instance()->GetRenderDevice().InstantiateBuffer(BufferType_Uniform); + if (!m_instanceDataBuffer->Initialize(instanceUboOffsets.totalSize, Nz::BufferUsage_DeviceLocal | Nz::BufferUsage_Dynamic)) + throw std::runtime_error("failed to initialize viewer data UBO"); + + m_shaderBinding = settings->GetRenderPipelineLayout()->AllocateShaderBinding(); + + // TODO: Use StackVector + StackVector bindings = NazaraStackVector(ShaderBinding::Binding, 2); + + if (std::size_t bindingIndex = settings->GetPredefinedBindingIndex(PredefinedShaderBinding::UboInstanceData); bindingIndex != MaterialSettings::InvalidIndex) + { + bindings.push_back({ + bindingIndex, + ShaderBinding::UniformBufferBinding { + m_instanceDataBuffer.get(), 0, m_instanceDataBuffer->GetSize() + } + }); + } + + if (std::size_t bindingIndex = settings->GetPredefinedBindingIndex(PredefinedShaderBinding::UboViewerData); bindingIndex != MaterialSettings::InvalidIndex) + { + const std::shared_ptr& instanceDataUBO = Graphics::Instance()->GetViewerDataUBO(); + + bindings.push_back({ + bindingIndex, + ShaderBinding::UniformBufferBinding { + instanceDataUBO.get(), 0, instanceDataUBO->GetSize() + } + }); + } + + if (!bindings.empty()) + m_shaderBinding->Update(bindings.data(), bindings.size()); + } +} From a1e0ae3f3821c3dea1324fa6e54f9b44b4351ec1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 27 Jan 2021 16:44:06 +0100 Subject: [PATCH 046/278] Utility/IndexBuffer: Fix GetStride() method for big meshes --- include/Nazara/Utility/IndexBuffer.inl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/Nazara/Utility/IndexBuffer.inl b/include/Nazara/Utility/IndexBuffer.inl index d9a93f471..ebd6798e8 100644 --- a/include/Nazara/Utility/IndexBuffer.inl +++ b/include/Nazara/Utility/IndexBuffer.inl @@ -24,7 +24,7 @@ namespace Nz inline std::size_t IndexBuffer::GetStride() const { - return static_cast((m_largeIndices) ? sizeof(std::size_t) : sizeof(UInt16)); + return static_cast((m_largeIndices) ? sizeof(UInt32) : sizeof(UInt16)); } inline std::size_t IndexBuffer::GetStartOffset() const From a9e9ef252410dad38b7a768671326350aa7e0cda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 27 Jan 2021 16:45:00 +0100 Subject: [PATCH 047/278] Graphics: Add GraphicalMesh and Model classes --- examples/GraphicsTest/main.cpp | 90 ++++++----------------- include/Nazara/Graphics/GraphicalMesh.hpp | 50 +++++++++++++ include/Nazara/Graphics/GraphicalMesh.inl | 41 +++++++++++ include/Nazara/Graphics/Model.hpp | 55 ++++++++++++++ include/Nazara/Graphics/Model.inl | 23 ++++++ src/Nazara/Graphics/GraphicalMesh.cpp | 56 ++++++++++++++ src/Nazara/Graphics/Model.cpp | 51 +++++++++++++ 7 files changed, 300 insertions(+), 66 deletions(-) create mode 100644 include/Nazara/Graphics/GraphicalMesh.hpp create mode 100644 include/Nazara/Graphics/GraphicalMesh.inl create mode 100644 include/Nazara/Graphics/Model.hpp create mode 100644 include/Nazara/Graphics/Model.inl create mode 100644 src/Nazara/Graphics/GraphicalMesh.cpp create mode 100644 src/Nazara/Graphics/Model.cpp diff --git a/examples/GraphicsTest/main.cpp b/examples/GraphicsTest/main.cpp index 503d18936..d28511846 100644 --- a/examples/GraphicsTest/main.cpp +++ b/examples/GraphicsTest/main.cpp @@ -23,6 +23,7 @@ int main() Nz::RenderWindow window; Nz::MeshParams meshParams; + meshParams.storage = Nz::DataStorage_Software; meshParams.matrix = Nz::Matrix4f::Rotate(Nz::EulerAnglesf(0.f, 90.f, 180.f)) * Nz::Matrix4f::Scale(Nz::Vector3f(0.002f)); meshParams.vertexDeclaration = Nz::VertexDeclaration::Get(Nz::VertexLayout_XYZ_Normal_UV); @@ -42,16 +43,7 @@ int main() return __LINE__; } - Nz::StaticMesh* drfreakMesh = static_cast(drfreak->GetSubMesh(0)); - - const Nz::VertexBuffer* drfreakVB = drfreakMesh->GetVertexBuffer(); - const Nz::IndexBuffer* drfreakIB = drfreakMesh->GetIndexBuffer(); - - // Index buffer - std::cout << "Index count: " << drfreakIB->GetIndexCount() << std::endl; - - // Vertex buffer - std::cout << "Vertex count: " << drfreakVB->GetVertexCount() << std::endl; + std::shared_ptr gfxMesh = std::make_shared(drfreak); // Texture Nz::ImageRef drfreakImage = Nz::Image::LoadFromFile("resources/Spaceship/Texture/diffuse.png"); @@ -101,16 +93,20 @@ int main() std::shared_ptr textureSampler = device->InstantiateTextureSampler({}); - Nz::Material material(Nz::BasicMaterial::GetSettings()); - material.EnableDepthBuffer(true); + std::shared_ptr material = std::make_shared(Nz::BasicMaterial::GetSettings()); + material->EnableDepthBuffer(true); - Nz::BasicMaterial basicMat(material); + Nz::BasicMaterial basicMat(*material); basicMat.EnableAlphaTest(false); basicMat.SetAlphaMap(alphaTexture); basicMat.SetAlphaSampler(textureSampler); basicMat.SetDiffuseMap(texture); basicMat.SetDiffuseSampler(textureSampler); + Nz::Model model(std::move(gfxMesh)); + for (std::size_t i = 0; i < model.GetSubMeshCount(); ++i) + model.SetMaterial(i, material); + Nz::PredefinedInstanceData instanceUboOffsets = Nz::PredefinedInstanceData::GetOffsets(); Nz::PredefinedViewerData viewerUboOffsets = Nz::PredefinedViewerData::GetOffsets(); const Nz::BasicMaterial::UniformOffsets& materialSettingOffsets = Nz::BasicMaterial::GetOffsets(); @@ -126,29 +122,11 @@ int main() Nz::AccessByOffset(materialSettings.data(), materialSettingOffsets.alphaThreshold) = 0.5f; Nz::AccessByOffset(materialSettings.data(), materialSettingOffsets.diffuseColor) = Nz::Vector4f(1.f, 1.f, 1.f, 1.f); - std::shared_ptr renderPipelineLayout = material.GetSettings()->GetRenderPipelineLayout(); - - std::shared_ptr matSettingUBO = device->InstantiateBuffer(Nz::BufferType_Uniform); - if (!matSettingUBO->Initialize(materialSettings.size(), Nz::BufferUsage_DeviceLocal | Nz::BufferUsage_Dynamic)) - { - NazaraError("Failed to create mat setting UBO"); - return __LINE__; - } - - matSettingUBO->Fill(materialSettings.data(), 0, materialSettings.size()); - - std::vector vertexBuffers = { - { - 0, - drfreakVB->GetVertexDeclaration() - } - }; - std::vector instanceDataBuffer(instanceUboOffsets.totalSize); - Nz::ModelInstance modelInstance(material.GetSettings()); + Nz::ModelInstance modelInstance(material->GetSettings()); { - material.UpdateShaderBinding(modelInstance.GetShaderBinding()); + material->UpdateShaderBinding(modelInstance.GetShaderBinding()); Nz::AccessByOffset(instanceDataBuffer.data(), instanceUboOffsets.worldMatrixOffset) = Nz::Matrix4f::Translate(Nz::Vector3f::Forward() * 2 + Nz::Vector3f::Right()); @@ -156,9 +134,9 @@ int main() instanceDataUBO->Fill(instanceDataBuffer.data(), 0, instanceDataBuffer.size()); } - Nz::ModelInstance modelInstance2(material.GetSettings()); + Nz::ModelInstance modelInstance2(material->GetSettings()); { - material.UpdateShaderBinding(modelInstance2.GetShaderBinding()); + material->UpdateShaderBinding(modelInstance2.GetShaderBinding()); Nz::AccessByOffset(instanceDataBuffer.data(), instanceUboOffsets.worldMatrixOffset) = Nz::Matrix4f::Translate(Nz::Vector3f::Forward() * 2 + Nz::Vector3f::Right() * 3.f); @@ -168,31 +146,9 @@ int main() std::shared_ptr viewerDataUBO = Nz::Graphics::Instance()->GetViewerDataUBO(); - std::shared_ptr pipeline = material.GetPipeline()->GetRenderPipeline(vertexBuffers); - - Nz::RenderDevice* renderDevice = window.GetRenderDevice().get(); - Nz::RenderWindowImpl* windowImpl = window.GetImpl(); std::shared_ptr commandPool = windowImpl->CreateCommandPool(Nz::QueueType::Graphics); - Nz::RenderBuffer* renderBufferIB = static_cast(drfreakIB->GetBuffer()->GetImpl()); - Nz::RenderBuffer* renderBufferVB = static_cast(drfreakVB->GetBuffer()->GetImpl()); - - if (!renderBufferIB->Synchronize(renderDevice)) - { - NazaraError("Failed to synchronize render buffer"); - return __LINE__; - } - - if (!renderBufferVB->Synchronize(renderDevice)) - { - NazaraError("Failed to synchronize render buffer"); - return __LINE__; - } - - Nz::AbstractBuffer* indexBufferImpl = renderBufferIB->GetHardwareBuffer(renderDevice); - Nz::AbstractBuffer* vertexBufferImpl = renderBufferVB->GetHardwareBuffer(renderDevice); - Nz::CommandBufferPtr drawCommandBuffer; auto RebuildCommandBuffer = [&] { @@ -214,17 +170,19 @@ int main() builder.SetScissor(Nz::Recti{ 0, 0, int(windowSize.x), int(windowSize.y) }); builder.SetViewport(Nz::Recti{ 0, 0, int(windowSize.x), int(windowSize.y) }); - builder.BindIndexBuffer(indexBufferImpl); - builder.BindPipeline(*pipeline); - builder.BindVertexBuffer(0, vertexBufferImpl); + for (Nz::ModelInstance& modelInstance : { std::ref(modelInstance), std::ref(modelInstance2) }) + { + builder.BindShaderBinding(modelInstance.GetShaderBinding()); - builder.BindShaderBinding(modelInstance.GetShaderBinding()); + for (std::size_t i = 0; i < model.GetSubMeshCount(); ++i) + { + builder.BindIndexBuffer(model.GetIndexBuffer(i).get()); + builder.BindVertexBuffer(0, model.GetVertexBuffer(i).get()); + builder.BindPipeline(*model.GetRenderPipeline(i)); - builder.DrawIndexed(drfreakIB->GetIndexCount()); - - builder.BindShaderBinding(modelInstance2.GetShaderBinding()); - - builder.DrawIndexed(drfreakIB->GetIndexCount()); + builder.DrawIndexed(model.GetIndexCount(i)); + } + } } builder.EndRenderPass(); } diff --git a/include/Nazara/Graphics/GraphicalMesh.hpp b/include/Nazara/Graphics/GraphicalMesh.hpp new file mode 100644 index 000000000..cc68dcf95 --- /dev/null +++ b/include/Nazara/Graphics/GraphicalMesh.hpp @@ -0,0 +1,50 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_GRAPHICALMESH_HPP +#define NAZARA_GRAPHICALMESH_HPP + +#include +#include +#include +#include +#include + +namespace Nz +{ + class NAZARA_GRAPHICS_API GraphicalMesh + { + public: + GraphicalMesh(const Mesh* mesh); + GraphicalMesh(const GraphicalMesh&) = delete; + GraphicalMesh(GraphicalMesh&&) noexcept = default; + ~GraphicalMesh() = default; + + inline const std::shared_ptr& GetIndexBuffer(std::size_t subMesh) const; + inline std::size_t GetIndexCount(std::size_t subMesh) const; + inline const std::shared_ptr& GetVertexBuffer(std::size_t subMesh) const; + inline const VertexDeclarationConstRef& GetVertexDeclaration(std::size_t subMesh) const; + inline std::size_t GetSubMeshCount() const; + + GraphicalMesh& operator=(const GraphicalMesh&) = delete; + GraphicalMesh& operator=(GraphicalMesh&&) noexcept = default; + + private: + struct GraphicalSubMesh + { + std::shared_ptr indexBuffer; + std::shared_ptr vertexBuffer; + std::size_t indexCount; + VertexDeclarationConstRef vertexDeclaration; + }; + + std::vector m_subMeshes; + }; +} + +#include + +#endif // NAZARA_GRAPHICALMESH_HPP diff --git a/include/Nazara/Graphics/GraphicalMesh.inl b/include/Nazara/Graphics/GraphicalMesh.inl new file mode 100644 index 000000000..f00facb56 --- /dev/null +++ b/include/Nazara/Graphics/GraphicalMesh.inl @@ -0,0 +1,41 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +namespace Nz +{ + inline const std::shared_ptr& GraphicalMesh::GetIndexBuffer(std::size_t subMesh) const + { + assert(subMesh < m_subMeshes.size()); + return m_subMeshes[subMesh].indexBuffer; + } + + inline std::size_t GraphicalMesh::GetIndexCount(std::size_t subMesh) const + { + assert(subMesh < m_subMeshes.size()); + return m_subMeshes[subMesh].indexCount; + } + + inline const std::shared_ptr& GraphicalMesh::GetVertexBuffer(std::size_t subMesh) const + { + assert(subMesh < m_subMeshes.size()); + return m_subMeshes[subMesh].vertexBuffer; + } + + inline const VertexDeclarationConstRef& GraphicalMesh::GetVertexDeclaration(std::size_t subMesh) const + { + assert(subMesh < m_subMeshes.size()); + return m_subMeshes[subMesh].vertexDeclaration; + } + + inline std::size_t GraphicalMesh::GetSubMeshCount() const + { + return m_subMeshes.size(); + } +} + +#include diff --git a/include/Nazara/Graphics/Model.hpp b/include/Nazara/Graphics/Model.hpp new file mode 100644 index 000000000..47f9a1697 --- /dev/null +++ b/include/Nazara/Graphics/Model.hpp @@ -0,0 +1,55 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_MODEL_HPP +#define NAZARA_MODEL_HPP + +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + class GraphicalMesh; + class Material; + + class NAZARA_GRAPHICS_API Model + { + public: + Model(std::shared_ptr graphicalMesh); + Model(const Model&) = delete; + Model(Model&&) noexcept = default; + ~Model() = default; + + const std::shared_ptr& GetIndexBuffer(std::size_t subMeshIndex) const; + std::size_t GetIndexCount(std::size_t subMeshIndex) const; + const std::shared_ptr& GetRenderPipeline(std::size_t subMeshIndex) const; + const std::shared_ptr& GetVertexBuffer(std::size_t subMeshIndex) const; + inline std::size_t GetSubMeshCount() const; + + inline void SetMaterial(std::size_t subMeshIndex, std::shared_ptr material); + + Model& operator=(const Model&) = delete; + Model& operator=(Model&&) noexcept = default; + + private: + struct SubMeshData + { + std::shared_ptr material; + std::vector vertexBufferData; + }; + + std::shared_ptr m_graphicalMesh; + std::vector m_subMeshes; + }; +} + +#include + +#endif diff --git a/include/Nazara/Graphics/Model.inl b/include/Nazara/Graphics/Model.inl new file mode 100644 index 000000000..de31598dc --- /dev/null +++ b/include/Nazara/Graphics/Model.inl @@ -0,0 +1,23 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +namespace Nz +{ + inline std::size_t Model::GetSubMeshCount() const + { + return m_subMeshes.size(); + } + + inline void Model::SetMaterial(std::size_t subMeshIndex, std::shared_ptr material) + { + assert(subMeshIndex < m_subMeshes.size()); + m_subMeshes[subMeshIndex].material = std::move(material); + } +} + +#include diff --git a/src/Nazara/Graphics/GraphicalMesh.cpp b/src/Nazara/Graphics/GraphicalMesh.cpp new file mode 100644 index 000000000..a3042155c --- /dev/null +++ b/src/Nazara/Graphics/GraphicalMesh.cpp @@ -0,0 +1,56 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + GraphicalMesh::GraphicalMesh(const Mesh* mesh) + { + assert(mesh->GetAnimationType() == AnimationType_Static); + + RenderDevice& renderDevice = Graphics::Instance()->GetRenderDevice(); + + m_subMeshes.reserve(mesh->GetSubMeshCount()); + for (std::size_t i = 0; i < mesh->GetSubMeshCount(); ++i) + { + const SubMesh* subMesh = mesh->GetSubMesh(i); + + const StaticMesh* staticMesh = static_cast(subMesh); + + const IndexBuffer* indexBuffer = staticMesh->GetIndexBuffer(); + const VertexBuffer* vertexBuffer = staticMesh->GetVertexBuffer(); + + assert(indexBuffer->GetBuffer()->GetStorage() == DataStorage_Software); + const SoftwareBuffer* indexBufferContent = static_cast(indexBuffer->GetBuffer()->GetImpl()); + + assert(vertexBuffer->GetBuffer()->GetStorage() == DataStorage_Software); + const SoftwareBuffer* vertexBufferContent = static_cast(vertexBuffer->GetBuffer()->GetImpl()); + + auto& submeshData = m_subMeshes.emplace_back(); + submeshData.indexBuffer = renderDevice.InstantiateBuffer(BufferType_Index); + if (!submeshData.indexBuffer->Initialize(indexBuffer->GetStride() * indexBuffer->GetIndexCount(), BufferUsage_DeviceLocal)) + throw std::runtime_error("failed to create index buffer"); + + if (!submeshData.indexBuffer->Fill(indexBufferContent->GetData() + indexBuffer->GetStartOffset(), 0, indexBuffer->GetEndOffset() - indexBuffer->GetStartOffset())) + throw std::runtime_error("failed to fill index buffer"); + + submeshData.indexCount = indexBuffer->GetIndexCount(); + + submeshData.vertexBuffer = renderDevice.InstantiateBuffer(BufferType_Vertex); + if (!submeshData.vertexBuffer->Initialize(vertexBuffer->GetStride() * vertexBuffer->GetVertexCount(), BufferUsage_DeviceLocal)) + throw std::runtime_error("failed to create vertex buffer"); + + if (!submeshData.vertexBuffer->Fill(vertexBufferContent->GetData() + vertexBuffer->GetStartOffset(), 0, vertexBuffer->GetEndOffset() - vertexBuffer->GetStartOffset())) + throw std::runtime_error("failed to fill vertex buffer"); + + submeshData.vertexDeclaration = vertexBuffer->GetVertexDeclaration(); + } + } +} diff --git a/src/Nazara/Graphics/Model.cpp b/src/Nazara/Graphics/Model.cpp new file mode 100644 index 000000000..aff54d805 --- /dev/null +++ b/src/Nazara/Graphics/Model.cpp @@ -0,0 +1,51 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include + +namespace Nz +{ + inline Model::Model(std::shared_ptr graphicalMesh) : + m_graphicalMesh(std::move(graphicalMesh)) + { + m_subMeshes.reserve(m_graphicalMesh->GetSubMeshCount()); + for (std::size_t i = 0; i < m_graphicalMesh->GetSubMeshCount(); ++i) + { + auto& subMeshData = m_subMeshes.emplace_back(); + //subMeshData.material = DefaultMaterial; //< TODO + subMeshData.vertexBufferData = { + { + 0, + m_graphicalMesh->GetVertexDeclaration(i) + } + }; + } + } + + const std::shared_ptr& Model::GetIndexBuffer(std::size_t subMeshIndex) const + { + return m_graphicalMesh->GetIndexBuffer(subMeshIndex); + } + + std::size_t Model::GetIndexCount(std::size_t subMeshIndex) const + { + return m_graphicalMesh->GetIndexCount(subMeshIndex); + } + + const std::shared_ptr& Model::GetRenderPipeline(std::size_t subMeshIndex) const + { + assert(subMeshIndex < m_subMeshes.size()); + const auto& subMeshData = m_subMeshes[subMeshIndex]; + return subMeshData.material->GetPipeline()->GetRenderPipeline(subMeshData.vertexBufferData); + } + + const std::shared_ptr& Model::GetVertexBuffer(std::size_t subMeshIndex) const + { + return m_graphicalMesh->GetVertexBuffer(subMeshIndex); + } + +} From 78c3f573330331cef2ddf3f174bf997a7ee0c806 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 27 Jan 2021 16:45:11 +0100 Subject: [PATCH 048/278] Regenerate global headers --- include/Nazara/Graphics.hpp | 4 ++++ include/Nazara/Shader.hpp | 3 +++ 2 files changed, 7 insertions(+) diff --git a/include/Nazara/Graphics.hpp b/include/Nazara/Graphics.hpp index 44540452e..6601a7947 100644 --- a/include/Nazara/Graphics.hpp +++ b/include/Nazara/Graphics.hpp @@ -33,12 +33,16 @@ #include #include #include +#include #include #include #include #include +#include +#include #include #include #include +#include #endif // NAZARA_GLOBAL_GRAPHICS_HPP diff --git a/include/Nazara/Shader.hpp b/include/Nazara/Shader.hpp index d72fa4367..f8e41ff22 100644 --- a/include/Nazara/Shader.hpp +++ b/include/Nazara/Shader.hpp @@ -34,8 +34,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -49,6 +51,7 @@ #include #include #include +#include #include #include #include From b9151d8a7a706efab50202822078bc8e54876ba9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 27 Jan 2021 18:50:49 +0100 Subject: [PATCH 049/278] Graphics: Improve TextureSampler handling --- examples/GraphicsTest/main.cpp | 6 --- include/Nazara/Graphics/BasicMaterial.hpp | 8 +-- include/Nazara/Graphics/BasicMaterial.inl | 8 +-- include/Nazara/Graphics/Graphics.hpp | 4 ++ include/Nazara/Graphics/Graphics.inl | 5 ++ include/Nazara/Graphics/Material.hpp | 8 +-- include/Nazara/Graphics/Material.inl | 20 +++++--- .../Nazara/Graphics/TextureSamplerCache.hpp | 40 +++++++++++++++ .../Nazara/Graphics/TextureSamplerCache.inl | 17 +++++++ include/Nazara/Renderer/TextureSampler.hpp | 6 +++ include/Nazara/Renderer/TextureSampler.inl | 50 +++++++++++++++++++ src/Nazara/Graphics/Graphics.cpp | 2 + src/Nazara/Graphics/Material.cpp | 9 +++- src/Nazara/Graphics/TextureSamplerCache.cpp | 19 +++++++ .../VulkanRenderer/VulkanUploadPool.cpp | 6 +-- 15 files changed, 181 insertions(+), 27 deletions(-) create mode 100644 include/Nazara/Graphics/TextureSamplerCache.hpp create mode 100644 include/Nazara/Graphics/TextureSamplerCache.inl create mode 100644 src/Nazara/Graphics/TextureSamplerCache.cpp diff --git a/examples/GraphicsTest/main.cpp b/examples/GraphicsTest/main.cpp index d28511846..e967a930a 100644 --- a/examples/GraphicsTest/main.cpp +++ b/examples/GraphicsTest/main.cpp @@ -89,19 +89,13 @@ int main() return __LINE__; } - - - std::shared_ptr textureSampler = device->InstantiateTextureSampler({}); - std::shared_ptr material = std::make_shared(Nz::BasicMaterial::GetSettings()); material->EnableDepthBuffer(true); Nz::BasicMaterial basicMat(*material); basicMat.EnableAlphaTest(false); basicMat.SetAlphaMap(alphaTexture); - basicMat.SetAlphaSampler(textureSampler); basicMat.SetDiffuseMap(texture); - basicMat.SetDiffuseSampler(textureSampler); Nz::Model model(std::move(gfxMesh)); for (std::size_t i = 0; i < model.GetSubMeshCount(); ++i) diff --git a/include/Nazara/Graphics/BasicMaterial.hpp b/include/Nazara/Graphics/BasicMaterial.hpp index ff4815732..8142e9cc0 100644 --- a/include/Nazara/Graphics/BasicMaterial.hpp +++ b/include/Nazara/Graphics/BasicMaterial.hpp @@ -24,11 +24,11 @@ namespace Nz inline void EnableAlphaTest(bool alphaTest); inline const std::shared_ptr& GetAlphaMap() const; - inline const std::shared_ptr& GetAlphaSampler() const; + inline const TextureSamplerInfo& GetAlphaSampler() const; float GetAlphaTestThreshold() const; Color GetDiffuseColor() const; inline const std::shared_ptr& GetDiffuseMap() const; - inline const std::shared_ptr& GetDiffuseSampler() const; + inline const TextureSamplerInfo& GetDiffuseSampler() const; inline bool HasAlphaMap() const; inline bool HasAlphaTest() const; @@ -37,11 +37,11 @@ namespace Nz inline bool HasDiffuseMap() const; inline void SetAlphaMap(std::shared_ptr alphaMap); - inline void SetAlphaSampler(std::shared_ptr alphaSampler); + inline void SetAlphaSampler(TextureSamplerInfo alphaSampler); void SetAlphaTestThreshold(float alphaThreshold); void SetDiffuseColor(const Color& diffuse); inline void SetDiffuseMap(std::shared_ptr diffuseMap); - inline void SetDiffuseSampler(std::shared_ptr diffuseSampler); + inline void SetDiffuseSampler(TextureSamplerInfo diffuseSampler); static inline const UniformOffsets& GetOffsets(); static inline const std::shared_ptr& GetSettings(); diff --git a/include/Nazara/Graphics/BasicMaterial.inl b/include/Nazara/Graphics/BasicMaterial.inl index 8eb32ff7f..4ed3ad8ca 100644 --- a/include/Nazara/Graphics/BasicMaterial.inl +++ b/include/Nazara/Graphics/BasicMaterial.inl @@ -35,7 +35,7 @@ namespace Nz return m_material.GetTexture(m_textureIndexes.alpha); } - inline const std::shared_ptr& BasicMaterial::GetAlphaSampler() const + inline const TextureSamplerInfo& BasicMaterial::GetAlphaSampler() const { NazaraAssert(HasAlphaMap(), "Material has no alpha texture slot"); return m_material.GetTextureSampler(m_textureIndexes.alpha); @@ -47,7 +47,7 @@ namespace Nz return m_material.GetTexture(m_textureIndexes.diffuse); } - inline const std::shared_ptr& BasicMaterial::GetDiffuseSampler() const + inline const TextureSamplerInfo& BasicMaterial::GetDiffuseSampler() const { NazaraAssert(HasDiffuseMap(), "Material has no alpha texture slot"); return m_material.GetTextureSampler(m_textureIndexes.diffuse); @@ -88,7 +88,7 @@ namespace Nz m_material.EnableCondition(m_conditionIndexes.hasAlphaMap, hasAlphaMap); } - inline void BasicMaterial::SetAlphaSampler(std::shared_ptr alphaSampler) + inline void BasicMaterial::SetAlphaSampler(TextureSamplerInfo alphaSampler) { NazaraAssert(HasAlphaMap(), "Material has no alpha map slot"); m_material.SetTextureSampler(m_textureIndexes.alpha, std::move(alphaSampler)); @@ -104,7 +104,7 @@ namespace Nz m_material.EnableCondition(m_conditionIndexes.hasDiffuseMap, hasDiffuseMap); } - inline void BasicMaterial::SetDiffuseSampler(std::shared_ptr diffuseSampler) + inline void BasicMaterial::SetDiffuseSampler(TextureSamplerInfo diffuseSampler) { NazaraAssert(HasDiffuseMap(), "Material has no diffuse map slot"); m_material.SetTextureSampler(m_textureIndexes.diffuse, std::move(diffuseSampler)); diff --git a/include/Nazara/Graphics/Graphics.hpp b/include/Nazara/Graphics/Graphics.hpp index 954719f15..4f6f5115b 100644 --- a/include/Nazara/Graphics/Graphics.hpp +++ b/include/Nazara/Graphics/Graphics.hpp @@ -9,8 +9,10 @@ #include #include +#include #include #include +#include namespace Nz { @@ -30,6 +32,7 @@ namespace Nz ~Graphics(); inline RenderDevice& GetRenderDevice(); + inline TextureSamplerCache& GetSamplerCache(); inline const std::shared_ptr& GetViewerDataUBO(); struct Config @@ -38,6 +41,7 @@ namespace Nz }; private: + std::optional m_samplerCache; std::shared_ptr m_viewerDataUBO; std::shared_ptr m_renderDevice; diff --git a/include/Nazara/Graphics/Graphics.inl b/include/Nazara/Graphics/Graphics.inl index 35023cfc5..a4e581e5a 100644 --- a/include/Nazara/Graphics/Graphics.inl +++ b/include/Nazara/Graphics/Graphics.inl @@ -12,6 +12,11 @@ namespace Nz return *m_renderDevice; } + inline TextureSamplerCache& Graphics::GetSamplerCache() + { + return *m_samplerCache; + } + inline const std::shared_ptr& Graphics::GetViewerDataUBO() { return m_viewerDataUBO; diff --git a/include/Nazara/Graphics/Material.hpp b/include/Nazara/Graphics/Material.hpp index 13569061c..3e2d24ce1 100644 --- a/include/Nazara/Graphics/Material.hpp +++ b/include/Nazara/Graphics/Material.hpp @@ -66,7 +66,7 @@ namespace Nz inline const std::shared_ptr& GetShader(ShaderStageType shaderStage) const; inline BlendFunc GetSrcBlend() const; inline const std::shared_ptr& GetTexture(std::size_t textureIndex) const; - inline const std::shared_ptr& GetTextureSampler(std::size_t textureIndex) const; + inline const TextureSamplerInfo& GetTextureSampler(std::size_t textureIndex) const; inline const std::shared_ptr& GetUniformBuffer(std::size_t bufferIndex) const; inline std::vector& GetUniformBufferData(std::size_t bufferIndex); inline const std::vector& GetUniformBufferConstData(std::size_t bufferIndex); @@ -96,7 +96,7 @@ namespace Nz inline void SetUniformBuffer(std::size_t bufferIndex, std::shared_ptr uniformBuffer); inline void SetSrcBlend(BlendFunc func); inline void SetTexture(std::size_t textureIndex, std::shared_ptr texture); - inline void SetTextureSampler(std::size_t textureIndex, std::shared_ptr sampler); + inline void SetTextureSampler(std::size_t textureIndex, TextureSamplerInfo samplerInfo); void UpdateShaderBinding(ShaderBinding& shaderBinding) const; @@ -106,12 +106,14 @@ namespace Nz private: inline void InvalidatePipeline(); inline void InvalidateShaderBinding(); + inline void InvalidateTextureSampler(std::size_t textureIndex); inline void UpdatePipeline() const; struct MaterialTexture { - std::shared_ptr sampler; + mutable std::shared_ptr sampler; std::shared_ptr texture; + TextureSamplerInfo samplerInfo; }; struct UniformBuffer diff --git a/include/Nazara/Graphics/Material.inl b/include/Nazara/Graphics/Material.inl index 4d16ec19e..ddf82a7ce 100644 --- a/include/Nazara/Graphics/Material.inl +++ b/include/Nazara/Graphics/Material.inl @@ -436,10 +436,10 @@ namespace Nz return m_textures[textureIndex].texture; } - inline const std::shared_ptr& Material::GetTextureSampler(std::size_t textureIndex) const + inline const TextureSamplerInfo& Material::GetTextureSampler(std::size_t textureIndex) const { NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index"); - return m_textures[textureIndex].sampler; + return m_textures[textureIndex].samplerInfo; } inline const std::shared_ptr& Material::GetUniformBuffer(std::size_t bufferIndex) const @@ -695,13 +695,13 @@ namespace Nz } } - inline void Material::SetTextureSampler(std::size_t textureIndex, std::shared_ptr sampler) + inline void Material::SetTextureSampler(std::size_t textureIndex, TextureSamplerInfo samplerInfo) { NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index"); - if (m_textures[textureIndex].sampler != sampler) + if (m_textures[textureIndex].samplerInfo != samplerInfo) { - m_textures[textureIndex].sampler = std::move(sampler); - InvalidateShaderBinding(); + m_textures[textureIndex].samplerInfo = std::move(samplerInfo); + InvalidateTextureSampler(textureIndex); } } @@ -731,6 +731,14 @@ namespace Nz //TODO } + inline void Material::InvalidateTextureSampler(std::size_t textureIndex) + { + assert(textureIndex < m_textures.size()); + m_textures[textureIndex].sampler.reset(); + + InvalidateShaderBinding(); + } + inline void Material::UpdatePipeline() const { for (auto& shader : m_pipelineInfo.shaders) diff --git a/include/Nazara/Graphics/TextureSamplerCache.hpp b/include/Nazara/Graphics/TextureSamplerCache.hpp new file mode 100644 index 000000000..71a7e4c5d --- /dev/null +++ b/include/Nazara/Graphics/TextureSamplerCache.hpp @@ -0,0 +1,40 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_TEXTURESAMPLERCACHE_HPP +#define NAZARA_TEXTURESAMPLERCACHE_HPP + +#include +#include +#include +#include + +namespace Nz +{ + class RenderDevice; + + class NAZARA_GRAPHICS_API TextureSamplerCache + { + public: + inline TextureSamplerCache(std::shared_ptr device); + TextureSamplerCache(const TextureSamplerCache&) = delete; + TextureSamplerCache(TextureSamplerCache&&) = delete; + ~TextureSamplerCache() = default; + + const std::shared_ptr& Get(const TextureSamplerInfo& info); + + TextureSamplerCache& operator=(const TextureSamplerCache&) = delete; + TextureSamplerCache& operator=(TextureSamplerCache&&) = delete; + + private: + std::shared_ptr m_device; + std::unordered_map> m_samplers; + }; +} + +#include + +#endif diff --git a/include/Nazara/Graphics/TextureSamplerCache.inl b/include/Nazara/Graphics/TextureSamplerCache.inl new file mode 100644 index 000000000..e72e3c4cd --- /dev/null +++ b/include/Nazara/Graphics/TextureSamplerCache.inl @@ -0,0 +1,17 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +namespace Nz +{ + inline TextureSamplerCache::TextureSamplerCache(std::shared_ptr device) : + m_device(std::move(device)) + { + } +} + +#include diff --git a/include/Nazara/Renderer/TextureSampler.hpp b/include/Nazara/Renderer/TextureSampler.hpp index e050298c3..2b7977101 100644 --- a/include/Nazara/Renderer/TextureSampler.hpp +++ b/include/Nazara/Renderer/TextureSampler.hpp @@ -22,6 +22,9 @@ namespace Nz SamplerWrap wrapModeU = SamplerWrap_Clamp; SamplerWrap wrapModeV = SamplerWrap_Clamp; SamplerWrap wrapModeW = SamplerWrap_Clamp; + + inline bool operator==(const TextureSamplerInfo& samplerInfo) const; + inline bool operator!=(const TextureSamplerInfo& samplerInfo) const; }; class NAZARA_RENDERER_API TextureSampler @@ -37,6 +40,9 @@ namespace Nz }; } +template<> +struct std::hash; + #include #endif // NAZARA_TEXTURE_HPP diff --git a/include/Nazara/Renderer/TextureSampler.inl b/include/Nazara/Renderer/TextureSampler.inl index a741958f0..a7f802bcb 100644 --- a/include/Nazara/Renderer/TextureSampler.inl +++ b/include/Nazara/Renderer/TextureSampler.inl @@ -3,10 +3,60 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include +#include #include namespace Nz { + inline bool TextureSamplerInfo::operator==(const TextureSamplerInfo& samplerInfo) const + { + if (!NumberEquals(anisotropyLevel, samplerInfo.anisotropyLevel, 0.99f)) + return false; + + if (magFilter != samplerInfo.magFilter) + return false; + + if (minFilter != samplerInfo.minFilter) + return false; + + if (mipmapMode != samplerInfo.mipmapMode) + return false; + + if (wrapModeU != samplerInfo.wrapModeU) + return false; + + if (wrapModeV != samplerInfo.wrapModeV) + return false; + + if (wrapModeW != samplerInfo.wrapModeW) + return false; + + return true; + } + + inline bool TextureSamplerInfo::operator!=(const TextureSamplerInfo& samplerInfo) const + { + return !operator==(samplerInfo); + } } +template<> +struct std::hash +{ + std::size_t operator()(const Nz::TextureSamplerInfo& sampler) const + { + std::size_t seed = 0; + Nz::HashCombine(seed, sampler.anisotropyLevel); + Nz::HashCombine(seed, sampler.magFilter); + Nz::HashCombine(seed, sampler.minFilter); + Nz::HashCombine(seed, sampler.mipmapMode); + Nz::HashCombine(seed, sampler.wrapModeU); + Nz::HashCombine(seed, sampler.wrapModeV); + Nz::HashCombine(seed, sampler.wrapModeW); + + return seed; + } +}; + #include diff --git a/src/Nazara/Graphics/Graphics.cpp b/src/Nazara/Graphics/Graphics.cpp index aa2deb383..ebbd447d7 100644 --- a/src/Nazara/Graphics/Graphics.cpp +++ b/src/Nazara/Graphics/Graphics.cpp @@ -39,6 +39,8 @@ namespace Nz if (!m_renderDevice) throw std::runtime_error("failed to instantiate render device"); + m_samplerCache.emplace(m_renderDevice); + MaterialPipeline::Initialize(); Nz::PredefinedViewerData viewerUboOffsets = Nz::PredefinedViewerData::GetOffsets(); diff --git a/src/Nazara/Graphics/Material.cpp b/src/Nazara/Graphics/Material.cpp index 4f12980b7..77ed2dd3c 100644 --- a/src/Nazara/Graphics/Material.cpp +++ b/src/Nazara/Graphics/Material.cpp @@ -63,7 +63,14 @@ namespace Nz for (const auto& textureSlot : m_textures) { - if (textureSlot.texture && textureSlot.sampler) + if (!textureSlot.sampler) + { + TextureSamplerCache& samplerCache = Graphics::Instance()->GetSamplerCache(); + textureSlot.sampler = samplerCache.Get(textureSlot.samplerInfo); + } + + //TODO: Use "missing" texture + if (textureSlot.texture) { bindings.push_back({ bindingIndex, diff --git a/src/Nazara/Graphics/TextureSamplerCache.cpp b/src/Nazara/Graphics/TextureSamplerCache.cpp new file mode 100644 index 000000000..d211a9a36 --- /dev/null +++ b/src/Nazara/Graphics/TextureSamplerCache.cpp @@ -0,0 +1,19 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +namespace Nz +{ + const std::shared_ptr& TextureSamplerCache::Get(const TextureSamplerInfo& info) + { + auto it = m_samplers.find(info); + if (it == m_samplers.end()) + it = m_samplers.emplace(info, m_device->InstantiateTextureSampler(info)).first; + + return it->second; + } +} diff --git a/src/Nazara/VulkanRenderer/VulkanUploadPool.cpp b/src/Nazara/VulkanRenderer/VulkanUploadPool.cpp index 3d0027332..cc8a768c0 100644 --- a/src/Nazara/VulkanRenderer/VulkanUploadPool.cpp +++ b/src/Nazara/VulkanRenderer/VulkanUploadPool.cpp @@ -55,13 +55,13 @@ namespace Nz VkMemoryRequirements requirement = newBlock.buffer.GetMemoryRequirements(); if (!newBlock.blockMemory.Create(m_device, requirement.size, requirement.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) - throw std::runtime_error("Failed to allocate block memory: " + TranslateVulkanError(newBlock.blockMemory.GetLastErrorCode())); + throw std::runtime_error("failed to allocate block memory: " + TranslateVulkanError(newBlock.blockMemory.GetLastErrorCode())); if (!newBlock.buffer.BindBufferMemory(newBlock.blockMemory)) - throw std::runtime_error("Failed to bind buffer memory: " + TranslateVulkanError(newBlock.buffer.GetLastErrorCode())); + throw std::runtime_error("failed to bind buffer memory: " + TranslateVulkanError(newBlock.buffer.GetLastErrorCode())); if (!newBlock.blockMemory.Map()) - throw std::runtime_error("Failed to map buffer memory: " + TranslateVulkanError(newBlock.buffer.GetLastErrorCode())); + throw std::runtime_error("failed to map buffer memory: " + TranslateVulkanError(newBlock.buffer.GetLastErrorCode())); bestBlock.block = &m_blocks.emplace_back(std::move(newBlock)); bestBlock.alignedOffset = 0; From 41c921bcf637cb897f570fbdbeca0b2e25858d95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 27 Jan 2021 18:53:02 +0100 Subject: [PATCH 050/278] Function order --- include/Nazara/Graphics/Material.hpp | 2 +- include/Nazara/Graphics/Material.inl | 42 ++++++++++++++-------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/include/Nazara/Graphics/Material.hpp b/include/Nazara/Graphics/Material.hpp index 3e2d24ce1..7cfb01008 100644 --- a/include/Nazara/Graphics/Material.hpp +++ b/include/Nazara/Graphics/Material.hpp @@ -93,10 +93,10 @@ namespace Nz inline void SetFaceFilling(FaceFilling filling); inline void SetLineWidth(float lineWidth); inline void SetPointSize(float pointSize); - inline void SetUniformBuffer(std::size_t bufferIndex, std::shared_ptr uniformBuffer); inline void SetSrcBlend(BlendFunc func); inline void SetTexture(std::size_t textureIndex, std::shared_ptr texture); inline void SetTextureSampler(std::size_t textureIndex, TextureSamplerInfo samplerInfo); + inline void SetUniformBuffer(std::size_t bufferIndex, std::shared_ptr uniformBuffer); void UpdateShaderBinding(ShaderBinding& shaderBinding) const; diff --git a/include/Nazara/Graphics/Material.inl b/include/Nazara/Graphics/Material.inl index ddf82a7ce..3f7f2d85a 100644 --- a/include/Nazara/Graphics/Material.inl +++ b/include/Nazara/Graphics/Material.inl @@ -674,15 +674,20 @@ namespace Nz InvalidatePipeline(); } - inline void Material::SetUniformBuffer(std::size_t bufferIndex, std::shared_ptr uniformBuffer) + /*! + * \brief Sets the src in blend + * + * \param func Function for src blending + * + * \remark Invalidates the pipeline + * + * \see GetSrcBlend + */ + inline void Material::SetSrcBlend(BlendFunc func) { - NazaraAssert(bufferIndex < m_uniformBuffers.size(), "Invalid shared uniform buffer index"); - if (m_uniformBuffers[bufferIndex].buffer != uniformBuffer) - { - m_uniformBuffers[bufferIndex].buffer = std::move(uniformBuffer); - m_uniformBuffers[bufferIndex].dataInvalidated = true; - InvalidateShaderBinding(); - } + m_pipelineInfo.srcBlend = func; + + InvalidatePipeline(); } inline void Material::SetTexture(std::size_t textureIndex, std::shared_ptr texture) @@ -705,20 +710,15 @@ namespace Nz } } - /*! - * \brief Sets the src in blend - * - * \param func Function for src blending - * - * \remark Invalidates the pipeline - * - * \see GetSrcBlend - */ - inline void Material::SetSrcBlend(BlendFunc func) + inline void Material::SetUniformBuffer(std::size_t bufferIndex, std::shared_ptr uniformBuffer) { - m_pipelineInfo.srcBlend = func; - - InvalidatePipeline(); + NazaraAssert(bufferIndex < m_uniformBuffers.size(), "Invalid shared uniform buffer index"); + if (m_uniformBuffers[bufferIndex].buffer != uniformBuffer) + { + m_uniformBuffers[bufferIndex].buffer = std::move(uniformBuffer); + m_uniformBuffers[bufferIndex].dataInvalidated = true; + InvalidateShaderBinding(); + } } inline void Material::InvalidatePipeline() From 5eedd3c0bc630e6873e2f87db1c1539b1537abe8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 28 Jan 2021 15:59:18 +0100 Subject: [PATCH 051/278] Renderers: Fix UploadPool --- include/Nazara/VulkanRenderer/VulkanUploadPool.hpp | 2 +- src/Nazara/OpenGLRenderer/OpenGLUploadPool.cpp | 2 ++ src/Nazara/VulkanRenderer/VulkanUploadPool.cpp | 4 +++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/include/Nazara/VulkanRenderer/VulkanUploadPool.hpp b/include/Nazara/VulkanRenderer/VulkanUploadPool.hpp index fc8c9daf5..ede6eb297 100644 --- a/include/Nazara/VulkanRenderer/VulkanUploadPool.hpp +++ b/include/Nazara/VulkanRenderer/VulkanUploadPool.hpp @@ -44,7 +44,7 @@ namespace Nz { Vk::DeviceMemory blockMemory; Vk::Buffer buffer; - UInt64 freeOffset; + UInt64 freeOffset = 0; }; UInt64 m_blockSize; diff --git a/src/Nazara/OpenGLRenderer/OpenGLUploadPool.cpp b/src/Nazara/OpenGLRenderer/OpenGLUploadPool.cpp index 54901ee8d..6387f4ca5 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLUploadPool.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLUploadPool.cpp @@ -52,6 +52,8 @@ namespace Nz allocationData.mappedPtr = static_cast(bestBlock.block->memory.data()) + bestBlock.offset; allocationData.size = size; + bestBlock.block->freeOffset += size; + return allocationData; } diff --git a/src/Nazara/VulkanRenderer/VulkanUploadPool.cpp b/src/Nazara/VulkanRenderer/VulkanUploadPool.cpp index cc8a768c0..3949104f4 100644 --- a/src/Nazara/VulkanRenderer/VulkanUploadPool.cpp +++ b/src/Nazara/VulkanRenderer/VulkanUploadPool.cpp @@ -50,7 +50,7 @@ namespace Nz { Block newBlock; if (!newBlock.buffer.Create(m_device, 0U, m_blockSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT)) - throw std::runtime_error("Failed to create block buffer: " + TranslateVulkanError(newBlock.buffer.GetLastErrorCode())); + throw std::runtime_error("failed to create block buffer: " + TranslateVulkanError(newBlock.buffer.GetLastErrorCode())); VkMemoryRequirements requirement = newBlock.buffer.GetMemoryRequirements(); @@ -74,6 +74,8 @@ namespace Nz allocationData.offset = bestBlock.alignedOffset; allocationData.size = size; + bestBlock.block->freeOffset += size; + return allocationData; } From 3d84479d0eafeb283afdafdab07adc5c3bf75e0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Mon, 15 Feb 2021 14:48:16 +0100 Subject: [PATCH 052/278] Update vulkan headers --- thirdparty/include/vulkan/vk_icd.h | 57 +- thirdparty/include/vulkan/vk_layer.h | 16 +- thirdparty/include/vulkan/vk_platform.h | 18 +- thirdparty/include/vulkan/vulkan.h | 25 +- thirdparty/include/vulkan/vulkan_android.h | 14 +- thirdparty/include/vulkan/vulkan_beta.h | 56 + thirdparty/include/vulkan/vulkan_core.h | 3950 +++++++++++------ thirdparty/include/vulkan/vulkan_directfb.h | 54 + thirdparty/include/vulkan/vulkan_fuchsia.h | 14 +- thirdparty/include/vulkan/vulkan_ggp.h | 14 +- thirdparty/include/vulkan/vulkan_ios.h | 16 +- thirdparty/include/vulkan/vulkan_macos.h | 16 +- thirdparty/include/vulkan/vulkan_metal.h | 14 +- thirdparty/include/vulkan/vulkan_vi.h | 14 +- thirdparty/include/vulkan/vulkan_wayland.h | 14 +- thirdparty/include/vulkan/vulkan_win32.h | 17 +- thirdparty/include/vulkan/vulkan_xcb.h | 14 +- thirdparty/include/vulkan/vulkan_xlib.h | 14 +- .../include/vulkan/vulkan_xlib_xrandr.h | 14 +- 19 files changed, 2924 insertions(+), 1427 deletions(-) create mode 100644 thirdparty/include/vulkan/vulkan_beta.h create mode 100644 thirdparty/include/vulkan/vulkan_directfb.h diff --git a/thirdparty/include/vulkan/vk_icd.h b/thirdparty/include/vulkan/vk_icd.h index 5dff59a16..5e29ef557 100644 --- a/thirdparty/include/vulkan/vk_icd.h +++ b/thirdparty/include/vulkan/vk_icd.h @@ -41,17 +41,45 @@ // that if the loader is older, it should automatically fail a // call for any API version > 1.0. Otherwise, the loader will // manually determine if it can support the expected version. -#define CURRENT_LOADER_ICD_INTERFACE_VERSION 5 +// Version 6 - Add support for vk_icdEnumerateAdapterPhysicalDevices. +#define CURRENT_LOADER_ICD_INTERFACE_VERSION 6 #define MIN_SUPPORTED_LOADER_ICD_INTERFACE_VERSION 0 #define MIN_PHYS_DEV_EXTENSION_ICD_INTERFACE_VERSION 4 -typedef VkResult(VKAPI_PTR *PFN_vkNegotiateLoaderICDInterfaceVersion)(uint32_t *pVersion); +// Old typedefs that don't follow a proper naming convention but are preserved for compatibility +typedef VkResult(VKAPI_PTR *PFN_vkNegotiateLoaderICDInterfaceVersion)(uint32_t *pVersion); // This is defined in vk_layer.h which will be found by the loader, but if an ICD is building against this // file directly, it won't be found. #ifndef PFN_GetPhysicalDeviceProcAddr typedef PFN_vkVoidFunction(VKAPI_PTR *PFN_GetPhysicalDeviceProcAddr)(VkInstance instance, const char *pName); #endif +// Typedefs for loader/ICD interface +typedef VkResult (VKAPI_PTR *PFN_vk_icdNegotiateLoaderICDInterfaceVersion)(uint32_t* pVersion); +typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_vk_icdGetInstanceProcAddr)(VkInstance instance, const char* pName); +typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_vk_icdGetPhysicalDeviceProcAddr)(VkInstance instance, const char* pName); +#if defined(VK_USE_PLATFORM_WIN32_KHR) +typedef VkResult (VKAPI_PTR *PFN_vk_icdEnumerateAdapterPhysicalDevices)(VkInstance instance, LUID adapterLUID, + uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices); +#endif + +// Prototypes for loader/ICD interface +#if !defined(VK_NO_PROTOTYPES) +#ifdef __cplusplus +extern "C" { +#endif + VKAPI_ATTR VkResult VKAPI_CALL vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pVersion); + VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr(VkInstance instance, const char* pName); + VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetPhysicalDeviceProcAddr(VkInstance isntance, const char* pName); +#if defined(VK_USE_PLATFORM_WIN32_KHR) + VKAPI_ATTR VkResult VKAPI_CALL vk_icdEnumerateAdapterPhysicalDevices(VkInstance instance, LUID adapterLUID, + uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices); +#endif +#ifdef __cplusplus +} +#endif +#endif + /* * The ICD must reserve space for a pointer for the loader's dispatch * table, at the start of . @@ -91,6 +119,9 @@ typedef enum { VK_ICD_WSI_PLATFORM_DISPLAY, VK_ICD_WSI_PLATFORM_HEADLESS, VK_ICD_WSI_PLATFORM_METAL, + VK_ICD_WSI_PLATFORM_DIRECTFB, + VK_ICD_WSI_PLATFORM_VI, + VK_ICD_WSI_PLATFORM_GGP, } VkIcdWsiPlatform; typedef struct { @@ -137,6 +168,14 @@ typedef struct { } VkIcdSurfaceXlib; #endif // VK_USE_PLATFORM_XLIB_KHR +#ifdef VK_USE_PLATFORM_DIRECTFB_EXT +typedef struct { + VkIcdSurfaceBase base; + IDirectFB *dfb; + IDirectFBSurface *surface; +} VkIcdSurfaceDirectFB; +#endif // VK_USE_PLATFORM_DIRECTFB_EXT + #ifdef VK_USE_PLATFORM_ANDROID_KHR typedef struct { VkIcdSurfaceBase base; @@ -158,6 +197,13 @@ typedef struct { } VkIcdSurfaceIOS; #endif // VK_USE_PLATFORM_IOS_MVK +#ifdef VK_USE_PLATFORM_GGP +typedef struct { + VkIcdSurfaceBase base; + GgpStreamDescriptor streamDescriptor; +} VkIcdSurfaceGgp; +#endif // VK_USE_PLATFORM_GGP + typedef struct { VkIcdSurfaceBase base; VkDisplayModeKHR displayMode; @@ -180,4 +226,11 @@ typedef struct { } VkIcdSurfaceMetal; #endif // VK_USE_PLATFORM_METAL_EXT +#ifdef VK_USE_PLATFORM_VI_NN +typedef struct { + VkIcdSurfaceBase base; + void *window; +} VkIcdSurfaceVi; +#endif // VK_USE_PLATFORM_VI_NN + #endif // VKICD_H diff --git a/thirdparty/include/vulkan/vk_layer.h b/thirdparty/include/vulkan/vk_layer.h index fa7652008..0651870c7 100644 --- a/thirdparty/include/vulkan/vk_layer.h +++ b/thirdparty/include/vulkan/vk_layer.h @@ -83,7 +83,8 @@ typedef VkResult(VKAPI_PTR *PFN_PhysDevExt)(VkPhysicalDevice phys_device); typedef enum VkLayerFunction_ { VK_LAYER_LINK_INFO = 0, VK_LOADER_DATA_CALLBACK = 1, - VK_LOADER_LAYER_CREATE_DEVICE_CALLBACK = 2 + VK_LOADER_LAYER_CREATE_DEVICE_CALLBACK = 2, + VK_LOADER_FEATURES = 3, } VkLayerFunction; typedef struct VkLayerInstanceLink_ { @@ -111,6 +112,12 @@ typedef VkResult (VKAPI_PTR *PFN_vkSetDeviceLoaderData)(VkDevice device, typedef VkResult (VKAPI_PTR *PFN_vkLayerCreateDevice)(VkInstance instance, VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDevice *pDevice, PFN_vkGetInstanceProcAddr layerGIPA, PFN_vkGetDeviceProcAddr *nextGDPA); typedef void (VKAPI_PTR *PFN_vkLayerDestroyDevice)(VkDevice physicalDevice, const VkAllocationCallbacks *pAllocator, PFN_vkDestroyDevice destroyFunction); + +typedef enum VkLoaderFeastureFlagBits { + VK_LOADER_FEATURE_PHYSICAL_DEVICE_SORTING = 0x00000001, +} VkLoaderFlagBits; +typedef VkFlags VkLoaderFeatureFlags; + typedef struct { VkStructureType sType; // VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO const void *pNext; @@ -119,9 +126,10 @@ typedef struct { VkLayerInstanceLink *pLayerInfo; PFN_vkSetInstanceLoaderData pfnSetInstanceLoaderData; struct { - PFN_vkLayerCreateDevice pfnLayerCreateDevice; - PFN_vkLayerDestroyDevice pfnLayerDestroyDevice; - } layerDevice; + PFN_vkLayerCreateDevice pfnLayerCreateDevice; + PFN_vkLayerDestroyDevice pfnLayerDestroyDevice; + } layerDevice; + VkLoaderFeatureFlags loaderFeatures; } u; } VkLayerInstanceCreateInfo; diff --git a/thirdparty/include/vulkan/vk_platform.h b/thirdparty/include/vulkan/vk_platform.h index dbb011285..18b913abc 100644 --- a/thirdparty/include/vulkan/vk_platform.h +++ b/thirdparty/include/vulkan/vk_platform.h @@ -2,19 +2,9 @@ // File: vk_platform.h // /* -** Copyright (c) 2014-2020 The Khronos Group Inc. +** Copyright 2014-2021 The Khronos Group Inc. ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +** SPDX-License-Identifier: Apache-2.0 */ @@ -68,7 +58,9 @@ extern "C" #define VKAPI_PTR #endif -#include +#if !defined(VK_NO_STDDEF_H) + #include +#endif // !defined(VK_NO_STDDEF_H) #if !defined(VK_NO_STDINT_H) #if defined(_MSC_VER) && (_MSC_VER < 1600) diff --git a/thirdparty/include/vulkan/vulkan.h b/thirdparty/include/vulkan/vulkan.h index ee3fd3c6f..7f2a6e61e 100644 --- a/thirdparty/include/vulkan/vulkan.h +++ b/thirdparty/include/vulkan/vulkan.h @@ -2,19 +2,9 @@ #define VULKAN_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +** SPDX-License-Identifier: Apache-2.0 */ #include "vk_platform.h" @@ -71,6 +61,12 @@ #endif +#ifdef VK_USE_PLATFORM_DIRECTFB_EXT +#include +#include "vulkan_directfb.h" +#endif + + #ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT #include #include @@ -83,4 +79,9 @@ #include "vulkan_ggp.h" #endif + +#ifdef VK_ENABLE_BETA_EXTENSIONS +#include "vulkan_beta.h" +#endif + #endif // VULKAN_H_ diff --git a/thirdparty/include/vulkan/vulkan_android.h b/thirdparty/include/vulkan/vulkan_android.h index 4f27750cd..2160e3e7c 100644 --- a/thirdparty/include/vulkan/vulkan_android.h +++ b/thirdparty/include/vulkan/vulkan_android.h @@ -2,19 +2,9 @@ #define VULKAN_ANDROID_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +** SPDX-License-Identifier: Apache-2.0 */ /* diff --git a/thirdparty/include/vulkan/vulkan_beta.h b/thirdparty/include/vulkan/vulkan_beta.h new file mode 100644 index 000000000..bef8ce348 --- /dev/null +++ b/thirdparty/include/vulkan/vulkan_beta.h @@ -0,0 +1,56 @@ +#ifndef VULKAN_BETA_H_ +#define VULKAN_BETA_H_ 1 + +/* +** Copyright 2015-2021 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +#define VK_KHR_portability_subset 1 +#define VK_KHR_PORTABILITY_SUBSET_SPEC_VERSION 1 +#define VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME "VK_KHR_portability_subset" +typedef struct VkPhysicalDevicePortabilitySubsetFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 constantAlphaColorBlendFactors; + VkBool32 events; + VkBool32 imageViewFormatReinterpretation; + VkBool32 imageViewFormatSwizzle; + VkBool32 imageView2DOn3DImage; + VkBool32 multisampleArrayImage; + VkBool32 mutableComparisonSamplers; + VkBool32 pointPolygons; + VkBool32 samplerMipLodBias; + VkBool32 separateStencilMaskRef; + VkBool32 shaderSampleRateInterpolationFunctions; + VkBool32 tessellationIsolines; + VkBool32 tessellationPointMode; + VkBool32 triangleFans; + VkBool32 vertexAttributeAccessBeyondStride; +} VkPhysicalDevicePortabilitySubsetFeaturesKHR; + +typedef struct VkPhysicalDevicePortabilitySubsetPropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t minVertexInputBindingStrideAlignment; +} VkPhysicalDevicePortabilitySubsetPropertiesKHR; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/include/vulkan/vulkan_core.h b/thirdparty/include/vulkan/vulkan_core.h index 09c569ef9..1bbdab8bb 100644 --- a/thirdparty/include/vulkan/vulkan_core.h +++ b/thirdparty/include/vulkan/vulkan_core.h @@ -2,19 +2,9 @@ #define VULKAN_CORE_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +** SPDX-License-Identifier: Apache-2.0 */ /* @@ -31,24 +21,6 @@ extern "C" { #define VK_VERSION_1_0 1 #include "vk_platform.h" -#define VK_MAKE_VERSION(major, minor, patch) \ - (((major) << 22) | ((minor) << 12) | (patch)) - -// DEPRECATED: This define has been removed. Specific version defines (e.g. VK_API_VERSION_1_0), or the VK_MAKE_VERSION macro, should be used instead. -//#define VK_API_VERSION VK_MAKE_VERSION(1, 0, 0) // Patch version should always be set to 0 - -// Vulkan 1.0 version number -#define VK_API_VERSION_1_0 VK_MAKE_VERSION(1, 0, 0)// Patch version should always be set to 0 - -#define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22) -#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff) -#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff) -// Version of this file -#define VK_HEADER_VERSION 133 - - -#define VK_NULL_HANDLE 0 - #define VK_DEFINE_HANDLE(object) typedef struct object##_T* object; @@ -61,10 +33,34 @@ extern "C" { #endif #endif -typedef uint32_t VkFlags; +#define VK_MAKE_VERSION(major, minor, patch) \ + ((((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch))) + +// DEPRECATED: This define has been removed. Specific version defines (e.g. VK_API_VERSION_1_0), or the VK_MAKE_VERSION macro, should be used instead. +//#define VK_API_VERSION VK_MAKE_VERSION(1, 0, 0) // Patch version should always be set to 0 + +// Vulkan 1.0 version number +#define VK_API_VERSION_1_0 VK_MAKE_VERSION(1, 0, 0)// Patch version should always be set to 0 + +// Version of this file +#define VK_HEADER_VERSION 170 + +// Complete version of this file +#define VK_HEADER_VERSION_COMPLETE VK_MAKE_VERSION(1, 2, VK_HEADER_VERSION) + +#define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22) +#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff) +#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff) + +#define VK_NULL_HANDLE 0 + typedef uint32_t VkBool32; +typedef uint64_t VkDeviceAddress; typedef uint64_t VkDeviceSize; +typedef uint32_t VkFlags; typedef uint32_t VkSampleMask; +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBuffer) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImage) VK_DEFINE_HANDLE(VkInstance) VK_DEFINE_HANDLE(VkPhysicalDevice) VK_DEFINE_HANDLE(VkDevice) @@ -73,8 +69,6 @@ VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSemaphore) VK_DEFINE_HANDLE(VkCommandBuffer) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFence) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDeviceMemory) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBuffer) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImage) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkEvent) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkQueryPool) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBufferView) @@ -82,38 +76,30 @@ VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImageView) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkShaderModule) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineCache) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineLayout) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkRenderPass) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipeline) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkRenderPass) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSetLayout) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSampler) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorPool) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSet) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorPool) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFramebuffer) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCommandPool) -#define VK_LOD_CLAMP_NONE 1000.0f -#define VK_REMAINING_MIP_LEVELS (~0U) -#define VK_REMAINING_ARRAY_LAYERS (~0U) -#define VK_WHOLE_SIZE (~0ULL) #define VK_ATTACHMENT_UNUSED (~0U) -#define VK_TRUE 1 #define VK_FALSE 0 +#define VK_LOD_CLAMP_NONE 1000.0f #define VK_QUEUE_FAMILY_IGNORED (~0U) +#define VK_REMAINING_ARRAY_LAYERS (~0U) +#define VK_REMAINING_MIP_LEVELS (~0U) #define VK_SUBPASS_EXTERNAL (~0U) -#define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256 -#define VK_UUID_SIZE 16 +#define VK_TRUE 1 +#define VK_WHOLE_SIZE (~0ULL) #define VK_MAX_MEMORY_TYPES 32 #define VK_MAX_MEMORY_HEAPS 16 +#define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256 +#define VK_UUID_SIZE 16 #define VK_MAX_EXTENSION_NAME_SIZE 256 #define VK_MAX_DESCRIPTION_SIZE 256 -typedef enum VkPipelineCacheHeaderVersion { - VK_PIPELINE_CACHE_HEADER_VERSION_ONE = 1, - VK_PIPELINE_CACHE_HEADER_VERSION_BEGIN_RANGE = VK_PIPELINE_CACHE_HEADER_VERSION_ONE, - VK_PIPELINE_CACHE_HEADER_VERSION_END_RANGE = VK_PIPELINE_CACHE_HEADER_VERSION_ONE, - VK_PIPELINE_CACHE_HEADER_VERSION_RANGE_SIZE = (VK_PIPELINE_CACHE_HEADER_VERSION_ONE - VK_PIPELINE_CACHE_HEADER_VERSION_ONE + 1), - VK_PIPELINE_CACHE_HEADER_VERSION_MAX_ENUM = 0x7FFFFFFF -} VkPipelineCacheHeaderVersion; - typedef enum VkResult { VK_SUCCESS = 0, VK_NOT_READY = 1, @@ -148,14 +134,17 @@ typedef enum VkResult { VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT = -1000158000, VK_ERROR_NOT_PERMITTED_EXT = -1000174001, VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT = -1000255000, + VK_THREAD_IDLE_KHR = 1000268000, + VK_THREAD_DONE_KHR = 1000268001, + VK_OPERATION_DEFERRED_KHR = 1000268002, + VK_OPERATION_NOT_DEFERRED_KHR = 1000268003, + VK_PIPELINE_COMPILE_REQUIRED_EXT = 1000297000, VK_ERROR_OUT_OF_POOL_MEMORY_KHR = VK_ERROR_OUT_OF_POOL_MEMORY, VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR = VK_ERROR_INVALID_EXTERNAL_HANDLE, VK_ERROR_FRAGMENTATION_EXT = VK_ERROR_FRAGMENTATION, VK_ERROR_INVALID_DEVICE_ADDRESS_EXT = VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS, VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS_KHR = VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS, - VK_RESULT_BEGIN_RANGE = VK_ERROR_UNKNOWN, - VK_RESULT_END_RANGE = VK_INCOMPLETE, - VK_RESULT_RANGE_SIZE = (VK_INCOMPLETE - VK_ERROR_UNKNOWN + 1), + VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT = VK_PIPELINE_COMPILE_REQUIRED_EXT, VK_RESULT_MAX_ENUM = 0x7FFFFFFF } VkResult; @@ -352,6 +341,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT = 1000028001, VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT = 1000028002, VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX = 1000030000, + VK_STRUCTURE_TYPE_IMAGE_VIEW_ADDRESS_PROPERTIES_NVX = 1000030001, VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD = 1000041000, VK_STRUCTURE_TYPE_STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP = 1000049000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV = 1000050000, @@ -384,12 +374,6 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT = 1000081001, VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT = 1000081002, VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000, - VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX = 1000086000, - VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX = 1000086001, - VK_STRUCTURE_TYPE_CMD_PROCESS_COMMANDS_INFO_NVX = 1000086002, - VK_STRUCTURE_TYPE_CMD_RESERVE_SPACE_FOR_COMMANDS_INFO_NVX = 1000086003, - VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX = 1000086004, - VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX = 1000086005, VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV = 1000087000, VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT = 1000090000, VK_STRUCTURE_TYPE_DISPLAY_POWER_INFO_EXT = 1000091000, @@ -453,17 +437,39 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT = 1000148001, VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT = 1000148002, VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV = 1000149000, + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR = 1000150007, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR = 1000150000, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR = 1000150002, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR = 1000150003, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR = 1000150004, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR = 1000150005, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR = 1000150006, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_VERSION_INFO_KHR = 1000150009, + VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR = 1000150010, + VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR = 1000150011, + VK_STRUCTURE_TYPE_COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR = 1000150012, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR = 1000150013, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR = 1000150014, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR = 1000150017, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR = 1000150020, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR = 1000347000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR = 1000347001, + VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR = 1000150015, + VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR = 1000150016, + VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_INTERFACE_CREATE_INFO_KHR = 1000150018, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR = 1000348013, VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV = 1000152000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_FEATURES_NV = 1000154000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_PROPERTIES_NV = 1000154001, VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT = 1000158000, - VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT = 1000158001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT = 1000158002, VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT = 1000158003, VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT = 1000158004, VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT = 1000158005, VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160000, VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR = 1000163000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_PROPERTIES_KHR = 1000163001, VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV = 1000164000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV = 1000164001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV = 1000164002, @@ -507,7 +513,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV = 1000206000, VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV = 1000206001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL = 1000209000, - VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO_INTEL = 1000210000, + VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL = 1000210000, VK_STRUCTURE_TYPE_INITIALIZE_PERFORMANCE_API_INFO_INTEL = 1000210001, VK_STRUCTURE_TYPE_PERFORMANCE_MARKER_INFO_INTEL = 1000210002, VK_STRUCTURE_TYPE_PERFORMANCE_STREAM_MARKER_INFO_INTEL = 1000210003, @@ -517,6 +523,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_DISPLAY_NATIVE_HDR_SURFACE_CAPABILITIES_AMD = 1000213000, VK_STRUCTURE_TYPE_SWAPCHAIN_DISPLAY_NATIVE_HDR_CREATE_INFO_AMD = 1000213001, VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA = 1000214000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES_KHR = 1000215000, VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT = 1000217000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT = 1000218000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT = 1000218001, @@ -524,8 +531,14 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES_EXT = 1000225000, VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT = 1000225001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT = 1000225002, + VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR = 1000226000, + VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR = 1000226001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR = 1000226002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR = 1000226003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR = 1000226004, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD = 1000227000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COHERENT_MEMORY_FEATURES_AMD = 1000229000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_ATOMIC_INT64_FEATURES_EXT = 1000234000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT = 1000237000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT = 1000238000, VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT = 1000238001, @@ -550,7 +563,9 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT = 1000259000, VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT = 1000259001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT = 1000259002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT = 1000260000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT = 1000265000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT = 1000267000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR = 1000269000, VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR = 1000269001, VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR = 1000269002, @@ -558,8 +573,67 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR = 1000269004, VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR = 1000269005, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT = 1000276000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_NV = 1000277000, + VK_STRUCTURE_TYPE_GRAPHICS_SHADER_GROUP_CREATE_INFO_NV = 1000277001, + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_SHADER_GROUPS_CREATE_INFO_NV = 1000277002, + VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_TOKEN_NV = 1000277003, + VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NV = 1000277004, + VK_STRUCTURE_TYPE_GENERATED_COMMANDS_INFO_NV = 1000277005, + VK_STRUCTURE_TYPE_GENERATED_COMMANDS_MEMORY_REQUIREMENTS_INFO_NV = 1000277006, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_NV = 1000277007, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT = 1000281000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT = 1000281001, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDER_PASS_TRANSFORM_INFO_QCOM = 1000282000, + VK_STRUCTURE_TYPE_RENDER_PASS_TRANSFORM_BEGIN_INFO_QCOM = 1000282001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT = 1000284000, + VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT = 1000284001, + VK_STRUCTURE_TYPE_DEVICE_MEMORY_REPORT_CALLBACK_DATA_EXT = 1000284002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT = 1000286000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT = 1000286001, + VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT = 1000287000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT = 1000287001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT = 1000287002, + VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR = 1000290000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT = 1000295000, + VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO_EXT = 1000295001, + VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO_EXT = 1000295002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES_EXT = 1000297000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV = 1000300000, + VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV = 1000300001, + VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR = 1000314000, + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2_KHR = 1000314001, + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2_KHR = 1000314002, + VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR = 1000314003, + VK_STRUCTURE_TYPE_SUBMIT_INFO_2_KHR = 1000314004, + VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO_KHR = 1000314005, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO_KHR = 1000314006, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR = 1000314007, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_2_NV = 1000314008, + VK_STRUCTURE_TYPE_CHECKPOINT_DATA_2_NV = 1000314009, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES_KHR = 1000325000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_PROPERTIES_NV = 1000326000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_FEATURES_NV = 1000326001, + VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_ENUM_STATE_CREATE_INFO_NV = 1000326002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_FEATURES_EXT = 1000332000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_PROPERTIES_EXT = 1000332001, + VK_STRUCTURE_TYPE_COPY_COMMAND_TRANSFORM_INFO_QCOM = 1000333000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES_EXT = 1000335000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_FEATURES_KHR = 1000336000, + VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2_KHR = 1000337000, + VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2_KHR = 1000337001, + VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2_KHR = 1000337002, + VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2_KHR = 1000337003, + VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2_KHR = 1000337004, + VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2_KHR = 1000337005, + VK_STRUCTURE_TYPE_BUFFER_COPY_2_KHR = 1000337006, + VK_STRUCTURE_TYPE_IMAGE_COPY_2_KHR = 1000337007, + VK_STRUCTURE_TYPE_IMAGE_BLIT_2_KHR = 1000337008, + VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2_KHR = 1000337009, + VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2_KHR = 1000337010, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT = 1000340000, + VK_STRUCTURE_TYPE_DIRECTFB_SURFACE_CREATE_INFO_EXT = 1000346000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_VALVE = 1000351000, + VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_VALVE = 1000351002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES, VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT, @@ -618,8 +692,8 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO, VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO, VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES_KHR, VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES, @@ -658,6 +732,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO_KHR = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO_KHR = VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO, + VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO_INTEL = VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES, @@ -673,29 +748,114 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO_KHR = VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO, VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES, - VK_STRUCTURE_TYPE_BEGIN_RANGE = VK_STRUCTURE_TYPE_APPLICATION_INFO, - VK_STRUCTURE_TYPE_END_RANGE = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO, - VK_STRUCTURE_TYPE_RANGE_SIZE = (VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO - VK_STRUCTURE_TYPE_APPLICATION_INFO + 1), VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF } VkStructureType; +typedef enum VkImageLayout { + VK_IMAGE_LAYOUT_UNDEFINED = 0, + VK_IMAGE_LAYOUT_GENERAL = 1, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL = 2, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL = 3, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL = 4, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL = 5, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL = 6, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL = 7, + VK_IMAGE_LAYOUT_PREINITIALIZED = 8, + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL = 1000117000, + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL = 1000117001, + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL = 1000241000, + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL = 1000241001, + VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL = 1000241002, + VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL = 1000241003, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002, + VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR = 1000111000, + VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV = 1000164003, + VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT = 1000218000, + VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR = 1000314000, + VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR = 1000314001, + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV, + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_MAX_ENUM = 0x7FFFFFFF +} VkImageLayout; + +typedef enum VkObjectType { + VK_OBJECT_TYPE_UNKNOWN = 0, + VK_OBJECT_TYPE_INSTANCE = 1, + VK_OBJECT_TYPE_PHYSICAL_DEVICE = 2, + VK_OBJECT_TYPE_DEVICE = 3, + VK_OBJECT_TYPE_QUEUE = 4, + VK_OBJECT_TYPE_SEMAPHORE = 5, + VK_OBJECT_TYPE_COMMAND_BUFFER = 6, + VK_OBJECT_TYPE_FENCE = 7, + VK_OBJECT_TYPE_DEVICE_MEMORY = 8, + VK_OBJECT_TYPE_BUFFER = 9, + VK_OBJECT_TYPE_IMAGE = 10, + VK_OBJECT_TYPE_EVENT = 11, + VK_OBJECT_TYPE_QUERY_POOL = 12, + VK_OBJECT_TYPE_BUFFER_VIEW = 13, + VK_OBJECT_TYPE_IMAGE_VIEW = 14, + VK_OBJECT_TYPE_SHADER_MODULE = 15, + VK_OBJECT_TYPE_PIPELINE_CACHE = 16, + VK_OBJECT_TYPE_PIPELINE_LAYOUT = 17, + VK_OBJECT_TYPE_RENDER_PASS = 18, + VK_OBJECT_TYPE_PIPELINE = 19, + VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT = 20, + VK_OBJECT_TYPE_SAMPLER = 21, + VK_OBJECT_TYPE_DESCRIPTOR_POOL = 22, + VK_OBJECT_TYPE_DESCRIPTOR_SET = 23, + VK_OBJECT_TYPE_FRAMEBUFFER = 24, + VK_OBJECT_TYPE_COMMAND_POOL = 25, + VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION = 1000156000, + VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE = 1000085000, + VK_OBJECT_TYPE_SURFACE_KHR = 1000000000, + VK_OBJECT_TYPE_SWAPCHAIN_KHR = 1000001000, + VK_OBJECT_TYPE_DISPLAY_KHR = 1000002000, + VK_OBJECT_TYPE_DISPLAY_MODE_KHR = 1000002001, + VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT = 1000011000, + VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT = 1000128000, + VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR = 1000150000, + VK_OBJECT_TYPE_VALIDATION_CACHE_EXT = 1000160000, + VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000, + VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL = 1000210000, + VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR = 1000268000, + VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NV = 1000277000, + VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT = 1000295000, + VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR = VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE, + VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR = VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION, + VK_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkObjectType; + +typedef enum VkVendorId { + VK_VENDOR_ID_VIV = 0x10001, + VK_VENDOR_ID_VSI = 0x10002, + VK_VENDOR_ID_KAZAN = 0x10003, + VK_VENDOR_ID_CODEPLAY = 0x10004, + VK_VENDOR_ID_MESA = 0x10005, + VK_VENDOR_ID_POCL = 0x10006, + VK_VENDOR_ID_MAX_ENUM = 0x7FFFFFFF +} VkVendorId; + +typedef enum VkPipelineCacheHeaderVersion { + VK_PIPELINE_CACHE_HEADER_VERSION_ONE = 1, + VK_PIPELINE_CACHE_HEADER_VERSION_MAX_ENUM = 0x7FFFFFFF +} VkPipelineCacheHeaderVersion; + typedef enum VkSystemAllocationScope { VK_SYSTEM_ALLOCATION_SCOPE_COMMAND = 0, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT = 1, VK_SYSTEM_ALLOCATION_SCOPE_CACHE = 2, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE = 3, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE = 4, - VK_SYSTEM_ALLOCATION_SCOPE_BEGIN_RANGE = VK_SYSTEM_ALLOCATION_SCOPE_COMMAND, - VK_SYSTEM_ALLOCATION_SCOPE_END_RANGE = VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE, - VK_SYSTEM_ALLOCATION_SCOPE_RANGE_SIZE = (VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE - VK_SYSTEM_ALLOCATION_SCOPE_COMMAND + 1), VK_SYSTEM_ALLOCATION_SCOPE_MAX_ENUM = 0x7FFFFFFF } VkSystemAllocationScope; typedef enum VkInternalAllocationType { VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE = 0, - VK_INTERNAL_ALLOCATION_TYPE_BEGIN_RANGE = VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE, - VK_INTERNAL_ALLOCATION_TYPE_END_RANGE = VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE, - VK_INTERNAL_ALLOCATION_TYPE_RANGE_SIZE = (VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE - VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE + 1), VK_INTERNAL_ALLOCATION_TYPE_MAX_ENUM = 0x7FFFFFFF } VkInternalAllocationType; @@ -941,6 +1101,8 @@ typedef enum VkFormat { VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT = 1000066011, VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT = 1000066012, VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT = 1000066013, + VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT = 1000340000, + VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT = 1000340001, VK_FORMAT_G8B8G8R8_422_UNORM_KHR = VK_FORMAT_G8B8G8R8_422_UNORM, VK_FORMAT_B8G8R8G8_422_UNORM_KHR = VK_FORMAT_B8G8R8G8_422_UNORM, VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, @@ -975,41 +1137,29 @@ typedef enum VkFormat { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM_KHR = VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, VK_FORMAT_G16_B16R16_2PLANE_422_UNORM_KHR = VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM_KHR = VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, - VK_FORMAT_BEGIN_RANGE = VK_FORMAT_UNDEFINED, - VK_FORMAT_END_RANGE = VK_FORMAT_ASTC_12x12_SRGB_BLOCK, - VK_FORMAT_RANGE_SIZE = (VK_FORMAT_ASTC_12x12_SRGB_BLOCK - VK_FORMAT_UNDEFINED + 1), VK_FORMAT_MAX_ENUM = 0x7FFFFFFF } VkFormat; -typedef enum VkImageType { - VK_IMAGE_TYPE_1D = 0, - VK_IMAGE_TYPE_2D = 1, - VK_IMAGE_TYPE_3D = 2, - VK_IMAGE_TYPE_BEGIN_RANGE = VK_IMAGE_TYPE_1D, - VK_IMAGE_TYPE_END_RANGE = VK_IMAGE_TYPE_3D, - VK_IMAGE_TYPE_RANGE_SIZE = (VK_IMAGE_TYPE_3D - VK_IMAGE_TYPE_1D + 1), - VK_IMAGE_TYPE_MAX_ENUM = 0x7FFFFFFF -} VkImageType; - typedef enum VkImageTiling { VK_IMAGE_TILING_OPTIMAL = 0, VK_IMAGE_TILING_LINEAR = 1, VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT = 1000158000, - VK_IMAGE_TILING_BEGIN_RANGE = VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_TILING_END_RANGE = VK_IMAGE_TILING_LINEAR, - VK_IMAGE_TILING_RANGE_SIZE = (VK_IMAGE_TILING_LINEAR - VK_IMAGE_TILING_OPTIMAL + 1), VK_IMAGE_TILING_MAX_ENUM = 0x7FFFFFFF } VkImageTiling; +typedef enum VkImageType { + VK_IMAGE_TYPE_1D = 0, + VK_IMAGE_TYPE_2D = 1, + VK_IMAGE_TYPE_3D = 2, + VK_IMAGE_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkImageType; + typedef enum VkPhysicalDeviceType { VK_PHYSICAL_DEVICE_TYPE_OTHER = 0, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU = 1, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU = 2, VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU = 3, VK_PHYSICAL_DEVICE_TYPE_CPU = 4, - VK_PHYSICAL_DEVICE_TYPE_BEGIN_RANGE = VK_PHYSICAL_DEVICE_TYPE_OTHER, - VK_PHYSICAL_DEVICE_TYPE_END_RANGE = VK_PHYSICAL_DEVICE_TYPE_CPU, - VK_PHYSICAL_DEVICE_TYPE_RANGE_SIZE = (VK_PHYSICAL_DEVICE_TYPE_CPU - VK_PHYSICAL_DEVICE_TYPE_OTHER + 1), VK_PHYSICAL_DEVICE_TYPE_MAX_ENUM = 0x7FFFFFFF } VkPhysicalDeviceType; @@ -1019,69 +1169,19 @@ typedef enum VkQueryType { VK_QUERY_TYPE_TIMESTAMP = 2, VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT = 1000028004, VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR = 1000116000, + VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR = 1000150000, + VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR = 1000150001, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV = 1000165000, VK_QUERY_TYPE_PERFORMANCE_QUERY_INTEL = 1000210000, - VK_QUERY_TYPE_BEGIN_RANGE = VK_QUERY_TYPE_OCCLUSION, - VK_QUERY_TYPE_END_RANGE = VK_QUERY_TYPE_TIMESTAMP, - VK_QUERY_TYPE_RANGE_SIZE = (VK_QUERY_TYPE_TIMESTAMP - VK_QUERY_TYPE_OCCLUSION + 1), VK_QUERY_TYPE_MAX_ENUM = 0x7FFFFFFF } VkQueryType; typedef enum VkSharingMode { VK_SHARING_MODE_EXCLUSIVE = 0, VK_SHARING_MODE_CONCURRENT = 1, - VK_SHARING_MODE_BEGIN_RANGE = VK_SHARING_MODE_EXCLUSIVE, - VK_SHARING_MODE_END_RANGE = VK_SHARING_MODE_CONCURRENT, - VK_SHARING_MODE_RANGE_SIZE = (VK_SHARING_MODE_CONCURRENT - VK_SHARING_MODE_EXCLUSIVE + 1), VK_SHARING_MODE_MAX_ENUM = 0x7FFFFFFF } VkSharingMode; -typedef enum VkImageLayout { - VK_IMAGE_LAYOUT_UNDEFINED = 0, - VK_IMAGE_LAYOUT_GENERAL = 1, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL = 2, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL = 3, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL = 4, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL = 5, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL = 6, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL = 7, - VK_IMAGE_LAYOUT_PREINITIALIZED = 8, - VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL = 1000117000, - VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL = 1000117001, - VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL = 1000241000, - VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL = 1000241001, - VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL = 1000241002, - VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL = 1000241003, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002, - VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR = 1000111000, - VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV = 1000164003, - VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT = 1000218000, - VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, - VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL, - VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL, - VK_IMAGE_LAYOUT_BEGIN_RANGE = VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_END_RANGE = VK_IMAGE_LAYOUT_PREINITIALIZED, - VK_IMAGE_LAYOUT_RANGE_SIZE = (VK_IMAGE_LAYOUT_PREINITIALIZED - VK_IMAGE_LAYOUT_UNDEFINED + 1), - VK_IMAGE_LAYOUT_MAX_ENUM = 0x7FFFFFFF -} VkImageLayout; - -typedef enum VkImageViewType { - VK_IMAGE_VIEW_TYPE_1D = 0, - VK_IMAGE_VIEW_TYPE_2D = 1, - VK_IMAGE_VIEW_TYPE_3D = 2, - VK_IMAGE_VIEW_TYPE_CUBE = 3, - VK_IMAGE_VIEW_TYPE_1D_ARRAY = 4, - VK_IMAGE_VIEW_TYPE_2D_ARRAY = 5, - VK_IMAGE_VIEW_TYPE_CUBE_ARRAY = 6, - VK_IMAGE_VIEW_TYPE_BEGIN_RANGE = VK_IMAGE_VIEW_TYPE_1D, - VK_IMAGE_VIEW_TYPE_END_RANGE = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, - VK_IMAGE_VIEW_TYPE_RANGE_SIZE = (VK_IMAGE_VIEW_TYPE_CUBE_ARRAY - VK_IMAGE_VIEW_TYPE_1D + 1), - VK_IMAGE_VIEW_TYPE_MAX_ENUM = 0x7FFFFFFF -} VkImageViewType; - typedef enum VkComponentSwizzle { VK_COMPONENT_SWIZZLE_IDENTITY = 0, VK_COMPONENT_SWIZZLE_ZERO = 1, @@ -1090,111 +1190,19 @@ typedef enum VkComponentSwizzle { VK_COMPONENT_SWIZZLE_G = 4, VK_COMPONENT_SWIZZLE_B = 5, VK_COMPONENT_SWIZZLE_A = 6, - VK_COMPONENT_SWIZZLE_BEGIN_RANGE = VK_COMPONENT_SWIZZLE_IDENTITY, - VK_COMPONENT_SWIZZLE_END_RANGE = VK_COMPONENT_SWIZZLE_A, - VK_COMPONENT_SWIZZLE_RANGE_SIZE = (VK_COMPONENT_SWIZZLE_A - VK_COMPONENT_SWIZZLE_IDENTITY + 1), VK_COMPONENT_SWIZZLE_MAX_ENUM = 0x7FFFFFFF } VkComponentSwizzle; -typedef enum VkVertexInputRate { - VK_VERTEX_INPUT_RATE_VERTEX = 0, - VK_VERTEX_INPUT_RATE_INSTANCE = 1, - VK_VERTEX_INPUT_RATE_BEGIN_RANGE = VK_VERTEX_INPUT_RATE_VERTEX, - VK_VERTEX_INPUT_RATE_END_RANGE = VK_VERTEX_INPUT_RATE_INSTANCE, - VK_VERTEX_INPUT_RATE_RANGE_SIZE = (VK_VERTEX_INPUT_RATE_INSTANCE - VK_VERTEX_INPUT_RATE_VERTEX + 1), - VK_VERTEX_INPUT_RATE_MAX_ENUM = 0x7FFFFFFF -} VkVertexInputRate; - -typedef enum VkPrimitiveTopology { - VK_PRIMITIVE_TOPOLOGY_POINT_LIST = 0, - VK_PRIMITIVE_TOPOLOGY_LINE_LIST = 1, - VK_PRIMITIVE_TOPOLOGY_LINE_STRIP = 2, - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST = 3, - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP = 4, - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN = 5, - VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY = 6, - VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY = 7, - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY = 8, - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY = 9, - VK_PRIMITIVE_TOPOLOGY_PATCH_LIST = 10, - VK_PRIMITIVE_TOPOLOGY_BEGIN_RANGE = VK_PRIMITIVE_TOPOLOGY_POINT_LIST, - VK_PRIMITIVE_TOPOLOGY_END_RANGE = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, - VK_PRIMITIVE_TOPOLOGY_RANGE_SIZE = (VK_PRIMITIVE_TOPOLOGY_PATCH_LIST - VK_PRIMITIVE_TOPOLOGY_POINT_LIST + 1), - VK_PRIMITIVE_TOPOLOGY_MAX_ENUM = 0x7FFFFFFF -} VkPrimitiveTopology; - -typedef enum VkPolygonMode { - VK_POLYGON_MODE_FILL = 0, - VK_POLYGON_MODE_LINE = 1, - VK_POLYGON_MODE_POINT = 2, - VK_POLYGON_MODE_FILL_RECTANGLE_NV = 1000153000, - VK_POLYGON_MODE_BEGIN_RANGE = VK_POLYGON_MODE_FILL, - VK_POLYGON_MODE_END_RANGE = VK_POLYGON_MODE_POINT, - VK_POLYGON_MODE_RANGE_SIZE = (VK_POLYGON_MODE_POINT - VK_POLYGON_MODE_FILL + 1), - VK_POLYGON_MODE_MAX_ENUM = 0x7FFFFFFF -} VkPolygonMode; - -typedef enum VkFrontFace { - VK_FRONT_FACE_COUNTER_CLOCKWISE = 0, - VK_FRONT_FACE_CLOCKWISE = 1, - VK_FRONT_FACE_BEGIN_RANGE = VK_FRONT_FACE_COUNTER_CLOCKWISE, - VK_FRONT_FACE_END_RANGE = VK_FRONT_FACE_CLOCKWISE, - VK_FRONT_FACE_RANGE_SIZE = (VK_FRONT_FACE_CLOCKWISE - VK_FRONT_FACE_COUNTER_CLOCKWISE + 1), - VK_FRONT_FACE_MAX_ENUM = 0x7FFFFFFF -} VkFrontFace; - -typedef enum VkCompareOp { - VK_COMPARE_OP_NEVER = 0, - VK_COMPARE_OP_LESS = 1, - VK_COMPARE_OP_EQUAL = 2, - VK_COMPARE_OP_LESS_OR_EQUAL = 3, - VK_COMPARE_OP_GREATER = 4, - VK_COMPARE_OP_NOT_EQUAL = 5, - VK_COMPARE_OP_GREATER_OR_EQUAL = 6, - VK_COMPARE_OP_ALWAYS = 7, - VK_COMPARE_OP_BEGIN_RANGE = VK_COMPARE_OP_NEVER, - VK_COMPARE_OP_END_RANGE = VK_COMPARE_OP_ALWAYS, - VK_COMPARE_OP_RANGE_SIZE = (VK_COMPARE_OP_ALWAYS - VK_COMPARE_OP_NEVER + 1), - VK_COMPARE_OP_MAX_ENUM = 0x7FFFFFFF -} VkCompareOp; - -typedef enum VkStencilOp { - VK_STENCIL_OP_KEEP = 0, - VK_STENCIL_OP_ZERO = 1, - VK_STENCIL_OP_REPLACE = 2, - VK_STENCIL_OP_INCREMENT_AND_CLAMP = 3, - VK_STENCIL_OP_DECREMENT_AND_CLAMP = 4, - VK_STENCIL_OP_INVERT = 5, - VK_STENCIL_OP_INCREMENT_AND_WRAP = 6, - VK_STENCIL_OP_DECREMENT_AND_WRAP = 7, - VK_STENCIL_OP_BEGIN_RANGE = VK_STENCIL_OP_KEEP, - VK_STENCIL_OP_END_RANGE = VK_STENCIL_OP_DECREMENT_AND_WRAP, - VK_STENCIL_OP_RANGE_SIZE = (VK_STENCIL_OP_DECREMENT_AND_WRAP - VK_STENCIL_OP_KEEP + 1), - VK_STENCIL_OP_MAX_ENUM = 0x7FFFFFFF -} VkStencilOp; - -typedef enum VkLogicOp { - VK_LOGIC_OP_CLEAR = 0, - VK_LOGIC_OP_AND = 1, - VK_LOGIC_OP_AND_REVERSE = 2, - VK_LOGIC_OP_COPY = 3, - VK_LOGIC_OP_AND_INVERTED = 4, - VK_LOGIC_OP_NO_OP = 5, - VK_LOGIC_OP_XOR = 6, - VK_LOGIC_OP_OR = 7, - VK_LOGIC_OP_NOR = 8, - VK_LOGIC_OP_EQUIVALENT = 9, - VK_LOGIC_OP_INVERT = 10, - VK_LOGIC_OP_OR_REVERSE = 11, - VK_LOGIC_OP_COPY_INVERTED = 12, - VK_LOGIC_OP_OR_INVERTED = 13, - VK_LOGIC_OP_NAND = 14, - VK_LOGIC_OP_SET = 15, - VK_LOGIC_OP_BEGIN_RANGE = VK_LOGIC_OP_CLEAR, - VK_LOGIC_OP_END_RANGE = VK_LOGIC_OP_SET, - VK_LOGIC_OP_RANGE_SIZE = (VK_LOGIC_OP_SET - VK_LOGIC_OP_CLEAR + 1), - VK_LOGIC_OP_MAX_ENUM = 0x7FFFFFFF -} VkLogicOp; +typedef enum VkImageViewType { + VK_IMAGE_VIEW_TYPE_1D = 0, + VK_IMAGE_VIEW_TYPE_2D = 1, + VK_IMAGE_VIEW_TYPE_3D = 2, + VK_IMAGE_VIEW_TYPE_CUBE = 3, + VK_IMAGE_VIEW_TYPE_1D_ARRAY = 4, + VK_IMAGE_VIEW_TYPE_2D_ARRAY = 5, + VK_IMAGE_VIEW_TYPE_CUBE_ARRAY = 6, + VK_IMAGE_VIEW_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkImageViewType; typedef enum VkBlendFactor { VK_BLEND_FACTOR_ZERO = 0, @@ -1216,9 +1224,6 @@ typedef enum VkBlendFactor { VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR = 16, VK_BLEND_FACTOR_SRC1_ALPHA = 17, VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA = 18, - VK_BLEND_FACTOR_BEGIN_RANGE = VK_BLEND_FACTOR_ZERO, - VK_BLEND_FACTOR_END_RANGE = VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA, - VK_BLEND_FACTOR_RANGE_SIZE = (VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA - VK_BLEND_FACTOR_ZERO + 1), VK_BLEND_FACTOR_MAX_ENUM = 0x7FFFFFFF } VkBlendFactor; @@ -1274,12 +1279,21 @@ typedef enum VkBlendOp { VK_BLEND_OP_RED_EXT = 1000148043, VK_BLEND_OP_GREEN_EXT = 1000148044, VK_BLEND_OP_BLUE_EXT = 1000148045, - VK_BLEND_OP_BEGIN_RANGE = VK_BLEND_OP_ADD, - VK_BLEND_OP_END_RANGE = VK_BLEND_OP_MAX, - VK_BLEND_OP_RANGE_SIZE = (VK_BLEND_OP_MAX - VK_BLEND_OP_ADD + 1), VK_BLEND_OP_MAX_ENUM = 0x7FFFFFFF } VkBlendOp; +typedef enum VkCompareOp { + VK_COMPARE_OP_NEVER = 0, + VK_COMPARE_OP_LESS = 1, + VK_COMPARE_OP_EQUAL = 2, + VK_COMPARE_OP_LESS_OR_EQUAL = 3, + VK_COMPARE_OP_GREATER = 4, + VK_COMPARE_OP_NOT_EQUAL = 5, + VK_COMPARE_OP_GREATER_OR_EQUAL = 6, + VK_COMPARE_OP_ALWAYS = 7, + VK_COMPARE_OP_MAX_ENUM = 0x7FFFFFFF +} VkCompareOp; + typedef enum VkDynamicState { VK_DYNAMIC_STATE_VIEWPORT = 0, VK_DYNAMIC_STATE_SCISSOR = 1, @@ -1293,48 +1307,93 @@ typedef enum VkDynamicState { VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV = 1000087000, VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT = 1000099000, VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT = 1000143000, + VK_DYNAMIC_STATE_RAY_TRACING_PIPELINE_STACK_SIZE_KHR = 1000347000, VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV = 1000164004, VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV = 1000164006, VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV = 1000205001, + VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR = 1000226000, VK_DYNAMIC_STATE_LINE_STIPPLE_EXT = 1000259000, - VK_DYNAMIC_STATE_BEGIN_RANGE = VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_END_RANGE = VK_DYNAMIC_STATE_STENCIL_REFERENCE, - VK_DYNAMIC_STATE_RANGE_SIZE = (VK_DYNAMIC_STATE_STENCIL_REFERENCE - VK_DYNAMIC_STATE_VIEWPORT + 1), + VK_DYNAMIC_STATE_CULL_MODE_EXT = 1000267000, + VK_DYNAMIC_STATE_FRONT_FACE_EXT = 1000267001, + VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT = 1000267002, + VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT = 1000267003, + VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT = 1000267004, + VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT = 1000267005, + VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT = 1000267006, + VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT = 1000267007, + VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT = 1000267008, + VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT = 1000267009, + VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT = 1000267010, + VK_DYNAMIC_STATE_STENCIL_OP_EXT = 1000267011, VK_DYNAMIC_STATE_MAX_ENUM = 0x7FFFFFFF } VkDynamicState; -typedef enum VkFilter { - VK_FILTER_NEAREST = 0, - VK_FILTER_LINEAR = 1, - VK_FILTER_CUBIC_IMG = 1000015000, - VK_FILTER_CUBIC_EXT = VK_FILTER_CUBIC_IMG, - VK_FILTER_BEGIN_RANGE = VK_FILTER_NEAREST, - VK_FILTER_END_RANGE = VK_FILTER_LINEAR, - VK_FILTER_RANGE_SIZE = (VK_FILTER_LINEAR - VK_FILTER_NEAREST + 1), - VK_FILTER_MAX_ENUM = 0x7FFFFFFF -} VkFilter; +typedef enum VkFrontFace { + VK_FRONT_FACE_COUNTER_CLOCKWISE = 0, + VK_FRONT_FACE_CLOCKWISE = 1, + VK_FRONT_FACE_MAX_ENUM = 0x7FFFFFFF +} VkFrontFace; -typedef enum VkSamplerMipmapMode { - VK_SAMPLER_MIPMAP_MODE_NEAREST = 0, - VK_SAMPLER_MIPMAP_MODE_LINEAR = 1, - VK_SAMPLER_MIPMAP_MODE_BEGIN_RANGE = VK_SAMPLER_MIPMAP_MODE_NEAREST, - VK_SAMPLER_MIPMAP_MODE_END_RANGE = VK_SAMPLER_MIPMAP_MODE_LINEAR, - VK_SAMPLER_MIPMAP_MODE_RANGE_SIZE = (VK_SAMPLER_MIPMAP_MODE_LINEAR - VK_SAMPLER_MIPMAP_MODE_NEAREST + 1), - VK_SAMPLER_MIPMAP_MODE_MAX_ENUM = 0x7FFFFFFF -} VkSamplerMipmapMode; +typedef enum VkVertexInputRate { + VK_VERTEX_INPUT_RATE_VERTEX = 0, + VK_VERTEX_INPUT_RATE_INSTANCE = 1, + VK_VERTEX_INPUT_RATE_MAX_ENUM = 0x7FFFFFFF +} VkVertexInputRate; -typedef enum VkSamplerAddressMode { - VK_SAMPLER_ADDRESS_MODE_REPEAT = 0, - VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT = 1, - VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE = 2, - VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER = 3, - VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE = 4, - VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE_KHR = VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, - VK_SAMPLER_ADDRESS_MODE_BEGIN_RANGE = VK_SAMPLER_ADDRESS_MODE_REPEAT, - VK_SAMPLER_ADDRESS_MODE_END_RANGE = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, - VK_SAMPLER_ADDRESS_MODE_RANGE_SIZE = (VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER - VK_SAMPLER_ADDRESS_MODE_REPEAT + 1), - VK_SAMPLER_ADDRESS_MODE_MAX_ENUM = 0x7FFFFFFF -} VkSamplerAddressMode; +typedef enum VkPrimitiveTopology { + VK_PRIMITIVE_TOPOLOGY_POINT_LIST = 0, + VK_PRIMITIVE_TOPOLOGY_LINE_LIST = 1, + VK_PRIMITIVE_TOPOLOGY_LINE_STRIP = 2, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST = 3, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP = 4, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN = 5, + VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY = 6, + VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY = 7, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY = 8, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY = 9, + VK_PRIMITIVE_TOPOLOGY_PATCH_LIST = 10, + VK_PRIMITIVE_TOPOLOGY_MAX_ENUM = 0x7FFFFFFF +} VkPrimitiveTopology; + +typedef enum VkPolygonMode { + VK_POLYGON_MODE_FILL = 0, + VK_POLYGON_MODE_LINE = 1, + VK_POLYGON_MODE_POINT = 2, + VK_POLYGON_MODE_FILL_RECTANGLE_NV = 1000153000, + VK_POLYGON_MODE_MAX_ENUM = 0x7FFFFFFF +} VkPolygonMode; + +typedef enum VkStencilOp { + VK_STENCIL_OP_KEEP = 0, + VK_STENCIL_OP_ZERO = 1, + VK_STENCIL_OP_REPLACE = 2, + VK_STENCIL_OP_INCREMENT_AND_CLAMP = 3, + VK_STENCIL_OP_DECREMENT_AND_CLAMP = 4, + VK_STENCIL_OP_INVERT = 5, + VK_STENCIL_OP_INCREMENT_AND_WRAP = 6, + VK_STENCIL_OP_DECREMENT_AND_WRAP = 7, + VK_STENCIL_OP_MAX_ENUM = 0x7FFFFFFF +} VkStencilOp; + +typedef enum VkLogicOp { + VK_LOGIC_OP_CLEAR = 0, + VK_LOGIC_OP_AND = 1, + VK_LOGIC_OP_AND_REVERSE = 2, + VK_LOGIC_OP_COPY = 3, + VK_LOGIC_OP_AND_INVERTED = 4, + VK_LOGIC_OP_NO_OP = 5, + VK_LOGIC_OP_XOR = 6, + VK_LOGIC_OP_OR = 7, + VK_LOGIC_OP_NOR = 8, + VK_LOGIC_OP_EQUIVALENT = 9, + VK_LOGIC_OP_INVERT = 10, + VK_LOGIC_OP_OR_REVERSE = 11, + VK_LOGIC_OP_COPY_INVERTED = 12, + VK_LOGIC_OP_OR_INVERTED = 13, + VK_LOGIC_OP_NAND = 14, + VK_LOGIC_OP_SET = 15, + VK_LOGIC_OP_MAX_ENUM = 0x7FFFFFFF +} VkLogicOp; typedef enum VkBorderColor { VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK = 0, @@ -1343,12 +1402,35 @@ typedef enum VkBorderColor { VK_BORDER_COLOR_INT_OPAQUE_BLACK = 3, VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE = 4, VK_BORDER_COLOR_INT_OPAQUE_WHITE = 5, - VK_BORDER_COLOR_BEGIN_RANGE = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, - VK_BORDER_COLOR_END_RANGE = VK_BORDER_COLOR_INT_OPAQUE_WHITE, - VK_BORDER_COLOR_RANGE_SIZE = (VK_BORDER_COLOR_INT_OPAQUE_WHITE - VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK + 1), + VK_BORDER_COLOR_FLOAT_CUSTOM_EXT = 1000287003, + VK_BORDER_COLOR_INT_CUSTOM_EXT = 1000287004, VK_BORDER_COLOR_MAX_ENUM = 0x7FFFFFFF } VkBorderColor; +typedef enum VkFilter { + VK_FILTER_NEAREST = 0, + VK_FILTER_LINEAR = 1, + VK_FILTER_CUBIC_IMG = 1000015000, + VK_FILTER_CUBIC_EXT = VK_FILTER_CUBIC_IMG, + VK_FILTER_MAX_ENUM = 0x7FFFFFFF +} VkFilter; + +typedef enum VkSamplerAddressMode { + VK_SAMPLER_ADDRESS_MODE_REPEAT = 0, + VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT = 1, + VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE = 2, + VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER = 3, + VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE = 4, + VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE_KHR = VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, + VK_SAMPLER_ADDRESS_MODE_MAX_ENUM = 0x7FFFFFFF +} VkSamplerAddressMode; + +typedef enum VkSamplerMipmapMode { + VK_SAMPLER_MIPMAP_MODE_NEAREST = 0, + VK_SAMPLER_MIPMAP_MODE_LINEAR = 1, + VK_SAMPLER_MIPMAP_MODE_MAX_ENUM = 0x7FFFFFFF +} VkSamplerMipmapMode; + typedef enum VkDescriptorType { VK_DESCRIPTOR_TYPE_SAMPLER = 0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER = 1, @@ -1362,10 +1444,9 @@ typedef enum VkDescriptorType { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10, VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT = 1000138000, + VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR = 1000150000, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000, - VK_DESCRIPTOR_TYPE_BEGIN_RANGE = VK_DESCRIPTOR_TYPE_SAMPLER, - VK_DESCRIPTOR_TYPE_END_RANGE = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, - VK_DESCRIPTOR_TYPE_RANGE_SIZE = (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT - VK_DESCRIPTOR_TYPE_SAMPLER + 1), + VK_DESCRIPTOR_TYPE_MUTABLE_VALVE = 1000351000, VK_DESCRIPTOR_TYPE_MAX_ENUM = 0x7FFFFFFF } VkDescriptorType; @@ -1373,119 +1454,100 @@ typedef enum VkAttachmentLoadOp { VK_ATTACHMENT_LOAD_OP_LOAD = 0, VK_ATTACHMENT_LOAD_OP_CLEAR = 1, VK_ATTACHMENT_LOAD_OP_DONT_CARE = 2, - VK_ATTACHMENT_LOAD_OP_BEGIN_RANGE = VK_ATTACHMENT_LOAD_OP_LOAD, - VK_ATTACHMENT_LOAD_OP_END_RANGE = VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_LOAD_OP_RANGE_SIZE = (VK_ATTACHMENT_LOAD_OP_DONT_CARE - VK_ATTACHMENT_LOAD_OP_LOAD + 1), VK_ATTACHMENT_LOAD_OP_MAX_ENUM = 0x7FFFFFFF } VkAttachmentLoadOp; typedef enum VkAttachmentStoreOp { VK_ATTACHMENT_STORE_OP_STORE = 0, VK_ATTACHMENT_STORE_OP_DONT_CARE = 1, - VK_ATTACHMENT_STORE_OP_BEGIN_RANGE = VK_ATTACHMENT_STORE_OP_STORE, - VK_ATTACHMENT_STORE_OP_END_RANGE = VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_RANGE_SIZE = (VK_ATTACHMENT_STORE_OP_DONT_CARE - VK_ATTACHMENT_STORE_OP_STORE + 1), + VK_ATTACHMENT_STORE_OP_NONE_QCOM = 1000301000, VK_ATTACHMENT_STORE_OP_MAX_ENUM = 0x7FFFFFFF } VkAttachmentStoreOp; typedef enum VkPipelineBindPoint { VK_PIPELINE_BIND_POINT_GRAPHICS = 0, VK_PIPELINE_BIND_POINT_COMPUTE = 1, - VK_PIPELINE_BIND_POINT_RAY_TRACING_NV = 1000165000, - VK_PIPELINE_BIND_POINT_BEGIN_RANGE = VK_PIPELINE_BIND_POINT_GRAPHICS, - VK_PIPELINE_BIND_POINT_END_RANGE = VK_PIPELINE_BIND_POINT_COMPUTE, - VK_PIPELINE_BIND_POINT_RANGE_SIZE = (VK_PIPELINE_BIND_POINT_COMPUTE - VK_PIPELINE_BIND_POINT_GRAPHICS + 1), + VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR = 1000165000, + VK_PIPELINE_BIND_POINT_RAY_TRACING_NV = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, VK_PIPELINE_BIND_POINT_MAX_ENUM = 0x7FFFFFFF } VkPipelineBindPoint; typedef enum VkCommandBufferLevel { VK_COMMAND_BUFFER_LEVEL_PRIMARY = 0, VK_COMMAND_BUFFER_LEVEL_SECONDARY = 1, - VK_COMMAND_BUFFER_LEVEL_BEGIN_RANGE = VK_COMMAND_BUFFER_LEVEL_PRIMARY, - VK_COMMAND_BUFFER_LEVEL_END_RANGE = VK_COMMAND_BUFFER_LEVEL_SECONDARY, - VK_COMMAND_BUFFER_LEVEL_RANGE_SIZE = (VK_COMMAND_BUFFER_LEVEL_SECONDARY - VK_COMMAND_BUFFER_LEVEL_PRIMARY + 1), VK_COMMAND_BUFFER_LEVEL_MAX_ENUM = 0x7FFFFFFF } VkCommandBufferLevel; typedef enum VkIndexType { VK_INDEX_TYPE_UINT16 = 0, VK_INDEX_TYPE_UINT32 = 1, - VK_INDEX_TYPE_NONE_NV = 1000165000, + VK_INDEX_TYPE_NONE_KHR = 1000165000, VK_INDEX_TYPE_UINT8_EXT = 1000265000, - VK_INDEX_TYPE_BEGIN_RANGE = VK_INDEX_TYPE_UINT16, - VK_INDEX_TYPE_END_RANGE = VK_INDEX_TYPE_UINT32, - VK_INDEX_TYPE_RANGE_SIZE = (VK_INDEX_TYPE_UINT32 - VK_INDEX_TYPE_UINT16 + 1), + VK_INDEX_TYPE_NONE_NV = VK_INDEX_TYPE_NONE_KHR, VK_INDEX_TYPE_MAX_ENUM = 0x7FFFFFFF } VkIndexType; typedef enum VkSubpassContents { VK_SUBPASS_CONTENTS_INLINE = 0, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS = 1, - VK_SUBPASS_CONTENTS_BEGIN_RANGE = VK_SUBPASS_CONTENTS_INLINE, - VK_SUBPASS_CONTENTS_END_RANGE = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, - VK_SUBPASS_CONTENTS_RANGE_SIZE = (VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS - VK_SUBPASS_CONTENTS_INLINE + 1), VK_SUBPASS_CONTENTS_MAX_ENUM = 0x7FFFFFFF } VkSubpassContents; -typedef enum VkObjectType { - VK_OBJECT_TYPE_UNKNOWN = 0, - VK_OBJECT_TYPE_INSTANCE = 1, - VK_OBJECT_TYPE_PHYSICAL_DEVICE = 2, - VK_OBJECT_TYPE_DEVICE = 3, - VK_OBJECT_TYPE_QUEUE = 4, - VK_OBJECT_TYPE_SEMAPHORE = 5, - VK_OBJECT_TYPE_COMMAND_BUFFER = 6, - VK_OBJECT_TYPE_FENCE = 7, - VK_OBJECT_TYPE_DEVICE_MEMORY = 8, - VK_OBJECT_TYPE_BUFFER = 9, - VK_OBJECT_TYPE_IMAGE = 10, - VK_OBJECT_TYPE_EVENT = 11, - VK_OBJECT_TYPE_QUERY_POOL = 12, - VK_OBJECT_TYPE_BUFFER_VIEW = 13, - VK_OBJECT_TYPE_IMAGE_VIEW = 14, - VK_OBJECT_TYPE_SHADER_MODULE = 15, - VK_OBJECT_TYPE_PIPELINE_CACHE = 16, - VK_OBJECT_TYPE_PIPELINE_LAYOUT = 17, - VK_OBJECT_TYPE_RENDER_PASS = 18, - VK_OBJECT_TYPE_PIPELINE = 19, - VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT = 20, - VK_OBJECT_TYPE_SAMPLER = 21, - VK_OBJECT_TYPE_DESCRIPTOR_POOL = 22, - VK_OBJECT_TYPE_DESCRIPTOR_SET = 23, - VK_OBJECT_TYPE_FRAMEBUFFER = 24, - VK_OBJECT_TYPE_COMMAND_POOL = 25, - VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION = 1000156000, - VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE = 1000085000, - VK_OBJECT_TYPE_SURFACE_KHR = 1000000000, - VK_OBJECT_TYPE_SWAPCHAIN_KHR = 1000001000, - VK_OBJECT_TYPE_DISPLAY_KHR = 1000002000, - VK_OBJECT_TYPE_DISPLAY_MODE_KHR = 1000002001, - VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT = 1000011000, - VK_OBJECT_TYPE_OBJECT_TABLE_NVX = 1000086000, - VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX = 1000086001, - VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT = 1000128000, - VK_OBJECT_TYPE_VALIDATION_CACHE_EXT = 1000160000, - VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000, - VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL = 1000210000, - VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR = VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE, - VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR = VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION, - VK_OBJECT_TYPE_BEGIN_RANGE = VK_OBJECT_TYPE_UNKNOWN, - VK_OBJECT_TYPE_END_RANGE = VK_OBJECT_TYPE_COMMAND_POOL, - VK_OBJECT_TYPE_RANGE_SIZE = (VK_OBJECT_TYPE_COMMAND_POOL - VK_OBJECT_TYPE_UNKNOWN + 1), - VK_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF -} VkObjectType; +typedef enum VkAccessFlagBits { + VK_ACCESS_INDIRECT_COMMAND_READ_BIT = 0x00000001, + VK_ACCESS_INDEX_READ_BIT = 0x00000002, + VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT = 0x00000004, + VK_ACCESS_UNIFORM_READ_BIT = 0x00000008, + VK_ACCESS_INPUT_ATTACHMENT_READ_BIT = 0x00000010, + VK_ACCESS_SHADER_READ_BIT = 0x00000020, + VK_ACCESS_SHADER_WRITE_BIT = 0x00000040, + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT = 0x00000080, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT = 0x00000100, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 0x00000200, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 0x00000400, + VK_ACCESS_TRANSFER_READ_BIT = 0x00000800, + VK_ACCESS_TRANSFER_WRITE_BIT = 0x00001000, + VK_ACCESS_HOST_READ_BIT = 0x00002000, + VK_ACCESS_HOST_WRITE_BIT = 0x00004000, + VK_ACCESS_MEMORY_READ_BIT = 0x00008000, + VK_ACCESS_MEMORY_WRITE_BIT = 0x00010000, + VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT = 0x02000000, + VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0x04000000, + VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0x08000000, + VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT = 0x00100000, + VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000, + VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR = 0x00200000, + VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR = 0x00400000, + VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV = 0x00800000, + VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0x01000000, + VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV = 0x00020000, + VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV = 0x00040000, + VK_ACCESS_NONE_KHR = 0, + VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, + VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, + VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR = VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV, + VK_ACCESS_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkAccessFlagBits; +typedef VkFlags VkAccessFlags; -typedef enum VkVendorId { - VK_VENDOR_ID_VIV = 0x10001, - VK_VENDOR_ID_VSI = 0x10002, - VK_VENDOR_ID_KAZAN = 0x10003, - VK_VENDOR_ID_CODEPLAY = 0x10004, - VK_VENDOR_ID_BEGIN_RANGE = VK_VENDOR_ID_VIV, - VK_VENDOR_ID_END_RANGE = VK_VENDOR_ID_CODEPLAY, - VK_VENDOR_ID_RANGE_SIZE = (VK_VENDOR_ID_CODEPLAY - VK_VENDOR_ID_VIV + 1), - VK_VENDOR_ID_MAX_ENUM = 0x7FFFFFFF -} VkVendorId; -typedef VkFlags VkInstanceCreateFlags; +typedef enum VkImageAspectFlagBits { + VK_IMAGE_ASPECT_COLOR_BIT = 0x00000001, + VK_IMAGE_ASPECT_DEPTH_BIT = 0x00000002, + VK_IMAGE_ASPECT_STENCIL_BIT = 0x00000004, + VK_IMAGE_ASPECT_METADATA_BIT = 0x00000008, + VK_IMAGE_ASPECT_PLANE_0_BIT = 0x00000010, + VK_IMAGE_ASPECT_PLANE_1_BIT = 0x00000020, + VK_IMAGE_ASPECT_PLANE_2_BIT = 0x00000040, + VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT = 0x00000080, + VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT = 0x00000100, + VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT = 0x00000200, + VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT = 0x00000400, + VK_IMAGE_ASPECT_PLANE_0_BIT_KHR = VK_IMAGE_ASPECT_PLANE_0_BIT, + VK_IMAGE_ASPECT_PLANE_1_BIT_KHR = VK_IMAGE_ASPECT_PLANE_1_BIT, + VK_IMAGE_ASPECT_PLANE_2_BIT_KHR = VK_IMAGE_ASPECT_PLANE_2_BIT, + VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkImageAspectFlagBits; +typedef VkFlags VkImageAspectFlags; typedef enum VkFormatFeatureFlagBits { VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT = 0x00000001, @@ -1512,7 +1574,9 @@ typedef enum VkFormatFeatureFlagBits { VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT = 0x00800000, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT = 0x00010000, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG = 0x00002000, + VK_FORMAT_FEATURE_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR = 0x20000000, VK_FORMAT_FEATURE_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x01000000, + VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x40000000, VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT, VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR = VK_FORMAT_FEATURE_TRANSFER_DST_BIT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT = VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT, @@ -1528,21 +1592,6 @@ typedef enum VkFormatFeatureFlagBits { } VkFormatFeatureFlagBits; typedef VkFlags VkFormatFeatureFlags; -typedef enum VkImageUsageFlagBits { - VK_IMAGE_USAGE_TRANSFER_SRC_BIT = 0x00000001, - VK_IMAGE_USAGE_TRANSFER_DST_BIT = 0x00000002, - VK_IMAGE_USAGE_SAMPLED_BIT = 0x00000004, - VK_IMAGE_USAGE_STORAGE_BIT = 0x00000008, - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT = 0x00000010, - VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000020, - VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0x00000040, - VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0x00000080, - VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV = 0x00000100, - VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x00000200, - VK_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkImageUsageFlagBits; -typedef VkFlags VkImageUsageFlags; - typedef enum VkImageCreateFlagBits { VK_IMAGE_CREATE_SPARSE_BINDING_BIT = 0x00000001, VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002, @@ -1581,15 +1630,30 @@ typedef enum VkSampleCountFlagBits { } VkSampleCountFlagBits; typedef VkFlags VkSampleCountFlags; -typedef enum VkQueueFlagBits { - VK_QUEUE_GRAPHICS_BIT = 0x00000001, - VK_QUEUE_COMPUTE_BIT = 0x00000002, - VK_QUEUE_TRANSFER_BIT = 0x00000004, - VK_QUEUE_SPARSE_BINDING_BIT = 0x00000008, - VK_QUEUE_PROTECTED_BIT = 0x00000010, - VK_QUEUE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkQueueFlagBits; -typedef VkFlags VkQueueFlags; +typedef enum VkImageUsageFlagBits { + VK_IMAGE_USAGE_TRANSFER_SRC_BIT = 0x00000001, + VK_IMAGE_USAGE_TRANSFER_DST_BIT = 0x00000002, + VK_IMAGE_USAGE_SAMPLED_BIT = 0x00000004, + VK_IMAGE_USAGE_STORAGE_BIT = 0x00000008, + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT = 0x00000010, + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000020, + VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0x00000040, + VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0x00000080, + VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV = 0x00000100, + VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x00000200, + VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV, + VK_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkImageUsageFlagBits; +typedef VkFlags VkImageUsageFlags; +typedef VkFlags VkInstanceCreateFlags; + +typedef enum VkMemoryHeapFlagBits { + VK_MEMORY_HEAP_DEVICE_LOCAL_BIT = 0x00000001, + VK_MEMORY_HEAP_MULTI_INSTANCE_BIT = 0x00000002, + VK_MEMORY_HEAP_MULTI_INSTANCE_BIT_KHR = VK_MEMORY_HEAP_MULTI_INSTANCE_BIT, + VK_MEMORY_HEAP_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkMemoryHeapFlagBits; +typedef VkFlags VkMemoryHeapFlags; typedef enum VkMemoryPropertyFlagBits { VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT = 0x00000001, @@ -1604,13 +1668,15 @@ typedef enum VkMemoryPropertyFlagBits { } VkMemoryPropertyFlagBits; typedef VkFlags VkMemoryPropertyFlags; -typedef enum VkMemoryHeapFlagBits { - VK_MEMORY_HEAP_DEVICE_LOCAL_BIT = 0x00000001, - VK_MEMORY_HEAP_MULTI_INSTANCE_BIT = 0x00000002, - VK_MEMORY_HEAP_MULTI_INSTANCE_BIT_KHR = VK_MEMORY_HEAP_MULTI_INSTANCE_BIT, - VK_MEMORY_HEAP_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkMemoryHeapFlagBits; -typedef VkFlags VkMemoryHeapFlags; +typedef enum VkQueueFlagBits { + VK_QUEUE_GRAPHICS_BIT = 0x00000001, + VK_QUEUE_COMPUTE_BIT = 0x00000002, + VK_QUEUE_TRANSFER_BIT = 0x00000004, + VK_QUEUE_SPARSE_BINDING_BIT = 0x00000008, + VK_QUEUE_PROTECTED_BIT = 0x00000010, + VK_QUEUE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkQueueFlagBits; +typedef VkFlags VkQueueFlags; typedef VkFlags VkDeviceCreateFlags; typedef enum VkDeviceQueueCreateFlagBits { @@ -1639,36 +1705,27 @@ typedef enum VkPipelineStageFlagBits { VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00010000, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT = 0x01000000, VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00040000, - VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX = 0x00020000, + VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR = 0x02000000, + VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR = 0x00200000, VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV = 0x00400000, - VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV = 0x00200000, - VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV = 0x02000000, VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV = 0x00080000, VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV = 0x00100000, VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0x00800000, + VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV = 0x00020000, + VK_PIPELINE_STAGE_NONE_KHR = 0, + VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV = VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, + VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV = VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, + VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV, VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkPipelineStageFlagBits; typedef VkFlags VkPipelineStageFlags; typedef VkFlags VkMemoryMapFlags; -typedef enum VkImageAspectFlagBits { - VK_IMAGE_ASPECT_COLOR_BIT = 0x00000001, - VK_IMAGE_ASPECT_DEPTH_BIT = 0x00000002, - VK_IMAGE_ASPECT_STENCIL_BIT = 0x00000004, - VK_IMAGE_ASPECT_METADATA_BIT = 0x00000008, - VK_IMAGE_ASPECT_PLANE_0_BIT = 0x00000010, - VK_IMAGE_ASPECT_PLANE_1_BIT = 0x00000020, - VK_IMAGE_ASPECT_PLANE_2_BIT = 0x00000040, - VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT = 0x00000080, - VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT = 0x00000100, - VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT = 0x00000200, - VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT = 0x00000400, - VK_IMAGE_ASPECT_PLANE_0_BIT_KHR = VK_IMAGE_ASPECT_PLANE_0_BIT, - VK_IMAGE_ASPECT_PLANE_1_BIT_KHR = VK_IMAGE_ASPECT_PLANE_1_BIT, - VK_IMAGE_ASPECT_PLANE_2_BIT_KHR = VK_IMAGE_ASPECT_PLANE_2_BIT, - VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkImageAspectFlagBits; -typedef VkFlags VkImageAspectFlags; +typedef enum VkSparseMemoryBindFlagBits { + VK_SPARSE_MEMORY_BIND_METADATA_BIT = 0x00000001, + VK_SPARSE_MEMORY_BIND_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSparseMemoryBindFlagBits; +typedef VkFlags VkSparseMemoryBindFlags; typedef enum VkSparseImageFormatFlagBits { VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT = 0x00000001, @@ -1678,20 +1735,18 @@ typedef enum VkSparseImageFormatFlagBits { } VkSparseImageFormatFlagBits; typedef VkFlags VkSparseImageFormatFlags; -typedef enum VkSparseMemoryBindFlagBits { - VK_SPARSE_MEMORY_BIND_METADATA_BIT = 0x00000001, - VK_SPARSE_MEMORY_BIND_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkSparseMemoryBindFlagBits; -typedef VkFlags VkSparseMemoryBindFlags; - typedef enum VkFenceCreateFlagBits { VK_FENCE_CREATE_SIGNALED_BIT = 0x00000001, VK_FENCE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkFenceCreateFlagBits; typedef VkFlags VkFenceCreateFlags; typedef VkFlags VkSemaphoreCreateFlags; + +typedef enum VkEventCreateFlagBits { + VK_EVENT_CREATE_DEVICE_ONLY_BIT_KHR = 0x00000001, + VK_EVENT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkEventCreateFlagBits; typedef VkFlags VkEventCreateFlags; -typedef VkFlags VkQueryPoolCreateFlags; typedef enum VkQueryPipelineStatisticFlagBits { VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT = 0x00000001, @@ -1708,6 +1763,7 @@ typedef enum VkQueryPipelineStatisticFlagBits { VK_QUERY_PIPELINE_STATISTIC_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkQueryPipelineStatisticFlagBits; typedef VkFlags VkQueryPipelineStatisticFlags; +typedef VkFlags VkQueryPoolCreateFlags; typedef enum VkQueryResultFlagBits { VK_QUERY_RESULT_64_BIT = 0x00000001, @@ -1744,7 +1800,10 @@ typedef enum VkBufferUsageFlagBits { VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT = 0x00000800, VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT = 0x00001000, VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00000200, - VK_BUFFER_USAGE_RAY_TRACING_BIT_NV = 0x00000400, + VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR = 0x00080000, + VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR = 0x00100000, + VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR = 0x00000400, + VK_BUFFER_USAGE_RAY_TRACING_BIT_NV = VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF @@ -1754,6 +1813,7 @@ typedef VkFlags VkBufferViewCreateFlags; typedef enum VkImageViewCreateFlagBits { VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DYNAMIC_BIT_EXT = 0x00000001, + VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DEFERRED_BIT_EXT = 0x00000002, VK_IMAGE_VIEW_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkImageViewCreateFlagBits; typedef VkFlags VkImageViewCreateFlags; @@ -1762,17 +1822,42 @@ typedef enum VkShaderModuleCreateFlagBits { VK_SHADER_MODULE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkShaderModuleCreateFlagBits; typedef VkFlags VkShaderModuleCreateFlags; + +typedef enum VkPipelineCacheCreateFlagBits { + VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT = 0x00000001, + VK_PIPELINE_CACHE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineCacheCreateFlagBits; typedef VkFlags VkPipelineCacheCreateFlags; +typedef enum VkColorComponentFlagBits { + VK_COLOR_COMPONENT_R_BIT = 0x00000001, + VK_COLOR_COMPONENT_G_BIT = 0x00000002, + VK_COLOR_COMPONENT_B_BIT = 0x00000004, + VK_COLOR_COMPONENT_A_BIT = 0x00000008, + VK_COLOR_COMPONENT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkColorComponentFlagBits; +typedef VkFlags VkColorComponentFlags; + typedef enum VkPipelineCreateFlagBits { VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT = 0x00000001, VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT = 0x00000002, VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004, VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT = 0x00000008, VK_PIPELINE_CREATE_DISPATCH_BASE_BIT = 0x00000010, + VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR = 0x00004000, + VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR = 0x00008000, + VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR = 0x00010000, + VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR = 0x00020000, + VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR = 0x00001000, + VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR = 0x00002000, + VK_PIPELINE_CREATE_RAY_TRACING_SHADER_GROUP_HANDLE_CAPTURE_REPLAY_BIT_KHR = 0x00080000, VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NV = 0x00000020, VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR = 0x00000040, VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR = 0x00000080, + VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV = 0x00040000, + VK_PIPELINE_CREATE_LIBRARY_BIT_KHR = 0x00000800, + VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT = 0x00000100, + VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT = 0x00000200, VK_PIPELINE_CREATE_DISPATCH_BASE = VK_PIPELINE_CREATE_DISPATCH_BASE_BIT, VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR = VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT, VK_PIPELINE_CREATE_DISPATCH_BASE_KHR = VK_PIPELINE_CREATE_DISPATCH_BASE, @@ -1796,21 +1881,22 @@ typedef enum VkShaderStageFlagBits { VK_SHADER_STAGE_COMPUTE_BIT = 0x00000020, VK_SHADER_STAGE_ALL_GRAPHICS = 0x0000001F, VK_SHADER_STAGE_ALL = 0x7FFFFFFF, - VK_SHADER_STAGE_RAYGEN_BIT_NV = 0x00000100, - VK_SHADER_STAGE_ANY_HIT_BIT_NV = 0x00000200, - VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV = 0x00000400, - VK_SHADER_STAGE_MISS_BIT_NV = 0x00000800, - VK_SHADER_STAGE_INTERSECTION_BIT_NV = 0x00001000, - VK_SHADER_STAGE_CALLABLE_BIT_NV = 0x00002000, + VK_SHADER_STAGE_RAYGEN_BIT_KHR = 0x00000100, + VK_SHADER_STAGE_ANY_HIT_BIT_KHR = 0x00000200, + VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR = 0x00000400, + VK_SHADER_STAGE_MISS_BIT_KHR = 0x00000800, + VK_SHADER_STAGE_INTERSECTION_BIT_KHR = 0x00001000, + VK_SHADER_STAGE_CALLABLE_BIT_KHR = 0x00002000, VK_SHADER_STAGE_TASK_BIT_NV = 0x00000040, VK_SHADER_STAGE_MESH_BIT_NV = 0x00000080, + VK_SHADER_STAGE_RAYGEN_BIT_NV = VK_SHADER_STAGE_RAYGEN_BIT_KHR, + VK_SHADER_STAGE_ANY_HIT_BIT_NV = VK_SHADER_STAGE_ANY_HIT_BIT_KHR, + VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, + VK_SHADER_STAGE_MISS_BIT_NV = VK_SHADER_STAGE_MISS_BIT_KHR, + VK_SHADER_STAGE_INTERSECTION_BIT_NV = VK_SHADER_STAGE_INTERSECTION_BIT_KHR, + VK_SHADER_STAGE_CALLABLE_BIT_NV = VK_SHADER_STAGE_CALLABLE_BIT_KHR, VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkShaderStageFlagBits; -typedef VkFlags VkPipelineVertexInputStateCreateFlags; -typedef VkFlags VkPipelineInputAssemblyStateCreateFlags; -typedef VkFlags VkPipelineTessellationStateCreateFlags; -typedef VkFlags VkPipelineViewportStateCreateFlags; -typedef VkFlags VkPipelineRasterizationStateCreateFlags; typedef enum VkCullModeFlagBits { VK_CULL_MODE_NONE = 0, @@ -1820,18 +1906,14 @@ typedef enum VkCullModeFlagBits { VK_CULL_MODE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkCullModeFlagBits; typedef VkFlags VkCullModeFlags; +typedef VkFlags VkPipelineVertexInputStateCreateFlags; +typedef VkFlags VkPipelineInputAssemblyStateCreateFlags; +typedef VkFlags VkPipelineTessellationStateCreateFlags; +typedef VkFlags VkPipelineViewportStateCreateFlags; +typedef VkFlags VkPipelineRasterizationStateCreateFlags; typedef VkFlags VkPipelineMultisampleStateCreateFlags; typedef VkFlags VkPipelineDepthStencilStateCreateFlags; typedef VkFlags VkPipelineColorBlendStateCreateFlags; - -typedef enum VkColorComponentFlagBits { - VK_COLOR_COMPONENT_R_BIT = 0x00000001, - VK_COLOR_COMPONENT_G_BIT = 0x00000002, - VK_COLOR_COMPONENT_B_BIT = 0x00000004, - VK_COLOR_COMPONENT_A_BIT = 0x00000008, - VK_COLOR_COMPONENT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkColorComponentFlagBits; -typedef VkFlags VkColorComponentFlags; typedef VkFlags VkPipelineDynamicStateCreateFlags; typedef VkFlags VkPipelineLayoutCreateFlags; typedef VkFlags VkShaderStageFlags; @@ -1843,34 +1925,24 @@ typedef enum VkSamplerCreateFlagBits { } VkSamplerCreateFlagBits; typedef VkFlags VkSamplerCreateFlags; -typedef enum VkDescriptorSetLayoutCreateFlagBits { - VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT = 0x00000002, - VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR = 0x00000001, - VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT, - VK_DESCRIPTOR_SET_LAYOUT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkDescriptorSetLayoutCreateFlagBits; -typedef VkFlags VkDescriptorSetLayoutCreateFlags; - typedef enum VkDescriptorPoolCreateFlagBits { VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 0x00000001, VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT = 0x00000002, + VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE = 0x00000004, VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT, VK_DESCRIPTOR_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkDescriptorPoolCreateFlagBits; typedef VkFlags VkDescriptorPoolCreateFlags; typedef VkFlags VkDescriptorPoolResetFlags; -typedef enum VkFramebufferCreateFlagBits { - VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT = 0x00000001, - VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT_KHR = VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, - VK_FRAMEBUFFER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkFramebufferCreateFlagBits; -typedef VkFlags VkFramebufferCreateFlags; - -typedef enum VkRenderPassCreateFlagBits { - VK_RENDER_PASS_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkRenderPassCreateFlagBits; -typedef VkFlags VkRenderPassCreateFlags; +typedef enum VkDescriptorSetLayoutCreateFlagBits { + VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT = 0x00000002, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR = 0x00000001, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_VALVE = 0x00000004, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkDescriptorSetLayoutCreateFlagBits; +typedef VkFlags VkDescriptorSetLayoutCreateFlags; typedef enum VkAttachmentDescriptionFlagBits { VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT = 0x00000001, @@ -1878,46 +1950,6 @@ typedef enum VkAttachmentDescriptionFlagBits { } VkAttachmentDescriptionFlagBits; typedef VkFlags VkAttachmentDescriptionFlags; -typedef enum VkSubpassDescriptionFlagBits { - VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX = 0x00000001, - VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX = 0x00000002, - VK_SUBPASS_DESCRIPTION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkSubpassDescriptionFlagBits; -typedef VkFlags VkSubpassDescriptionFlags; - -typedef enum VkAccessFlagBits { - VK_ACCESS_INDIRECT_COMMAND_READ_BIT = 0x00000001, - VK_ACCESS_INDEX_READ_BIT = 0x00000002, - VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT = 0x00000004, - VK_ACCESS_UNIFORM_READ_BIT = 0x00000008, - VK_ACCESS_INPUT_ATTACHMENT_READ_BIT = 0x00000010, - VK_ACCESS_SHADER_READ_BIT = 0x00000020, - VK_ACCESS_SHADER_WRITE_BIT = 0x00000040, - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT = 0x00000080, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT = 0x00000100, - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 0x00000200, - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 0x00000400, - VK_ACCESS_TRANSFER_READ_BIT = 0x00000800, - VK_ACCESS_TRANSFER_WRITE_BIT = 0x00001000, - VK_ACCESS_HOST_READ_BIT = 0x00002000, - VK_ACCESS_HOST_WRITE_BIT = 0x00004000, - VK_ACCESS_MEMORY_READ_BIT = 0x00008000, - VK_ACCESS_MEMORY_WRITE_BIT = 0x00010000, - VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT = 0x02000000, - VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0x04000000, - VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0x08000000, - VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT = 0x00100000, - VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX = 0x00020000, - VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX = 0x00040000, - VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000, - VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV = 0x00800000, - VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV = 0x00200000, - VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV = 0x00400000, - VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0x01000000, - VK_ACCESS_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkAccessFlagBits; -typedef VkFlags VkAccessFlags; - typedef enum VkDependencyFlagBits { VK_DEPENDENCY_BY_REGION_BIT = 0x00000001, VK_DEPENDENCY_DEVICE_GROUP_BIT = 0x00000004, @@ -1928,6 +1960,28 @@ typedef enum VkDependencyFlagBits { } VkDependencyFlagBits; typedef VkFlags VkDependencyFlags; +typedef enum VkFramebufferCreateFlagBits { + VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT = 0x00000001, + VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT_KHR = VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, + VK_FRAMEBUFFER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkFramebufferCreateFlagBits; +typedef VkFlags VkFramebufferCreateFlags; + +typedef enum VkRenderPassCreateFlagBits { + VK_RENDER_PASS_CREATE_TRANSFORM_BIT_QCOM = 0x00000002, + VK_RENDER_PASS_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkRenderPassCreateFlagBits; +typedef VkFlags VkRenderPassCreateFlags; + +typedef enum VkSubpassDescriptionFlagBits { + VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX = 0x00000001, + VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX = 0x00000002, + VK_SUBPASS_DESCRIPTION_FRAGMENT_REGION_BIT_QCOM = 0x00000004, + VK_SUBPASS_DESCRIPTION_SHADER_RESOLVE_BIT_QCOM = 0x00000008, + VK_SUBPASS_DESCRIPTION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSubpassDescriptionFlagBits; +typedef VkFlags VkSubpassDescriptionFlags; + typedef enum VkCommandPoolCreateFlagBits { VK_COMMAND_POOL_CREATE_TRANSIENT_BIT = 0x00000001, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT = 0x00000002, @@ -1970,26 +2024,103 @@ typedef enum VkStencilFaceFlagBits { VK_STENCIL_FACE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkStencilFaceFlagBits; typedef VkFlags VkStencilFaceFlags; -typedef struct VkApplicationInfo { +typedef struct VkExtent2D { + uint32_t width; + uint32_t height; +} VkExtent2D; + +typedef struct VkExtent3D { + uint32_t width; + uint32_t height; + uint32_t depth; +} VkExtent3D; + +typedef struct VkOffset2D { + int32_t x; + int32_t y; +} VkOffset2D; + +typedef struct VkOffset3D { + int32_t x; + int32_t y; + int32_t z; +} VkOffset3D; + +typedef struct VkRect2D { + VkOffset2D offset; + VkExtent2D extent; +} VkRect2D; + +typedef struct VkBaseInStructure { + VkStructureType sType; + const struct VkBaseInStructure* pNext; +} VkBaseInStructure; + +typedef struct VkBaseOutStructure { + VkStructureType sType; + struct VkBaseOutStructure* pNext; +} VkBaseOutStructure; + +typedef struct VkBufferMemoryBarrier { VkStructureType sType; const void* pNext; - const char* pApplicationName; - uint32_t applicationVersion; - const char* pEngineName; - uint32_t engineVersion; - uint32_t apiVersion; -} VkApplicationInfo; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkBuffer buffer; + VkDeviceSize offset; + VkDeviceSize size; +} VkBufferMemoryBarrier; -typedef struct VkInstanceCreateInfo { - VkStructureType sType; - const void* pNext; - VkInstanceCreateFlags flags; - const VkApplicationInfo* pApplicationInfo; - uint32_t enabledLayerCount; - const char* const* ppEnabledLayerNames; - uint32_t enabledExtensionCount; - const char* const* ppEnabledExtensionNames; -} VkInstanceCreateInfo; +typedef struct VkDispatchIndirectCommand { + uint32_t x; + uint32_t y; + uint32_t z; +} VkDispatchIndirectCommand; + +typedef struct VkDrawIndexedIndirectCommand { + uint32_t indexCount; + uint32_t instanceCount; + uint32_t firstIndex; + int32_t vertexOffset; + uint32_t firstInstance; +} VkDrawIndexedIndirectCommand; + +typedef struct VkDrawIndirectCommand { + uint32_t vertexCount; + uint32_t instanceCount; + uint32_t firstVertex; + uint32_t firstInstance; +} VkDrawIndirectCommand; + +typedef struct VkImageSubresourceRange { + VkImageAspectFlags aspectMask; + uint32_t baseMipLevel; + uint32_t levelCount; + uint32_t baseArrayLayer; + uint32_t layerCount; +} VkImageSubresourceRange; + +typedef struct VkImageMemoryBarrier { + VkStructureType sType; + const void* pNext; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; + VkImageLayout oldLayout; + VkImageLayout newLayout; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkImage image; + VkImageSubresourceRange subresourceRange; +} VkImageMemoryBarrier; + +typedef struct VkMemoryBarrier { + VkStructureType sType; + const void* pNext; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; +} VkMemoryBarrier; typedef void* (VKAPI_PTR *PFN_vkAllocationFunction)( void* pUserData, @@ -1997,13 +2128,6 @@ typedef void* (VKAPI_PTR *PFN_vkAllocationFunction)( size_t alignment, VkSystemAllocationScope allocationScope); -typedef void* (VKAPI_PTR *PFN_vkReallocationFunction)( - void* pUserData, - void* pOriginal, - size_t size, - size_t alignment, - VkSystemAllocationScope allocationScope); - typedef void (VKAPI_PTR *PFN_vkFreeFunction)( void* pUserData, void* pMemory); @@ -2020,6 +2144,14 @@ typedef void (VKAPI_PTR *PFN_vkInternalFreeNotification)( VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope); +typedef void* (VKAPI_PTR *PFN_vkReallocationFunction)( + void* pUserData, + void* pOriginal, + size_t size, + size_t alignment, + VkSystemAllocationScope allocationScope); + +typedef void (VKAPI_PTR *PFN_vkVoidFunction)(void); typedef struct VkAllocationCallbacks { void* pUserData; PFN_vkAllocationFunction pfnAllocation; @@ -2029,6 +2161,51 @@ typedef struct VkAllocationCallbacks { PFN_vkInternalFreeNotification pfnInternalFree; } VkAllocationCallbacks; +typedef struct VkApplicationInfo { + VkStructureType sType; + const void* pNext; + const char* pApplicationName; + uint32_t applicationVersion; + const char* pEngineName; + uint32_t engineVersion; + uint32_t apiVersion; +} VkApplicationInfo; + +typedef struct VkFormatProperties { + VkFormatFeatureFlags linearTilingFeatures; + VkFormatFeatureFlags optimalTilingFeatures; + VkFormatFeatureFlags bufferFeatures; +} VkFormatProperties; + +typedef struct VkImageFormatProperties { + VkExtent3D maxExtent; + uint32_t maxMipLevels; + uint32_t maxArrayLayers; + VkSampleCountFlags sampleCounts; + VkDeviceSize maxResourceSize; +} VkImageFormatProperties; + +typedef struct VkInstanceCreateInfo { + VkStructureType sType; + const void* pNext; + VkInstanceCreateFlags flags; + const VkApplicationInfo* pApplicationInfo; + uint32_t enabledLayerCount; + const char* const* ppEnabledLayerNames; + uint32_t enabledExtensionCount; + const char* const* ppEnabledExtensionNames; +} VkInstanceCreateInfo; + +typedef struct VkMemoryHeap { + VkDeviceSize size; + VkMemoryHeapFlags flags; +} VkMemoryHeap; + +typedef struct VkMemoryType { + VkMemoryPropertyFlags propertyFlags; + uint32_t heapIndex; +} VkMemoryType; + typedef struct VkPhysicalDeviceFeatures { VkBool32 robustBufferAccess; VkBool32 fullDrawIndexUint32; @@ -2087,26 +2264,6 @@ typedef struct VkPhysicalDeviceFeatures { VkBool32 inheritedQueries; } VkPhysicalDeviceFeatures; -typedef struct VkFormatProperties { - VkFormatFeatureFlags linearTilingFeatures; - VkFormatFeatureFlags optimalTilingFeatures; - VkFormatFeatureFlags bufferFeatures; -} VkFormatProperties; - -typedef struct VkExtent3D { - uint32_t width; - uint32_t height; - uint32_t depth; -} VkExtent3D; - -typedef struct VkImageFormatProperties { - VkExtent3D maxExtent; - uint32_t maxMipLevels; - uint32_t maxArrayLayers; - VkSampleCountFlags sampleCounts; - VkDeviceSize maxResourceSize; -} VkImageFormatProperties; - typedef struct VkPhysicalDeviceLimits { uint32_t maxImageDimension1D; uint32_t maxImageDimension2D; @@ -2216,6 +2373,13 @@ typedef struct VkPhysicalDeviceLimits { VkDeviceSize nonCoherentAtomSize; } VkPhysicalDeviceLimits; +typedef struct VkPhysicalDeviceMemoryProperties { + uint32_t memoryTypeCount; + VkMemoryType memoryTypes[VK_MAX_MEMORY_TYPES]; + uint32_t memoryHeapCount; + VkMemoryHeap memoryHeaps[VK_MAX_MEMORY_HEAPS]; +} VkPhysicalDeviceMemoryProperties; + typedef struct VkPhysicalDeviceSparseProperties { VkBool32 residencyStandard2DBlockShape; VkBool32 residencyStandard2DMultisampleBlockShape; @@ -2243,24 +2407,6 @@ typedef struct VkQueueFamilyProperties { VkExtent3D minImageTransferGranularity; } VkQueueFamilyProperties; -typedef struct VkMemoryType { - VkMemoryPropertyFlags propertyFlags; - uint32_t heapIndex; -} VkMemoryType; - -typedef struct VkMemoryHeap { - VkDeviceSize size; - VkMemoryHeapFlags flags; -} VkMemoryHeap; - -typedef struct VkPhysicalDeviceMemoryProperties { - uint32_t memoryTypeCount; - VkMemoryType memoryTypes[VK_MAX_MEMORY_TYPES]; - uint32_t memoryHeapCount; - VkMemoryHeap memoryHeaps[VK_MAX_MEMORY_HEAPS]; -} VkPhysicalDeviceMemoryProperties; - -typedef void (VKAPI_PTR *PFN_vkVoidFunction)(void); typedef struct VkDeviceQueueCreateInfo { VkStructureType sType; const void* pNext; @@ -2307,13 +2453,6 @@ typedef struct VkSubmitInfo { const VkSemaphore* pSignalSemaphores; } VkSubmitInfo; -typedef struct VkMemoryAllocateInfo { - VkStructureType sType; - const void* pNext; - VkDeviceSize allocationSize; - uint32_t memoryTypeIndex; -} VkMemoryAllocateInfo; - typedef struct VkMappedMemoryRange { VkStructureType sType; const void* pNext; @@ -2322,26 +2461,19 @@ typedef struct VkMappedMemoryRange { VkDeviceSize size; } VkMappedMemoryRange; +typedef struct VkMemoryAllocateInfo { + VkStructureType sType; + const void* pNext; + VkDeviceSize allocationSize; + uint32_t memoryTypeIndex; +} VkMemoryAllocateInfo; + typedef struct VkMemoryRequirements { VkDeviceSize size; VkDeviceSize alignment; uint32_t memoryTypeBits; } VkMemoryRequirements; -typedef struct VkSparseImageFormatProperties { - VkImageAspectFlags aspectMask; - VkExtent3D imageGranularity; - VkSparseImageFormatFlags flags; -} VkSparseImageFormatProperties; - -typedef struct VkSparseImageMemoryRequirements { - VkSparseImageFormatProperties formatProperties; - uint32_t imageMipTailFirstLod; - VkDeviceSize imageMipTailSize; - VkDeviceSize imageMipTailOffset; - VkDeviceSize imageMipTailStride; -} VkSparseImageMemoryRequirements; - typedef struct VkSparseMemoryBind { VkDeviceSize resourceOffset; VkDeviceSize size; @@ -2368,12 +2500,6 @@ typedef struct VkImageSubresource { uint32_t arrayLayer; } VkImageSubresource; -typedef struct VkOffset3D { - int32_t x; - int32_t y; - int32_t z; -} VkOffset3D; - typedef struct VkSparseImageMemoryBind { VkImageSubresource subresource; VkOffset3D offset; @@ -2404,6 +2530,20 @@ typedef struct VkBindSparseInfo { const VkSemaphore* pSignalSemaphores; } VkBindSparseInfo; +typedef struct VkSparseImageFormatProperties { + VkImageAspectFlags aspectMask; + VkExtent3D imageGranularity; + VkSparseImageFormatFlags flags; +} VkSparseImageFormatProperties; + +typedef struct VkSparseImageMemoryRequirements { + VkSparseImageFormatProperties formatProperties; + uint32_t imageMipTailFirstLod; + VkDeviceSize imageMipTailSize; + VkDeviceSize imageMipTailOffset; + VkDeviceSize imageMipTailStride; +} VkSparseImageMemoryRequirements; + typedef struct VkFenceCreateInfo { VkStructureType sType; const void* pNext; @@ -2485,14 +2625,6 @@ typedef struct VkComponentMapping { VkComponentSwizzle a; } VkComponentMapping; -typedef struct VkImageSubresourceRange { - VkImageAspectFlags aspectMask; - uint32_t baseMipLevel; - uint32_t levelCount; - uint32_t baseArrayLayer; - uint32_t layerCount; -} VkImageSubresourceRange; - typedef struct VkImageViewCreateInfo { VkStructureType sType; const void* pNext; @@ -2543,6 +2675,16 @@ typedef struct VkPipelineShaderStageCreateInfo { const VkSpecializationInfo* pSpecializationInfo; } VkPipelineShaderStageCreateInfo; +typedef struct VkComputePipelineCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineCreateFlags flags; + VkPipelineShaderStageCreateInfo stage; + VkPipelineLayout layout; + VkPipeline basePipelineHandle; + int32_t basePipelineIndex; +} VkComputePipelineCreateInfo; + typedef struct VkVertexInputBindingDescription { uint32_t binding; uint32_t stride; @@ -2590,21 +2732,6 @@ typedef struct VkViewport { float maxDepth; } VkViewport; -typedef struct VkOffset2D { - int32_t x; - int32_t y; -} VkOffset2D; - -typedef struct VkExtent2D { - uint32_t width; - uint32_t height; -} VkExtent2D; - -typedef struct VkRect2D { - VkOffset2D offset; - VkExtent2D extent; -} VkRect2D; - typedef struct VkPipelineViewportStateCreateInfo { VkStructureType sType; const void* pNext; @@ -2720,16 +2847,6 @@ typedef struct VkGraphicsPipelineCreateInfo { int32_t basePipelineIndex; } VkGraphicsPipelineCreateInfo; -typedef struct VkComputePipelineCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineCreateFlags flags; - VkPipelineShaderStageCreateInfo stage; - VkPipelineLayout layout; - VkPipeline basePipelineHandle; - int32_t basePipelineIndex; -} VkComputePipelineCreateInfo; - typedef struct VkPushConstantRange { VkShaderStageFlags stageFlags; uint32_t offset; @@ -2767,21 +2884,29 @@ typedef struct VkSamplerCreateInfo { VkBool32 unnormalizedCoordinates; } VkSamplerCreateInfo; -typedef struct VkDescriptorSetLayoutBinding { - uint32_t binding; - VkDescriptorType descriptorType; - uint32_t descriptorCount; - VkShaderStageFlags stageFlags; - const VkSampler* pImmutableSamplers; -} VkDescriptorSetLayoutBinding; +typedef struct VkCopyDescriptorSet { + VkStructureType sType; + const void* pNext; + VkDescriptorSet srcSet; + uint32_t srcBinding; + uint32_t srcArrayElement; + VkDescriptorSet dstSet; + uint32_t dstBinding; + uint32_t dstArrayElement; + uint32_t descriptorCount; +} VkCopyDescriptorSet; -typedef struct VkDescriptorSetLayoutCreateInfo { - VkStructureType sType; - const void* pNext; - VkDescriptorSetLayoutCreateFlags flags; - uint32_t bindingCount; - const VkDescriptorSetLayoutBinding* pBindings; -} VkDescriptorSetLayoutCreateInfo; +typedef struct VkDescriptorBufferInfo { + VkBuffer buffer; + VkDeviceSize offset; + VkDeviceSize range; +} VkDescriptorBufferInfo; + +typedef struct VkDescriptorImageInfo { + VkSampler sampler; + VkImageView imageView; + VkImageLayout imageLayout; +} VkDescriptorImageInfo; typedef struct VkDescriptorPoolSize { VkDescriptorType type; @@ -2805,17 +2930,21 @@ typedef struct VkDescriptorSetAllocateInfo { const VkDescriptorSetLayout* pSetLayouts; } VkDescriptorSetAllocateInfo; -typedef struct VkDescriptorImageInfo { - VkSampler sampler; - VkImageView imageView; - VkImageLayout imageLayout; -} VkDescriptorImageInfo; +typedef struct VkDescriptorSetLayoutBinding { + uint32_t binding; + VkDescriptorType descriptorType; + uint32_t descriptorCount; + VkShaderStageFlags stageFlags; + const VkSampler* pImmutableSamplers; +} VkDescriptorSetLayoutBinding; -typedef struct VkDescriptorBufferInfo { - VkBuffer buffer; - VkDeviceSize offset; - VkDeviceSize range; -} VkDescriptorBufferInfo; +typedef struct VkDescriptorSetLayoutCreateInfo { + VkStructureType sType; + const void* pNext; + VkDescriptorSetLayoutCreateFlags flags; + uint32_t bindingCount; + const VkDescriptorSetLayoutBinding* pBindings; +} VkDescriptorSetLayoutCreateInfo; typedef struct VkWriteDescriptorSet { VkStructureType sType; @@ -2830,30 +2959,6 @@ typedef struct VkWriteDescriptorSet { const VkBufferView* pTexelBufferView; } VkWriteDescriptorSet; -typedef struct VkCopyDescriptorSet { - VkStructureType sType; - const void* pNext; - VkDescriptorSet srcSet; - uint32_t srcBinding; - uint32_t srcArrayElement; - VkDescriptorSet dstSet; - uint32_t dstBinding; - uint32_t dstArrayElement; - uint32_t descriptorCount; -} VkCopyDescriptorSet; - -typedef struct VkFramebufferCreateInfo { - VkStructureType sType; - const void* pNext; - VkFramebufferCreateFlags flags; - VkRenderPass renderPass; - uint32_t attachmentCount; - const VkImageView* pAttachments; - uint32_t width; - uint32_t height; - uint32_t layers; -} VkFramebufferCreateInfo; - typedef struct VkAttachmentDescription { VkAttachmentDescriptionFlags flags; VkFormat format; @@ -2871,6 +2976,18 @@ typedef struct VkAttachmentReference { VkImageLayout layout; } VkAttachmentReference; +typedef struct VkFramebufferCreateInfo { + VkStructureType sType; + const void* pNext; + VkFramebufferCreateFlags flags; + VkRenderPass renderPass; + uint32_t attachmentCount; + const VkImageView* pAttachments; + uint32_t width; + uint32_t height; + uint32_t layers; +} VkFramebufferCreateInfo; + typedef struct VkSubpassDescription { VkSubpassDescriptionFlags flags; VkPipelineBindPoint pipelineBindPoint; @@ -2952,21 +3069,6 @@ typedef struct VkImageSubresourceLayers { uint32_t layerCount; } VkImageSubresourceLayers; -typedef struct VkImageCopy { - VkImageSubresourceLayers srcSubresource; - VkOffset3D srcOffset; - VkImageSubresourceLayers dstSubresource; - VkOffset3D dstOffset; - VkExtent3D extent; -} VkImageCopy; - -typedef struct VkImageBlit { - VkImageSubresourceLayers srcSubresource; - VkOffset3D srcOffsets[2]; - VkImageSubresourceLayers dstSubresource; - VkOffset3D dstOffsets[2]; -} VkImageBlit; - typedef struct VkBufferImageCopy { VkDeviceSize bufferOffset; uint32_t bufferRowLength; @@ -3004,6 +3106,21 @@ typedef struct VkClearRect { uint32_t layerCount; } VkClearRect; +typedef struct VkImageBlit { + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffsets[2]; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffsets[2]; +} VkImageBlit; + +typedef struct VkImageCopy { + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffset; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffset; + VkExtent3D extent; +} VkImageCopy; + typedef struct VkImageResolve { VkImageSubresourceLayers srcSubresource; VkOffset3D srcOffset; @@ -3012,38 +3129,6 @@ typedef struct VkImageResolve { VkExtent3D extent; } VkImageResolve; -typedef struct VkMemoryBarrier { - VkStructureType sType; - const void* pNext; - VkAccessFlags srcAccessMask; - VkAccessFlags dstAccessMask; -} VkMemoryBarrier; - -typedef struct VkBufferMemoryBarrier { - VkStructureType sType; - const void* pNext; - VkAccessFlags srcAccessMask; - VkAccessFlags dstAccessMask; - uint32_t srcQueueFamilyIndex; - uint32_t dstQueueFamilyIndex; - VkBuffer buffer; - VkDeviceSize offset; - VkDeviceSize size; -} VkBufferMemoryBarrier; - -typedef struct VkImageMemoryBarrier { - VkStructureType sType; - const void* pNext; - VkAccessFlags srcAccessMask; - VkAccessFlags dstAccessMask; - VkImageLayout oldLayout; - VkImageLayout newLayout; - uint32_t srcQueueFamilyIndex; - uint32_t dstQueueFamilyIndex; - VkImage image; - VkImageSubresourceRange subresourceRange; -} VkImageMemoryBarrier; - typedef struct VkRenderPassBeginInfo { VkStructureType sType; const void* pNext; @@ -3054,37 +3139,6 @@ typedef struct VkRenderPassBeginInfo { const VkClearValue* pClearValues; } VkRenderPassBeginInfo; -typedef struct VkDispatchIndirectCommand { - uint32_t x; - uint32_t y; - uint32_t z; -} VkDispatchIndirectCommand; - -typedef struct VkDrawIndexedIndirectCommand { - uint32_t indexCount; - uint32_t instanceCount; - uint32_t firstIndex; - int32_t vertexOffset; - uint32_t firstInstance; -} VkDrawIndexedIndirectCommand; - -typedef struct VkDrawIndirectCommand { - uint32_t vertexCount; - uint32_t instanceCount; - uint32_t firstVertex; - uint32_t firstInstance; -} VkDrawIndirectCommand; - -typedef struct VkBaseOutStructure { - VkStructureType sType; - struct VkBaseOutStructure* pNext; -} VkBaseOutStructure; - -typedef struct VkBaseInStructure { - VkStructureType sType; - const struct VkBaseInStructure* pNext; -} VkBaseInStructure; - typedef VkResult (VKAPI_PTR *PFN_vkCreateInstance)(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance); typedef void (VKAPI_PTR *PFN_vkDestroyInstance)(VkInstance instance, const VkAllocationCallbacks* pAllocator); typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDevices)(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices); @@ -4038,9 +4092,6 @@ typedef enum VkPointClippingBehavior { VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY = 1, VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES, VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY_KHR = VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY, - VK_POINT_CLIPPING_BEHAVIOR_BEGIN_RANGE = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES, - VK_POINT_CLIPPING_BEHAVIOR_END_RANGE = VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY, - VK_POINT_CLIPPING_BEHAVIOR_RANGE_SIZE = (VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY - VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES + 1), VK_POINT_CLIPPING_BEHAVIOR_MAX_ENUM = 0x7FFFFFFF } VkPointClippingBehavior; @@ -4049,9 +4100,6 @@ typedef enum VkTessellationDomainOrigin { VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT = 1, VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT_KHR = VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT, VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT_KHR = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT, - VK_TESSELLATION_DOMAIN_ORIGIN_BEGIN_RANGE = VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT, - VK_TESSELLATION_DOMAIN_ORIGIN_END_RANGE = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT, - VK_TESSELLATION_DOMAIN_ORIGIN_RANGE_SIZE = (VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT - VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT + 1), VK_TESSELLATION_DOMAIN_ORIGIN_MAX_ENUM = 0x7FFFFFFF } VkTessellationDomainOrigin; @@ -4066,9 +4114,6 @@ typedef enum VkSamplerYcbcrModelConversion { VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709, VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601, VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020, - VK_SAMPLER_YCBCR_MODEL_CONVERSION_BEGIN_RANGE = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY, - VK_SAMPLER_YCBCR_MODEL_CONVERSION_END_RANGE = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020, - VK_SAMPLER_YCBCR_MODEL_CONVERSION_RANGE_SIZE = (VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020 - VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY + 1), VK_SAMPLER_YCBCR_MODEL_CONVERSION_MAX_ENUM = 0x7FFFFFFF } VkSamplerYcbcrModelConversion; @@ -4077,9 +4122,6 @@ typedef enum VkSamplerYcbcrRange { VK_SAMPLER_YCBCR_RANGE_ITU_NARROW = 1, VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR = VK_SAMPLER_YCBCR_RANGE_ITU_FULL, VK_SAMPLER_YCBCR_RANGE_ITU_NARROW_KHR = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW, - VK_SAMPLER_YCBCR_RANGE_BEGIN_RANGE = VK_SAMPLER_YCBCR_RANGE_ITU_FULL, - VK_SAMPLER_YCBCR_RANGE_END_RANGE = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW, - VK_SAMPLER_YCBCR_RANGE_RANGE_SIZE = (VK_SAMPLER_YCBCR_RANGE_ITU_NARROW - VK_SAMPLER_YCBCR_RANGE_ITU_FULL + 1), VK_SAMPLER_YCBCR_RANGE_MAX_ENUM = 0x7FFFFFFF } VkSamplerYcbcrRange; @@ -4088,9 +4130,6 @@ typedef enum VkChromaLocation { VK_CHROMA_LOCATION_MIDPOINT = 1, VK_CHROMA_LOCATION_COSITED_EVEN_KHR = VK_CHROMA_LOCATION_COSITED_EVEN, VK_CHROMA_LOCATION_MIDPOINT_KHR = VK_CHROMA_LOCATION_MIDPOINT, - VK_CHROMA_LOCATION_BEGIN_RANGE = VK_CHROMA_LOCATION_COSITED_EVEN, - VK_CHROMA_LOCATION_END_RANGE = VK_CHROMA_LOCATION_MIDPOINT, - VK_CHROMA_LOCATION_RANGE_SIZE = (VK_CHROMA_LOCATION_MIDPOINT - VK_CHROMA_LOCATION_COSITED_EVEN + 1), VK_CHROMA_LOCATION_MAX_ENUM = 0x7FFFFFFF } VkChromaLocation; @@ -4098,9 +4137,6 @@ typedef enum VkDescriptorUpdateTemplateType { VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET = 0, VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR = 1, VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET, - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_BEGIN_RANGE = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET, - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_END_RANGE = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET, - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_RANGE_SIZE = (VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET + 1), VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_MAX_ENUM = 0x7FFFFFFF } VkDescriptorUpdateTemplateType; @@ -4220,6 +4256,7 @@ typedef enum VkExternalSemaphoreHandleTypeFlagBits { VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0x00000004, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT = 0x00000008, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT = 0x00000010, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D11_FENCE_BIT = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, @@ -4379,8 +4416,6 @@ typedef struct VkMemoryRequirements2 { VkMemoryRequirements memoryRequirements; } VkMemoryRequirements2; -typedef VkMemoryRequirements2 VkMemoryRequirements2KHR; - typedef struct VkSparseImageMemoryRequirements2 { VkStructureType sType; void* pNext; @@ -4908,7 +4943,6 @@ VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSupport( // Vulkan 1.2 version number #define VK_API_VERSION_1_2 VK_MAKE_VERSION(1, 2, 0)// Patch version should always be set to 0 -typedef uint64_t VkDeviceAddress; #define VK_MAX_DRIVER_NAME_SIZE 256 #define VK_MAX_DRIVER_INFO_SIZE 256 @@ -4925,6 +4959,8 @@ typedef enum VkDriverId { VK_DRIVER_ID_GOOGLE_SWIFTSHADER = 10, VK_DRIVER_ID_GGP_PROPRIETARY = 11, VK_DRIVER_ID_BROADCOM_PROPRIETARY = 12, + VK_DRIVER_ID_MESA_LLVMPIPE = 13, + VK_DRIVER_ID_MOLTENVK = 14, VK_DRIVER_ID_AMD_PROPRIETARY_KHR = VK_DRIVER_ID_AMD_PROPRIETARY, VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR = VK_DRIVER_ID_AMD_OPEN_SOURCE, VK_DRIVER_ID_MESA_RADV_KHR = VK_DRIVER_ID_MESA_RADV, @@ -4937,9 +4973,6 @@ typedef enum VkDriverId { VK_DRIVER_ID_GOOGLE_SWIFTSHADER_KHR = VK_DRIVER_ID_GOOGLE_SWIFTSHADER, VK_DRIVER_ID_GGP_PROPRIETARY_KHR = VK_DRIVER_ID_GGP_PROPRIETARY, VK_DRIVER_ID_BROADCOM_PROPRIETARY_KHR = VK_DRIVER_ID_BROADCOM_PROPRIETARY, - VK_DRIVER_ID_BEGIN_RANGE = VK_DRIVER_ID_AMD_PROPRIETARY, - VK_DRIVER_ID_END_RANGE = VK_DRIVER_ID_BROADCOM_PROPRIETARY, - VK_DRIVER_ID_RANGE_SIZE = (VK_DRIVER_ID_BROADCOM_PROPRIETARY - VK_DRIVER_ID_AMD_PROPRIETARY + 1), VK_DRIVER_ID_MAX_ENUM = 0x7FFFFFFF } VkDriverId; @@ -4950,9 +4983,6 @@ typedef enum VkShaderFloatControlsIndependence { VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY_KHR = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY, VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL_KHR = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL, VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE_KHR = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE, - VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_BEGIN_RANGE = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY, - VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_END_RANGE = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE, - VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_RANGE_SIZE = (VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE - VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY + 1), VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_MAX_ENUM = 0x7FFFFFFF } VkShaderFloatControlsIndependence; @@ -4963,9 +4993,6 @@ typedef enum VkSamplerReductionMode { VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT = VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE, VK_SAMPLER_REDUCTION_MODE_MIN_EXT = VK_SAMPLER_REDUCTION_MODE_MIN, VK_SAMPLER_REDUCTION_MODE_MAX_EXT = VK_SAMPLER_REDUCTION_MODE_MAX, - VK_SAMPLER_REDUCTION_MODE_BEGIN_RANGE = VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE, - VK_SAMPLER_REDUCTION_MODE_END_RANGE = VK_SAMPLER_REDUCTION_MODE_MAX, - VK_SAMPLER_REDUCTION_MODE_RANGE_SIZE = (VK_SAMPLER_REDUCTION_MODE_MAX - VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE + 1), VK_SAMPLER_REDUCTION_MODE_MAX_ENUM = 0x7FFFFFFF } VkSamplerReductionMode; @@ -4974,9 +5001,6 @@ typedef enum VkSemaphoreType { VK_SEMAPHORE_TYPE_TIMELINE = 1, VK_SEMAPHORE_TYPE_BINARY_KHR = VK_SEMAPHORE_TYPE_BINARY, VK_SEMAPHORE_TYPE_TIMELINE_KHR = VK_SEMAPHORE_TYPE_TIMELINE, - VK_SEMAPHORE_TYPE_BEGIN_RANGE = VK_SEMAPHORE_TYPE_BINARY, - VK_SEMAPHORE_TYPE_END_RANGE = VK_SEMAPHORE_TYPE_TIMELINE, - VK_SEMAPHORE_TYPE_RANGE_SIZE = (VK_SEMAPHORE_TYPE_TIMELINE - VK_SEMAPHORE_TYPE_BINARY + 1), VK_SEMAPHORE_TYPE_MAX_ENUM = 0x7FFFFFFF } VkSemaphoreType; @@ -5663,6 +5687,16 @@ VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR) #define VK_KHR_SURFACE_SPEC_VERSION 25 #define VK_KHR_SURFACE_EXTENSION_NAME "VK_KHR_surface" +typedef enum VkPresentModeKHR { + VK_PRESENT_MODE_IMMEDIATE_KHR = 0, + VK_PRESENT_MODE_MAILBOX_KHR = 1, + VK_PRESENT_MODE_FIFO_KHR = 2, + VK_PRESENT_MODE_FIFO_RELAXED_KHR = 3, + VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR = 1000111000, + VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR = 1000111001, + VK_PRESENT_MODE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPresentModeKHR; + typedef enum VkColorSpaceKHR { VK_COLOR_SPACE_SRGB_NONLINEAR_KHR = 0, VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT = 1000104001, @@ -5682,25 +5716,9 @@ typedef enum VkColorSpaceKHR { VK_COLOR_SPACE_DISPLAY_NATIVE_AMD = 1000213000, VK_COLORSPACE_SRGB_NONLINEAR_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, VK_COLOR_SPACE_DCI_P3_LINEAR_EXT = VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT, - VK_COLOR_SPACE_BEGIN_RANGE_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, - VK_COLOR_SPACE_END_RANGE_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, - VK_COLOR_SPACE_RANGE_SIZE_KHR = (VK_COLOR_SPACE_SRGB_NONLINEAR_KHR - VK_COLOR_SPACE_SRGB_NONLINEAR_KHR + 1), VK_COLOR_SPACE_MAX_ENUM_KHR = 0x7FFFFFFF } VkColorSpaceKHR; -typedef enum VkPresentModeKHR { - VK_PRESENT_MODE_IMMEDIATE_KHR = 0, - VK_PRESENT_MODE_MAILBOX_KHR = 1, - VK_PRESENT_MODE_FIFO_KHR = 2, - VK_PRESENT_MODE_FIFO_RELAXED_KHR = 3, - VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR = 1000111000, - VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR = 1000111001, - VK_PRESENT_MODE_BEGIN_RANGE_KHR = VK_PRESENT_MODE_IMMEDIATE_KHR, - VK_PRESENT_MODE_END_RANGE_KHR = VK_PRESENT_MODE_FIFO_RELAXED_KHR, - VK_PRESENT_MODE_RANGE_SIZE_KHR = (VK_PRESENT_MODE_FIFO_RELAXED_KHR - VK_PRESENT_MODE_IMMEDIATE_KHR + 1), - VK_PRESENT_MODE_MAX_ENUM_KHR = 0x7FFFFFFF -} VkPresentModeKHR; - typedef enum VkSurfaceTransformFlagBitsKHR { VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR = 0x00000001, VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR = 0x00000002, @@ -5713,7 +5731,6 @@ typedef enum VkSurfaceTransformFlagBitsKHR { VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR = 0x00000100, VK_SURFACE_TRANSFORM_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkSurfaceTransformFlagBitsKHR; -typedef VkFlags VkSurfaceTransformFlagsKHR; typedef enum VkCompositeAlphaFlagBitsKHR { VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR = 0x00000001, @@ -5723,6 +5740,7 @@ typedef enum VkCompositeAlphaFlagBitsKHR { VK_COMPOSITE_ALPHA_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkCompositeAlphaFlagBitsKHR; typedef VkFlags VkCompositeAlphaFlagsKHR; +typedef VkFlags VkSurfaceTransformFlagsKHR; typedef struct VkSurfaceCapabilitiesKHR { uint32_t minImageCount; uint32_t maxImageCount; @@ -5942,6 +5960,7 @@ VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayKHR) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayModeKHR) #define VK_KHR_DISPLAY_SPEC_VERSION 23 #define VK_KHR_DISPLAY_EXTENSION_NAME "VK_KHR_display" +typedef VkFlags VkDisplayModeCreateFlagsKHR; typedef enum VkDisplayPlaneAlphaFlagBitsKHR { VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR = 0x00000001, @@ -5951,28 +5970,12 @@ typedef enum VkDisplayPlaneAlphaFlagBitsKHR { VK_DISPLAY_PLANE_ALPHA_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkDisplayPlaneAlphaFlagBitsKHR; typedef VkFlags VkDisplayPlaneAlphaFlagsKHR; -typedef VkFlags VkDisplayModeCreateFlagsKHR; typedef VkFlags VkDisplaySurfaceCreateFlagsKHR; -typedef struct VkDisplayPropertiesKHR { - VkDisplayKHR display; - const char* displayName; - VkExtent2D physicalDimensions; - VkExtent2D physicalResolution; - VkSurfaceTransformFlagsKHR supportedTransforms; - VkBool32 planeReorderPossible; - VkBool32 persistentContent; -} VkDisplayPropertiesKHR; - typedef struct VkDisplayModeParametersKHR { VkExtent2D visibleRegion; uint32_t refreshRate; } VkDisplayModeParametersKHR; -typedef struct VkDisplayModePropertiesKHR { - VkDisplayModeKHR displayMode; - VkDisplayModeParametersKHR parameters; -} VkDisplayModePropertiesKHR; - typedef struct VkDisplayModeCreateInfoKHR { VkStructureType sType; const void* pNext; @@ -5980,6 +5983,11 @@ typedef struct VkDisplayModeCreateInfoKHR { VkDisplayModeParametersKHR parameters; } VkDisplayModeCreateInfoKHR; +typedef struct VkDisplayModePropertiesKHR { + VkDisplayModeKHR displayMode; + VkDisplayModeParametersKHR parameters; +} VkDisplayModePropertiesKHR; + typedef struct VkDisplayPlaneCapabilitiesKHR { VkDisplayPlaneAlphaFlagsKHR supportedAlpha; VkOffset2D minSrcPosition; @@ -5997,6 +6005,16 @@ typedef struct VkDisplayPlanePropertiesKHR { uint32_t currentStackIndex; } VkDisplayPlanePropertiesKHR; +typedef struct VkDisplayPropertiesKHR { + VkDisplayKHR display; + const char* displayName; + VkExtent2D physicalDimensions; + VkExtent2D physicalResolution; + VkSurfaceTransformFlagsKHR supportedTransforms; + VkBool32 planeReorderPossible; + VkBool32 persistentContent; +} VkDisplayPropertiesKHR; + typedef struct VkDisplaySurfaceCreateInfoKHR { VkStructureType sType; const void* pNext; @@ -6680,9 +6698,6 @@ typedef enum VkPerformanceCounterUnitKHR { VK_PERFORMANCE_COUNTER_UNIT_AMPS_KHR = 8, VK_PERFORMANCE_COUNTER_UNIT_HERTZ_KHR = 9, VK_PERFORMANCE_COUNTER_UNIT_CYCLES_KHR = 10, - VK_PERFORMANCE_COUNTER_UNIT_BEGIN_RANGE_KHR = VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR, - VK_PERFORMANCE_COUNTER_UNIT_END_RANGE_KHR = VK_PERFORMANCE_COUNTER_UNIT_CYCLES_KHR, - VK_PERFORMANCE_COUNTER_UNIT_RANGE_SIZE_KHR = (VK_PERFORMANCE_COUNTER_UNIT_CYCLES_KHR - VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR + 1), VK_PERFORMANCE_COUNTER_UNIT_MAX_ENUM_KHR = 0x7FFFFFFF } VkPerformanceCounterUnitKHR; @@ -6693,9 +6708,6 @@ typedef enum VkPerformanceCounterScopeKHR { VK_QUERY_SCOPE_COMMAND_BUFFER_KHR = VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR, VK_QUERY_SCOPE_RENDER_PASS_KHR = VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR, VK_QUERY_SCOPE_COMMAND_KHR = VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR, - VK_PERFORMANCE_COUNTER_SCOPE_BEGIN_RANGE_KHR = VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR, - VK_PERFORMANCE_COUNTER_SCOPE_END_RANGE_KHR = VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR, - VK_PERFORMANCE_COUNTER_SCOPE_RANGE_SIZE_KHR = (VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR - VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR + 1), VK_PERFORMANCE_COUNTER_SCOPE_MAX_ENUM_KHR = 0x7FFFFFFF } VkPerformanceCounterScopeKHR; @@ -6706,15 +6718,14 @@ typedef enum VkPerformanceCounterStorageKHR { VK_PERFORMANCE_COUNTER_STORAGE_UINT64_KHR = 3, VK_PERFORMANCE_COUNTER_STORAGE_FLOAT32_KHR = 4, VK_PERFORMANCE_COUNTER_STORAGE_FLOAT64_KHR = 5, - VK_PERFORMANCE_COUNTER_STORAGE_BEGIN_RANGE_KHR = VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR, - VK_PERFORMANCE_COUNTER_STORAGE_END_RANGE_KHR = VK_PERFORMANCE_COUNTER_STORAGE_FLOAT64_KHR, - VK_PERFORMANCE_COUNTER_STORAGE_RANGE_SIZE_KHR = (VK_PERFORMANCE_COUNTER_STORAGE_FLOAT64_KHR - VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR + 1), VK_PERFORMANCE_COUNTER_STORAGE_MAX_ENUM_KHR = 0x7FFFFFFF } VkPerformanceCounterStorageKHR; typedef enum VkPerformanceCounterDescriptionFlagBitsKHR { - VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_KHR = 0x00000001, - VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_KHR = 0x00000002, + VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_BIT_KHR = 0x00000001, + VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_BIT_KHR = 0x00000002, + VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_KHR = VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_BIT_KHR, + VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_KHR = VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_BIT_KHR, VK_PERFORMANCE_COUNTER_DESCRIPTION_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkPerformanceCounterDescriptionFlagBitsKHR; typedef VkFlags VkPerformanceCounterDescriptionFlagsKHR; @@ -6968,6 +6979,8 @@ typedef VkImageMemoryRequirementsInfo2 VkImageMemoryRequirementsInfo2KHR; typedef VkImageSparseMemoryRequirementsInfo2 VkImageSparseMemoryRequirementsInfo2KHR; +typedef VkMemoryRequirements2 VkMemoryRequirements2KHR; + typedef VkSparseImageMemoryRequirements2 VkSparseImageMemoryRequirements2KHR; typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements2KHR)(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements); @@ -7229,6 +7242,96 @@ typedef VkPhysicalDeviceVulkanMemoryModelFeatures VkPhysicalDeviceVulkanMemoryMo +#define VK_KHR_shader_terminate_invocation 1 +#define VK_KHR_SHADER_TERMINATE_INVOCATION_SPEC_VERSION 1 +#define VK_KHR_SHADER_TERMINATE_INVOCATION_EXTENSION_NAME "VK_KHR_shader_terminate_invocation" +typedef struct VkPhysicalDeviceShaderTerminateInvocationFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderTerminateInvocation; +} VkPhysicalDeviceShaderTerminateInvocationFeaturesKHR; + + + +#define VK_KHR_fragment_shading_rate 1 +#define VK_KHR_FRAGMENT_SHADING_RATE_SPEC_VERSION 1 +#define VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME "VK_KHR_fragment_shading_rate" + +typedef enum VkFragmentShadingRateCombinerOpKHR { + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR = 0, + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR = 1, + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_KHR = 2, + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR = 3, + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR = 4, + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_ENUM_KHR = 0x7FFFFFFF +} VkFragmentShadingRateCombinerOpKHR; +typedef struct VkFragmentShadingRateAttachmentInfoKHR { + VkStructureType sType; + const void* pNext; + const VkAttachmentReference2* pFragmentShadingRateAttachment; + VkExtent2D shadingRateAttachmentTexelSize; +} VkFragmentShadingRateAttachmentInfoKHR; + +typedef struct VkPipelineFragmentShadingRateStateCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkExtent2D fragmentSize; + VkFragmentShadingRateCombinerOpKHR combinerOps[2]; +} VkPipelineFragmentShadingRateStateCreateInfoKHR; + +typedef struct VkPhysicalDeviceFragmentShadingRateFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 pipelineFragmentShadingRate; + VkBool32 primitiveFragmentShadingRate; + VkBool32 attachmentFragmentShadingRate; +} VkPhysicalDeviceFragmentShadingRateFeaturesKHR; + +typedef struct VkPhysicalDeviceFragmentShadingRatePropertiesKHR { + VkStructureType sType; + void* pNext; + VkExtent2D minFragmentShadingRateAttachmentTexelSize; + VkExtent2D maxFragmentShadingRateAttachmentTexelSize; + uint32_t maxFragmentShadingRateAttachmentTexelSizeAspectRatio; + VkBool32 primitiveFragmentShadingRateWithMultipleViewports; + VkBool32 layeredShadingRateAttachments; + VkBool32 fragmentShadingRateNonTrivialCombinerOps; + VkExtent2D maxFragmentSize; + uint32_t maxFragmentSizeAspectRatio; + uint32_t maxFragmentShadingRateCoverageSamples; + VkSampleCountFlagBits maxFragmentShadingRateRasterizationSamples; + VkBool32 fragmentShadingRateWithShaderDepthStencilWrites; + VkBool32 fragmentShadingRateWithSampleMask; + VkBool32 fragmentShadingRateWithShaderSampleMask; + VkBool32 fragmentShadingRateWithConservativeRasterization; + VkBool32 fragmentShadingRateWithFragmentShaderInterlock; + VkBool32 fragmentShadingRateWithCustomSampleLocations; + VkBool32 fragmentShadingRateStrictMultiplyCombiner; +} VkPhysicalDeviceFragmentShadingRatePropertiesKHR; + +typedef struct VkPhysicalDeviceFragmentShadingRateKHR { + VkStructureType sType; + void* pNext; + VkSampleCountFlags sampleCounts; + VkExtent2D fragmentSize; +} VkPhysicalDeviceFragmentShadingRateKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceFragmentShadingRatesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pFragmentShadingRateCount, VkPhysicalDeviceFragmentShadingRateKHR* pFragmentShadingRates); +typedef void (VKAPI_PTR *PFN_vkCmdSetFragmentShadingRateKHR)(VkCommandBuffer commandBuffer, const VkExtent2D* pFragmentSize, const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceFragmentShadingRatesKHR( + VkPhysicalDevice physicalDevice, + uint32_t* pFragmentShadingRateCount, + VkPhysicalDeviceFragmentShadingRateKHR* pFragmentShadingRates); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetFragmentShadingRateKHR( + VkCommandBuffer commandBuffer, + const VkExtent2D* pFragmentSize, + const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); +#endif + + #define VK_KHR_spirv_1_4 1 #define VK_KHR_SPIRV_1_4_SPEC_VERSION 1 #define VK_KHR_SPIRV_1_4_EXTENSION_NAME "VK_KHR_spirv_1_4" @@ -7295,6 +7398,41 @@ VKAPI_ATTR uint64_t VKAPI_CALL vkGetDeviceMemoryOpaqueCaptureAddressKHR( #endif +#define VK_KHR_deferred_host_operations 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDeferredOperationKHR) +#define VK_KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION 4 +#define VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME "VK_KHR_deferred_host_operations" +typedef VkResult (VKAPI_PTR *PFN_vkCreateDeferredOperationKHR)(VkDevice device, const VkAllocationCallbacks* pAllocator, VkDeferredOperationKHR* pDeferredOperation); +typedef void (VKAPI_PTR *PFN_vkDestroyDeferredOperationKHR)(VkDevice device, VkDeferredOperationKHR operation, const VkAllocationCallbacks* pAllocator); +typedef uint32_t (VKAPI_PTR *PFN_vkGetDeferredOperationMaxConcurrencyKHR)(VkDevice device, VkDeferredOperationKHR operation); +typedef VkResult (VKAPI_PTR *PFN_vkGetDeferredOperationResultKHR)(VkDevice device, VkDeferredOperationKHR operation); +typedef VkResult (VKAPI_PTR *PFN_vkDeferredOperationJoinKHR)(VkDevice device, VkDeferredOperationKHR operation); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDeferredOperationKHR( + VkDevice device, + const VkAllocationCallbacks* pAllocator, + VkDeferredOperationKHR* pDeferredOperation); + +VKAPI_ATTR void VKAPI_CALL vkDestroyDeferredOperationKHR( + VkDevice device, + VkDeferredOperationKHR operation, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR uint32_t VKAPI_CALL vkGetDeferredOperationMaxConcurrencyKHR( + VkDevice device, + VkDeferredOperationKHR operation); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeferredOperationResultKHR( + VkDevice device, + VkDeferredOperationKHR operation); + +VKAPI_ATTR VkResult VKAPI_CALL vkDeferredOperationJoinKHR( + VkDevice device, + VkDeferredOperationKHR operation); +#endif + + #define VK_KHR_pipeline_executable_properties 1 #define VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_SPEC_VERSION 1 #define VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME "VK_KHR_pipeline_executable_properties" @@ -7304,9 +7442,6 @@ typedef enum VkPipelineExecutableStatisticFormatKHR { VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR = 1, VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR = 2, VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR = 3, - VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BEGIN_RANGE_KHR = VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR, - VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_END_RANGE_KHR = VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR, - VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_RANGE_SIZE_KHR = (VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR - VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR + 1), VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_MAX_ENUM_KHR = 0x7FFFFFFF } VkPipelineExecutableStatisticFormatKHR; typedef struct VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR { @@ -7388,11 +7523,440 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineExecutableInternalRepresentationsKHR #endif +#define VK_KHR_pipeline_library 1 +#define VK_KHR_PIPELINE_LIBRARY_SPEC_VERSION 1 +#define VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME "VK_KHR_pipeline_library" +typedef struct VkPipelineLibraryCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t libraryCount; + const VkPipeline* pLibraries; +} VkPipelineLibraryCreateInfoKHR; + + + #define VK_KHR_shader_non_semantic_info 1 #define VK_KHR_SHADER_NON_SEMANTIC_INFO_SPEC_VERSION 1 #define VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME "VK_KHR_shader_non_semantic_info" +#define VK_KHR_synchronization2 1 +typedef uint64_t VkFlags64; +#define VK_KHR_SYNCHRONIZATION_2_SPEC_VERSION 1 +#define VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME "VK_KHR_synchronization2" +typedef VkFlags64 VkPipelineStageFlags2KHR; + +// Flag bits for VkPipelineStageFlags2KHR +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_NONE_KHR = 0; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR = 0x00000001; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT_KHR = 0x00000002; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT_KHR = 0x00000004; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT_KHR = 0x00000008; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT_KHR = 0x00000010; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT_KHR = 0x00000020; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT_KHR = 0x00000040; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR = 0x00000080; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT_KHR = 0x00000100; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR = 0x00000200; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR = 0x00000400; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT_KHR = 0x00000800; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT_KHR = 0x00001000; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR = 0x00001000; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR = 0x00002000; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_HOST_BIT_KHR = 0x00004000; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT_KHR = 0x00008000; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR = 0x00010000; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_COPY_BIT_KHR = 0x100000000ULL; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_RESOLVE_BIT_KHR = 0x200000000ULL; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_BLIT_BIT_KHR = 0x400000000ULL; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_CLEAR_BIT_KHR = 0x800000000ULL; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT_KHR = 0x1000000000ULL; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT_KHR = 0x2000000000ULL; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT_KHR = 0x4000000000ULL; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT = 0x01000000; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT = 0x00040000; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV = 0x00020000; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00400000; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_SHADING_RATE_IMAGE_BIT_NV = 0x00400000; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR = 0x02000000; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR = 0x00200000; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_NV = 0x00200000; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_NV = 0x02000000; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0x00800000; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_NV = 0x00080000; +static const VkPipelineStageFlags2KHR VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_NV = 0x00100000; + +typedef VkFlags64 VkAccessFlags2KHR; + +// Flag bits for VkAccessFlags2KHR +static const VkAccessFlags2KHR VK_ACCESS_2_NONE_KHR = 0; +static const VkAccessFlags2KHR VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT_KHR = 0x00000001; +static const VkAccessFlags2KHR VK_ACCESS_2_INDEX_READ_BIT_KHR = 0x00000002; +static const VkAccessFlags2KHR VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT_KHR = 0x00000004; +static const VkAccessFlags2KHR VK_ACCESS_2_UNIFORM_READ_BIT_KHR = 0x00000008; +static const VkAccessFlags2KHR VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT_KHR = 0x00000010; +static const VkAccessFlags2KHR VK_ACCESS_2_SHADER_READ_BIT_KHR = 0x00000020; +static const VkAccessFlags2KHR VK_ACCESS_2_SHADER_WRITE_BIT_KHR = 0x00000040; +static const VkAccessFlags2KHR VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT_KHR = 0x00000080; +static const VkAccessFlags2KHR VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR = 0x00000100; +static const VkAccessFlags2KHR VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT_KHR = 0x00000200; +static const VkAccessFlags2KHR VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR = 0x00000400; +static const VkAccessFlags2KHR VK_ACCESS_2_TRANSFER_READ_BIT_KHR = 0x00000800; +static const VkAccessFlags2KHR VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR = 0x00001000; +static const VkAccessFlags2KHR VK_ACCESS_2_HOST_READ_BIT_KHR = 0x00002000; +static const VkAccessFlags2KHR VK_ACCESS_2_HOST_WRITE_BIT_KHR = 0x00004000; +static const VkAccessFlags2KHR VK_ACCESS_2_MEMORY_READ_BIT_KHR = 0x00008000; +static const VkAccessFlags2KHR VK_ACCESS_2_MEMORY_WRITE_BIT_KHR = 0x00010000; +static const VkAccessFlags2KHR VK_ACCESS_2_SHADER_SAMPLED_READ_BIT_KHR = 0x100000000ULL; +static const VkAccessFlags2KHR VK_ACCESS_2_SHADER_STORAGE_READ_BIT_KHR = 0x200000000ULL; +static const VkAccessFlags2KHR VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT_KHR = 0x400000000ULL; +static const VkAccessFlags2KHR VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT = 0x02000000; +static const VkAccessFlags2KHR VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0x04000000; +static const VkAccessFlags2KHR VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0x08000000; +static const VkAccessFlags2KHR VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT = 0x00100000; +static const VkAccessFlags2KHR VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_NV = 0x00020000; +static const VkAccessFlags2KHR VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_NV = 0x00040000; +static const VkAccessFlags2KHR VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR = 0x00800000; +static const VkAccessFlags2KHR VK_ACCESS_2_SHADING_RATE_IMAGE_READ_BIT_NV = 0x00800000; +static const VkAccessFlags2KHR VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR = 0x00200000; +static const VkAccessFlags2KHR VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR = 0x00400000; +static const VkAccessFlags2KHR VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_NV = 0x00200000; +static const VkAccessFlags2KHR VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_NV = 0x00400000; +static const VkAccessFlags2KHR VK_ACCESS_2_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0x01000000; +static const VkAccessFlags2KHR VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000; + + +typedef enum VkSubmitFlagBitsKHR { + VK_SUBMIT_PROTECTED_BIT_KHR = 0x00000001, + VK_SUBMIT_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkSubmitFlagBitsKHR; +typedef VkFlags VkSubmitFlagsKHR; +typedef struct VkMemoryBarrier2KHR { + VkStructureType sType; + const void* pNext; + VkPipelineStageFlags2KHR srcStageMask; + VkAccessFlags2KHR srcAccessMask; + VkPipelineStageFlags2KHR dstStageMask; + VkAccessFlags2KHR dstAccessMask; +} VkMemoryBarrier2KHR; + +typedef struct VkBufferMemoryBarrier2KHR { + VkStructureType sType; + const void* pNext; + VkPipelineStageFlags2KHR srcStageMask; + VkAccessFlags2KHR srcAccessMask; + VkPipelineStageFlags2KHR dstStageMask; + VkAccessFlags2KHR dstAccessMask; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkBuffer buffer; + VkDeviceSize offset; + VkDeviceSize size; +} VkBufferMemoryBarrier2KHR; + +typedef struct VkImageMemoryBarrier2KHR { + VkStructureType sType; + const void* pNext; + VkPipelineStageFlags2KHR srcStageMask; + VkAccessFlags2KHR srcAccessMask; + VkPipelineStageFlags2KHR dstStageMask; + VkAccessFlags2KHR dstAccessMask; + VkImageLayout oldLayout; + VkImageLayout newLayout; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkImage image; + VkImageSubresourceRange subresourceRange; +} VkImageMemoryBarrier2KHR; + +typedef struct VkDependencyInfoKHR { + VkStructureType sType; + const void* pNext; + VkDependencyFlags dependencyFlags; + uint32_t memoryBarrierCount; + const VkMemoryBarrier2KHR* pMemoryBarriers; + uint32_t bufferMemoryBarrierCount; + const VkBufferMemoryBarrier2KHR* pBufferMemoryBarriers; + uint32_t imageMemoryBarrierCount; + const VkImageMemoryBarrier2KHR* pImageMemoryBarriers; +} VkDependencyInfoKHR; + +typedef struct VkSemaphoreSubmitInfoKHR { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + uint64_t value; + VkPipelineStageFlags2KHR stageMask; + uint32_t deviceIndex; +} VkSemaphoreSubmitInfoKHR; + +typedef struct VkCommandBufferSubmitInfoKHR { + VkStructureType sType; + const void* pNext; + VkCommandBuffer commandBuffer; + uint32_t deviceMask; +} VkCommandBufferSubmitInfoKHR; + +typedef struct VkSubmitInfo2KHR { + VkStructureType sType; + const void* pNext; + VkSubmitFlagsKHR flags; + uint32_t waitSemaphoreInfoCount; + const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos; + uint32_t commandBufferInfoCount; + const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos; + uint32_t signalSemaphoreInfoCount; + const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos; +} VkSubmitInfo2KHR; + +typedef struct VkPhysicalDeviceSynchronization2FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 synchronization2; +} VkPhysicalDeviceSynchronization2FeaturesKHR; + +typedef struct VkQueueFamilyCheckpointProperties2NV { + VkStructureType sType; + void* pNext; + VkPipelineStageFlags2KHR checkpointExecutionStageMask; +} VkQueueFamilyCheckpointProperties2NV; + +typedef struct VkCheckpointData2NV { + VkStructureType sType; + void* pNext; + VkPipelineStageFlags2KHR stage; + void* pCheckpointMarker; +} VkCheckpointData2NV; + +typedef void (VKAPI_PTR *PFN_vkCmdSetEvent2KHR)(VkCommandBuffer commandBuffer, VkEvent event, const VkDependencyInfoKHR* pDependencyInfo); +typedef void (VKAPI_PTR *PFN_vkCmdResetEvent2KHR)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags2KHR stageMask); +typedef void (VKAPI_PTR *PFN_vkCmdWaitEvents2KHR)(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, const VkDependencyInfoKHR* pDependencyInfos); +typedef void (VKAPI_PTR *PFN_vkCmdPipelineBarrier2KHR)(VkCommandBuffer commandBuffer, const VkDependencyInfoKHR* pDependencyInfo); +typedef void (VKAPI_PTR *PFN_vkCmdWriteTimestamp2KHR)(VkCommandBuffer commandBuffer, VkPipelineStageFlags2KHR stage, VkQueryPool queryPool, uint32_t query); +typedef VkResult (VKAPI_PTR *PFN_vkQueueSubmit2KHR)(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2KHR* pSubmits, VkFence fence); +typedef void (VKAPI_PTR *PFN_vkCmdWriteBufferMarker2AMD)(VkCommandBuffer commandBuffer, VkPipelineStageFlags2KHR stage, VkBuffer dstBuffer, VkDeviceSize dstOffset, uint32_t marker); +typedef void (VKAPI_PTR *PFN_vkGetQueueCheckpointData2NV)(VkQueue queue, uint32_t* pCheckpointDataCount, VkCheckpointData2NV* pCheckpointData); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetEvent2KHR( + VkCommandBuffer commandBuffer, + VkEvent event, + const VkDependencyInfoKHR* pDependencyInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdResetEvent2KHR( + VkCommandBuffer commandBuffer, + VkEvent event, + VkPipelineStageFlags2KHR stageMask); + +VKAPI_ATTR void VKAPI_CALL vkCmdWaitEvents2KHR( + VkCommandBuffer commandBuffer, + uint32_t eventCount, + const VkEvent* pEvents, + const VkDependencyInfoKHR* pDependencyInfos); + +VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier2KHR( + VkCommandBuffer commandBuffer, + const VkDependencyInfoKHR* pDependencyInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdWriteTimestamp2KHR( + VkCommandBuffer commandBuffer, + VkPipelineStageFlags2KHR stage, + VkQueryPool queryPool, + uint32_t query); + +VKAPI_ATTR VkResult VKAPI_CALL vkQueueSubmit2KHR( + VkQueue queue, + uint32_t submitCount, + const VkSubmitInfo2KHR* pSubmits, + VkFence fence); + +VKAPI_ATTR void VKAPI_CALL vkCmdWriteBufferMarker2AMD( + VkCommandBuffer commandBuffer, + VkPipelineStageFlags2KHR stage, + VkBuffer dstBuffer, + VkDeviceSize dstOffset, + uint32_t marker); + +VKAPI_ATTR void VKAPI_CALL vkGetQueueCheckpointData2NV( + VkQueue queue, + uint32_t* pCheckpointDataCount, + VkCheckpointData2NV* pCheckpointData); +#endif + + +#define VK_KHR_zero_initialize_workgroup_memory 1 +#define VK_KHR_ZERO_INITIALIZE_WORKGROUP_MEMORY_SPEC_VERSION 1 +#define VK_KHR_ZERO_INITIALIZE_WORKGROUP_MEMORY_EXTENSION_NAME "VK_KHR_zero_initialize_workgroup_memory" +typedef struct VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderZeroInitializeWorkgroupMemory; +} VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeaturesKHR; + + + +#define VK_KHR_workgroup_memory_explicit_layout 1 +#define VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_SPEC_VERSION 1 +#define VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME "VK_KHR_workgroup_memory_explicit_layout" +typedef struct VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 workgroupMemoryExplicitLayout; + VkBool32 workgroupMemoryExplicitLayoutScalarBlockLayout; + VkBool32 workgroupMemoryExplicitLayout8BitAccess; + VkBool32 workgroupMemoryExplicitLayout16BitAccess; +} VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR; + + + +#define VK_KHR_copy_commands2 1 +#define VK_KHR_COPY_COMMANDS_2_SPEC_VERSION 1 +#define VK_KHR_COPY_COMMANDS_2_EXTENSION_NAME "VK_KHR_copy_commands2" +typedef struct VkBufferCopy2KHR { + VkStructureType sType; + const void* pNext; + VkDeviceSize srcOffset; + VkDeviceSize dstOffset; + VkDeviceSize size; +} VkBufferCopy2KHR; + +typedef struct VkCopyBufferInfo2KHR { + VkStructureType sType; + const void* pNext; + VkBuffer srcBuffer; + VkBuffer dstBuffer; + uint32_t regionCount; + const VkBufferCopy2KHR* pRegions; +} VkCopyBufferInfo2KHR; + +typedef struct VkImageCopy2KHR { + VkStructureType sType; + const void* pNext; + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffset; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffset; + VkExtent3D extent; +} VkImageCopy2KHR; + +typedef struct VkCopyImageInfo2KHR { + VkStructureType sType; + const void* pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkImageCopy2KHR* pRegions; +} VkCopyImageInfo2KHR; + +typedef struct VkBufferImageCopy2KHR { + VkStructureType sType; + const void* pNext; + VkDeviceSize bufferOffset; + uint32_t bufferRowLength; + uint32_t bufferImageHeight; + VkImageSubresourceLayers imageSubresource; + VkOffset3D imageOffset; + VkExtent3D imageExtent; +} VkBufferImageCopy2KHR; + +typedef struct VkCopyBufferToImageInfo2KHR { + VkStructureType sType; + const void* pNext; + VkBuffer srcBuffer; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkBufferImageCopy2KHR* pRegions; +} VkCopyBufferToImageInfo2KHR; + +typedef struct VkCopyImageToBufferInfo2KHR { + VkStructureType sType; + const void* pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkBuffer dstBuffer; + uint32_t regionCount; + const VkBufferImageCopy2KHR* pRegions; +} VkCopyImageToBufferInfo2KHR; + +typedef struct VkImageBlit2KHR { + VkStructureType sType; + const void* pNext; + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffsets[2]; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffsets[2]; +} VkImageBlit2KHR; + +typedef struct VkBlitImageInfo2KHR { + VkStructureType sType; + const void* pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkImageBlit2KHR* pRegions; + VkFilter filter; +} VkBlitImageInfo2KHR; + +typedef struct VkImageResolve2KHR { + VkStructureType sType; + const void* pNext; + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffset; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffset; + VkExtent3D extent; +} VkImageResolve2KHR; + +typedef struct VkResolveImageInfo2KHR { + VkStructureType sType; + const void* pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkImageResolve2KHR* pRegions; +} VkResolveImageInfo2KHR; + +typedef void (VKAPI_PTR *PFN_vkCmdCopyBuffer2KHR)(VkCommandBuffer commandBuffer, const VkCopyBufferInfo2KHR* pCopyBufferInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImage2KHR)(VkCommandBuffer commandBuffer, const VkCopyImageInfo2KHR* pCopyImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyBufferToImage2KHR)(VkCommandBuffer commandBuffer, const VkCopyBufferToImageInfo2KHR* pCopyBufferToImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImageToBuffer2KHR)(VkCommandBuffer commandBuffer, const VkCopyImageToBufferInfo2KHR* pCopyImageToBufferInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBlitImage2KHR)(VkCommandBuffer commandBuffer, const VkBlitImageInfo2KHR* pBlitImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdResolveImage2KHR)(VkCommandBuffer commandBuffer, const VkResolveImageInfo2KHR* pResolveImageInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyBuffer2KHR( + VkCommandBuffer commandBuffer, + const VkCopyBufferInfo2KHR* pCopyBufferInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImage2KHR( + VkCommandBuffer commandBuffer, + const VkCopyImageInfo2KHR* pCopyImageInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage2KHR( + VkCommandBuffer commandBuffer, + const VkCopyBufferToImageInfo2KHR* pCopyBufferToImageInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer2KHR( + VkCommandBuffer commandBuffer, + const VkCopyImageToBufferInfo2KHR* pCopyImageToBufferInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdBlitImage2KHR( + VkCommandBuffer commandBuffer, + const VkBlitImageInfo2KHR* pBlitImageInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdResolveImage2KHR( + VkCommandBuffer commandBuffer, + const VkResolveImageInfo2KHR* pResolveImageInfo); +#endif + + #define VK_EXT_debug_report 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT) #define VK_EXT_DEBUG_REPORT_SPEC_VERSION 9 @@ -7430,19 +7994,15 @@ typedef enum VkDebugReportObjectTypeEXT { VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT = 28, VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT = 29, VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT = 30, - VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT = 31, - VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT = 32, VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT = 33, VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT = 1000156000, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT = 1000085000, + VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT = 1000150000, VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT = 1000165000, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT, - VK_DEBUG_REPORT_OBJECT_TYPE_BEGIN_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, - VK_DEBUG_REPORT_OBJECT_TYPE_END_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT, - VK_DEBUG_REPORT_OBJECT_TYPE_RANGE_SIZE_EXT = (VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT - VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT + 1), VK_DEBUG_REPORT_OBJECT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF } VkDebugReportObjectTypeEXT; @@ -7523,9 +8083,6 @@ VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT( typedef enum VkRasterizationOrderAMD { VK_RASTERIZATION_ORDER_STRICT_AMD = 0, VK_RASTERIZATION_ORDER_RELAXED_AMD = 1, - VK_RASTERIZATION_ORDER_BEGIN_RANGE_AMD = VK_RASTERIZATION_ORDER_STRICT_AMD, - VK_RASTERIZATION_ORDER_END_RANGE_AMD = VK_RASTERIZATION_ORDER_RELAXED_AMD, - VK_RASTERIZATION_ORDER_RANGE_SIZE_AMD = (VK_RASTERIZATION_ORDER_RELAXED_AMD - VK_RASTERIZATION_ORDER_STRICT_AMD + 1), VK_RASTERIZATION_ORDER_MAX_ENUM_AMD = 0x7FFFFFFF } VkRasterizationOrderAMD; typedef struct VkPipelineRasterizationStateRasterizationOrderAMD { @@ -7719,7 +8276,7 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectByteCountEXT( #define VK_NVX_image_view_handle 1 -#define VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION 1 +#define VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION 2 #define VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME "VK_NVX_image_view_handle" typedef struct VkImageViewHandleInfoNVX { VkStructureType sType; @@ -7729,12 +8286,25 @@ typedef struct VkImageViewHandleInfoNVX { VkSampler sampler; } VkImageViewHandleInfoNVX; +typedef struct VkImageViewAddressPropertiesNVX { + VkStructureType sType; + void* pNext; + VkDeviceAddress deviceAddress; + VkDeviceSize size; +} VkImageViewAddressPropertiesNVX; + typedef uint32_t (VKAPI_PTR *PFN_vkGetImageViewHandleNVX)(VkDevice device, const VkImageViewHandleInfoNVX* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetImageViewAddressNVX)(VkDevice device, VkImageView imageView, VkImageViewAddressPropertiesNVX* pProperties); #ifndef VK_NO_PROTOTYPES VKAPI_ATTR uint32_t VKAPI_CALL vkGetImageViewHandleNVX( VkDevice device, const VkImageViewHandleInfoNVX* pInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetImageViewAddressNVX( + VkDevice device, + VkImageView imageView, + VkImageViewAddressPropertiesNVX* pProperties); #endif @@ -7799,9 +8369,6 @@ typedef enum VkShaderInfoTypeAMD { VK_SHADER_INFO_TYPE_STATISTICS_AMD = 0, VK_SHADER_INFO_TYPE_BINARY_AMD = 1, VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD = 2, - VK_SHADER_INFO_TYPE_BEGIN_RANGE_AMD = VK_SHADER_INFO_TYPE_STATISTICS_AMD, - VK_SHADER_INFO_TYPE_END_RANGE_AMD = VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD, - VK_SHADER_INFO_TYPE_RANGE_SIZE_AMD = (VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD - VK_SHADER_INFO_TYPE_STATISTICS_AMD + 1), VK_SHADER_INFO_TYPE_MAX_ENUM_AMD = 0x7FFFFFFF } VkShaderInfoTypeAMD; typedef struct VkShaderResourceUsageAMD { @@ -7922,9 +8489,6 @@ typedef struct VkExportMemoryAllocateInfoNV { typedef enum VkValidationCheckEXT { VK_VALIDATION_CHECK_ALL_EXT = 0, VK_VALIDATION_CHECK_SHADERS_EXT = 1, - VK_VALIDATION_CHECK_BEGIN_RANGE_EXT = VK_VALIDATION_CHECK_ALL_EXT, - VK_VALIDATION_CHECK_END_RANGE_EXT = VK_VALIDATION_CHECK_SHADERS_EXT, - VK_VALIDATION_CHECK_RANGE_SIZE_EXT = (VK_VALIDATION_CHECK_SHADERS_EXT - VK_VALIDATION_CHECK_ALL_EXT + 1), VK_VALIDATION_CHECK_MAX_ENUM_EXT = 0x7FFFFFFF } VkValidationCheckEXT; typedef struct VkValidationFlagsEXT { @@ -8017,229 +8581,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdEndConditionalRenderingEXT( #endif -#define VK_NVX_device_generated_commands 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkObjectTableNVX) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutNVX) -#define VK_NVX_DEVICE_GENERATED_COMMANDS_SPEC_VERSION 3 -#define VK_NVX_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME "VK_NVX_device_generated_commands" - -typedef enum VkIndirectCommandsTokenTypeNVX { - VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX = 0, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_DESCRIPTOR_SET_NVX = 1, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NVX = 2, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NVX = 3, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NVX = 4, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NVX = 5, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NVX = 6, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX = 7, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_BEGIN_RANGE_NVX = VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_END_RANGE_NVX = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_RANGE_SIZE_NVX = (VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX - VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX + 1), - VK_INDIRECT_COMMANDS_TOKEN_TYPE_MAX_ENUM_NVX = 0x7FFFFFFF -} VkIndirectCommandsTokenTypeNVX; - -typedef enum VkObjectEntryTypeNVX { - VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX = 0, - VK_OBJECT_ENTRY_TYPE_PIPELINE_NVX = 1, - VK_OBJECT_ENTRY_TYPE_INDEX_BUFFER_NVX = 2, - VK_OBJECT_ENTRY_TYPE_VERTEX_BUFFER_NVX = 3, - VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX = 4, - VK_OBJECT_ENTRY_TYPE_BEGIN_RANGE_NVX = VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX, - VK_OBJECT_ENTRY_TYPE_END_RANGE_NVX = VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX, - VK_OBJECT_ENTRY_TYPE_RANGE_SIZE_NVX = (VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX - VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX + 1), - VK_OBJECT_ENTRY_TYPE_MAX_ENUM_NVX = 0x7FFFFFFF -} VkObjectEntryTypeNVX; - -typedef enum VkIndirectCommandsLayoutUsageFlagBitsNVX { - VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NVX = 0x00000001, - VK_INDIRECT_COMMANDS_LAYOUT_USAGE_SPARSE_SEQUENCES_BIT_NVX = 0x00000002, - VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EMPTY_EXECUTIONS_BIT_NVX = 0x00000004, - VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NVX = 0x00000008, - VK_INDIRECT_COMMANDS_LAYOUT_USAGE_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF -} VkIndirectCommandsLayoutUsageFlagBitsNVX; -typedef VkFlags VkIndirectCommandsLayoutUsageFlagsNVX; - -typedef enum VkObjectEntryUsageFlagBitsNVX { - VK_OBJECT_ENTRY_USAGE_GRAPHICS_BIT_NVX = 0x00000001, - VK_OBJECT_ENTRY_USAGE_COMPUTE_BIT_NVX = 0x00000002, - VK_OBJECT_ENTRY_USAGE_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF -} VkObjectEntryUsageFlagBitsNVX; -typedef VkFlags VkObjectEntryUsageFlagsNVX; -typedef struct VkDeviceGeneratedCommandsFeaturesNVX { - VkStructureType sType; - const void* pNext; - VkBool32 computeBindingPointSupport; -} VkDeviceGeneratedCommandsFeaturesNVX; - -typedef struct VkDeviceGeneratedCommandsLimitsNVX { - VkStructureType sType; - const void* pNext; - uint32_t maxIndirectCommandsLayoutTokenCount; - uint32_t maxObjectEntryCounts; - uint32_t minSequenceCountBufferOffsetAlignment; - uint32_t minSequenceIndexBufferOffsetAlignment; - uint32_t minCommandsTokenBufferOffsetAlignment; -} VkDeviceGeneratedCommandsLimitsNVX; - -typedef struct VkIndirectCommandsTokenNVX { - VkIndirectCommandsTokenTypeNVX tokenType; - VkBuffer buffer; - VkDeviceSize offset; -} VkIndirectCommandsTokenNVX; - -typedef struct VkIndirectCommandsLayoutTokenNVX { - VkIndirectCommandsTokenTypeNVX tokenType; - uint32_t bindingUnit; - uint32_t dynamicCount; - uint32_t divisor; -} VkIndirectCommandsLayoutTokenNVX; - -typedef struct VkIndirectCommandsLayoutCreateInfoNVX { - VkStructureType sType; - const void* pNext; - VkPipelineBindPoint pipelineBindPoint; - VkIndirectCommandsLayoutUsageFlagsNVX flags; - uint32_t tokenCount; - const VkIndirectCommandsLayoutTokenNVX* pTokens; -} VkIndirectCommandsLayoutCreateInfoNVX; - -typedef struct VkCmdProcessCommandsInfoNVX { - VkStructureType sType; - const void* pNext; - VkObjectTableNVX objectTable; - VkIndirectCommandsLayoutNVX indirectCommandsLayout; - uint32_t indirectCommandsTokenCount; - const VkIndirectCommandsTokenNVX* pIndirectCommandsTokens; - uint32_t maxSequencesCount; - VkCommandBuffer targetCommandBuffer; - VkBuffer sequencesCountBuffer; - VkDeviceSize sequencesCountOffset; - VkBuffer sequencesIndexBuffer; - VkDeviceSize sequencesIndexOffset; -} VkCmdProcessCommandsInfoNVX; - -typedef struct VkCmdReserveSpaceForCommandsInfoNVX { - VkStructureType sType; - const void* pNext; - VkObjectTableNVX objectTable; - VkIndirectCommandsLayoutNVX indirectCommandsLayout; - uint32_t maxSequencesCount; -} VkCmdReserveSpaceForCommandsInfoNVX; - -typedef struct VkObjectTableCreateInfoNVX { - VkStructureType sType; - const void* pNext; - uint32_t objectCount; - const VkObjectEntryTypeNVX* pObjectEntryTypes; - const uint32_t* pObjectEntryCounts; - const VkObjectEntryUsageFlagsNVX* pObjectEntryUsageFlags; - uint32_t maxUniformBuffersPerDescriptor; - uint32_t maxStorageBuffersPerDescriptor; - uint32_t maxStorageImagesPerDescriptor; - uint32_t maxSampledImagesPerDescriptor; - uint32_t maxPipelineLayouts; -} VkObjectTableCreateInfoNVX; - -typedef struct VkObjectTableEntryNVX { - VkObjectEntryTypeNVX type; - VkObjectEntryUsageFlagsNVX flags; -} VkObjectTableEntryNVX; - -typedef struct VkObjectTablePipelineEntryNVX { - VkObjectEntryTypeNVX type; - VkObjectEntryUsageFlagsNVX flags; - VkPipeline pipeline; -} VkObjectTablePipelineEntryNVX; - -typedef struct VkObjectTableDescriptorSetEntryNVX { - VkObjectEntryTypeNVX type; - VkObjectEntryUsageFlagsNVX flags; - VkPipelineLayout pipelineLayout; - VkDescriptorSet descriptorSet; -} VkObjectTableDescriptorSetEntryNVX; - -typedef struct VkObjectTableVertexBufferEntryNVX { - VkObjectEntryTypeNVX type; - VkObjectEntryUsageFlagsNVX flags; - VkBuffer buffer; -} VkObjectTableVertexBufferEntryNVX; - -typedef struct VkObjectTableIndexBufferEntryNVX { - VkObjectEntryTypeNVX type; - VkObjectEntryUsageFlagsNVX flags; - VkBuffer buffer; - VkIndexType indexType; -} VkObjectTableIndexBufferEntryNVX; - -typedef struct VkObjectTablePushConstantEntryNVX { - VkObjectEntryTypeNVX type; - VkObjectEntryUsageFlagsNVX flags; - VkPipelineLayout pipelineLayout; - VkShaderStageFlags stageFlags; -} VkObjectTablePushConstantEntryNVX; - -typedef void (VKAPI_PTR *PFN_vkCmdProcessCommandsNVX)(VkCommandBuffer commandBuffer, const VkCmdProcessCommandsInfoNVX* pProcessCommandsInfo); -typedef void (VKAPI_PTR *PFN_vkCmdReserveSpaceForCommandsNVX)(VkCommandBuffer commandBuffer, const VkCmdReserveSpaceForCommandsInfoNVX* pReserveSpaceInfo); -typedef VkResult (VKAPI_PTR *PFN_vkCreateIndirectCommandsLayoutNVX)(VkDevice device, const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkIndirectCommandsLayoutNVX* pIndirectCommandsLayout); -typedef void (VKAPI_PTR *PFN_vkDestroyIndirectCommandsLayoutNVX)(VkDevice device, VkIndirectCommandsLayoutNVX indirectCommandsLayout, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkCreateObjectTableNVX)(VkDevice device, const VkObjectTableCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkObjectTableNVX* pObjectTable); -typedef void (VKAPI_PTR *PFN_vkDestroyObjectTableNVX)(VkDevice device, VkObjectTableNVX objectTable, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkRegisterObjectsNVX)(VkDevice device, VkObjectTableNVX objectTable, uint32_t objectCount, const VkObjectTableEntryNVX* const* ppObjectTableEntries, const uint32_t* pObjectIndices); -typedef VkResult (VKAPI_PTR *PFN_vkUnregisterObjectsNVX)(VkDevice device, VkObjectTableNVX objectTable, uint32_t objectCount, const VkObjectEntryTypeNVX* pObjectEntryTypes, const uint32_t* pObjectIndices); -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX)(VkPhysicalDevice physicalDevice, VkDeviceGeneratedCommandsFeaturesNVX* pFeatures, VkDeviceGeneratedCommandsLimitsNVX* pLimits); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdProcessCommandsNVX( - VkCommandBuffer commandBuffer, - const VkCmdProcessCommandsInfoNVX* pProcessCommandsInfo); - -VKAPI_ATTR void VKAPI_CALL vkCmdReserveSpaceForCommandsNVX( - VkCommandBuffer commandBuffer, - const VkCmdReserveSpaceForCommandsInfoNVX* pReserveSpaceInfo); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateIndirectCommandsLayoutNVX( - VkDevice device, - const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkIndirectCommandsLayoutNVX* pIndirectCommandsLayout); - -VKAPI_ATTR void VKAPI_CALL vkDestroyIndirectCommandsLayoutNVX( - VkDevice device, - VkIndirectCommandsLayoutNVX indirectCommandsLayout, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateObjectTableNVX( - VkDevice device, - const VkObjectTableCreateInfoNVX* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkObjectTableNVX* pObjectTable); - -VKAPI_ATTR void VKAPI_CALL vkDestroyObjectTableNVX( - VkDevice device, - VkObjectTableNVX objectTable, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkRegisterObjectsNVX( - VkDevice device, - VkObjectTableNVX objectTable, - uint32_t objectCount, - const VkObjectTableEntryNVX* const* ppObjectTableEntries, - const uint32_t* pObjectIndices); - -VKAPI_ATTR VkResult VKAPI_CALL vkUnregisterObjectsNVX( - VkDevice device, - VkObjectTableNVX objectTable, - uint32_t objectCount, - const VkObjectEntryTypeNVX* pObjectEntryTypes, - const uint32_t* pObjectIndices); - -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX( - VkPhysicalDevice physicalDevice, - VkDeviceGeneratedCommandsFeaturesNVX* pFeatures, - VkDeviceGeneratedCommandsLimitsNVX* pLimits); -#endif - - #define VK_NV_clip_space_w_scaling 1 #define VK_NV_CLIP_SPACE_W_SCALING_SPEC_VERSION 1 #define VK_NV_CLIP_SPACE_W_SCALING_EXTENSION_NAME "VK_NV_clip_space_w_scaling" @@ -8284,7 +8625,8 @@ VKAPI_ATTR VkResult VKAPI_CALL vkReleaseDisplayEXT( #define VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME "VK_EXT_display_surface_counter" typedef enum VkSurfaceCounterFlagBitsEXT { - VK_SURFACE_COUNTER_VBLANK_EXT = 0x00000001, + VK_SURFACE_COUNTER_VBLANK_BIT_EXT = 0x00000001, + VK_SURFACE_COUNTER_VBLANK_EXT = VK_SURFACE_COUNTER_VBLANK_BIT_EXT, VK_SURFACE_COUNTER_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF } VkSurfaceCounterFlagBitsEXT; typedef VkFlags VkSurfaceCounterFlagsEXT; @@ -8322,25 +8664,16 @@ typedef enum VkDisplayPowerStateEXT { VK_DISPLAY_POWER_STATE_OFF_EXT = 0, VK_DISPLAY_POWER_STATE_SUSPEND_EXT = 1, VK_DISPLAY_POWER_STATE_ON_EXT = 2, - VK_DISPLAY_POWER_STATE_BEGIN_RANGE_EXT = VK_DISPLAY_POWER_STATE_OFF_EXT, - VK_DISPLAY_POWER_STATE_END_RANGE_EXT = VK_DISPLAY_POWER_STATE_ON_EXT, - VK_DISPLAY_POWER_STATE_RANGE_SIZE_EXT = (VK_DISPLAY_POWER_STATE_ON_EXT - VK_DISPLAY_POWER_STATE_OFF_EXT + 1), VK_DISPLAY_POWER_STATE_MAX_ENUM_EXT = 0x7FFFFFFF } VkDisplayPowerStateEXT; typedef enum VkDeviceEventTypeEXT { VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT = 0, - VK_DEVICE_EVENT_TYPE_BEGIN_RANGE_EXT = VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT, - VK_DEVICE_EVENT_TYPE_END_RANGE_EXT = VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT, - VK_DEVICE_EVENT_TYPE_RANGE_SIZE_EXT = (VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT - VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT + 1), VK_DEVICE_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF } VkDeviceEventTypeEXT; typedef enum VkDisplayEventTypeEXT { VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT = 0, - VK_DISPLAY_EVENT_TYPE_BEGIN_RANGE_EXT = VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT, - VK_DISPLAY_EVENT_TYPE_END_RANGE_EXT = VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT, - VK_DISPLAY_EVENT_TYPE_RANGE_SIZE_EXT = (VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT - VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT + 1), VK_DISPLAY_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF } VkDisplayEventTypeEXT; typedef struct VkDisplayPowerInfoEXT { @@ -8482,9 +8815,6 @@ typedef enum VkViewportCoordinateSwizzleNV { VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Z_NV = 5, VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV = 6, VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV = 7, - VK_VIEWPORT_COORDINATE_SWIZZLE_BEGIN_RANGE_NV = VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV, - VK_VIEWPORT_COORDINATE_SWIZZLE_END_RANGE_NV = VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV, - VK_VIEWPORT_COORDINATE_SWIZZLE_RANGE_SIZE_NV = (VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV - VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV + 1), VK_VIEWPORT_COORDINATE_SWIZZLE_MAX_ENUM_NV = 0x7FFFFFFF } VkViewportCoordinateSwizzleNV; typedef VkFlags VkPipelineViewportSwizzleStateCreateFlagsNV; @@ -8512,9 +8842,6 @@ typedef struct VkPipelineViewportSwizzleStateCreateInfoNV { typedef enum VkDiscardRectangleModeEXT { VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT = 0, VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT = 1, - VK_DISCARD_RECTANGLE_MODE_BEGIN_RANGE_EXT = VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT, - VK_DISCARD_RECTANGLE_MODE_END_RANGE_EXT = VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT, - VK_DISCARD_RECTANGLE_MODE_RANGE_SIZE_EXT = (VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT - VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT + 1), VK_DISCARD_RECTANGLE_MODE_MAX_ENUM_EXT = 0x7FFFFFFF } VkDiscardRectangleModeEXT; typedef VkFlags VkPipelineDiscardRectangleStateCreateFlagsEXT; @@ -8552,9 +8879,6 @@ typedef enum VkConservativeRasterizationModeEXT { VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT = 0, VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT = 1, VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT = 2, - VK_CONSERVATIVE_RASTERIZATION_MODE_BEGIN_RANGE_EXT = VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT, - VK_CONSERVATIVE_RASTERIZATION_MODE_END_RANGE_EXT = VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT, - VK_CONSERVATIVE_RASTERIZATION_MODE_RANGE_SIZE_EXT = (VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT - VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT + 1), VK_CONSERVATIVE_RASTERIZATION_MODE_MAX_ENUM_EXT = 0x7FFFFFFF } VkConservativeRasterizationModeEXT; typedef VkFlags VkPipelineRasterizationConservativeStateCreateFlagsEXT; @@ -8651,10 +8975,9 @@ VKAPI_ATTR void VKAPI_CALL vkSetHdrMetadataEXT( #define VK_EXT_debug_utils 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugUtilsMessengerEXT) -#define VK_EXT_DEBUG_UTILS_SPEC_VERSION 1 +#define VK_EXT_DEBUG_UTILS_SPEC_VERSION 2 #define VK_EXT_DEBUG_UTILS_EXTENSION_NAME "VK_EXT_debug_utils" typedef VkFlags VkDebugUtilsMessengerCallbackDataFlagsEXT; -typedef VkFlags VkDebugUtilsMessengerCreateFlagsEXT; typedef enum VkDebugUtilsMessageSeverityFlagBitsEXT { VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT = 0x00000001, @@ -8663,7 +8986,6 @@ typedef enum VkDebugUtilsMessageSeverityFlagBitsEXT { VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT = 0x00001000, VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF } VkDebugUtilsMessageSeverityFlagBitsEXT; -typedef VkFlags VkDebugUtilsMessageSeverityFlagsEXT; typedef enum VkDebugUtilsMessageTypeFlagBitsEXT { VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT = 0x00000001, @@ -8672,6 +8994,15 @@ typedef enum VkDebugUtilsMessageTypeFlagBitsEXT { VK_DEBUG_UTILS_MESSAGE_TYPE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF } VkDebugUtilsMessageTypeFlagBitsEXT; typedef VkFlags VkDebugUtilsMessageTypeFlagsEXT; +typedef VkFlags VkDebugUtilsMessageSeverityFlagsEXT; +typedef VkFlags VkDebugUtilsMessengerCreateFlagsEXT; +typedef struct VkDebugUtilsLabelEXT { + VkStructureType sType; + const void* pNext; + const char* pLabelName; + float color[4]; +} VkDebugUtilsLabelEXT; + typedef struct VkDebugUtilsObjectNameInfoEXT { VkStructureType sType; const void* pNext; @@ -8680,23 +9011,6 @@ typedef struct VkDebugUtilsObjectNameInfoEXT { const char* pObjectName; } VkDebugUtilsObjectNameInfoEXT; -typedef struct VkDebugUtilsObjectTagInfoEXT { - VkStructureType sType; - const void* pNext; - VkObjectType objectType; - uint64_t objectHandle; - uint64_t tagName; - size_t tagSize; - const void* pTag; -} VkDebugUtilsObjectTagInfoEXT; - -typedef struct VkDebugUtilsLabelEXT { - VkStructureType sType; - const void* pNext; - const char* pLabelName; - float color[4]; -} VkDebugUtilsLabelEXT; - typedef struct VkDebugUtilsMessengerCallbackDataEXT { VkStructureType sType; const void* pNext; @@ -8728,6 +9042,16 @@ typedef struct VkDebugUtilsMessengerCreateInfoEXT { void* pUserData; } VkDebugUtilsMessengerCreateInfoEXT; +typedef struct VkDebugUtilsObjectTagInfoEXT { + VkStructureType sType; + const void* pNext; + VkObjectType objectType; + uint64_t objectHandle; + uint64_t tagName; + size_t tagSize; + const void* pTag; +} VkDebugUtilsObjectTagInfoEXT; + typedef VkResult (VKAPI_PTR *PFN_vkSetDebugUtilsObjectNameEXT)(VkDevice device, const VkDebugUtilsObjectNameInfoEXT* pNameInfo); typedef VkResult (VKAPI_PTR *PFN_vkSetDebugUtilsObjectTagEXT)(VkDevice device, const VkDebugUtilsObjectTagInfoEXT* pTagInfo); typedef void (VKAPI_PTR *PFN_vkQueueBeginDebugUtilsLabelEXT)(VkQueue queue, const VkDebugUtilsLabelEXT* pLabelInfo); @@ -8938,9 +9262,6 @@ typedef enum VkBlendOverlapEXT { VK_BLEND_OVERLAP_UNCORRELATED_EXT = 0, VK_BLEND_OVERLAP_DISJOINT_EXT = 1, VK_BLEND_OVERLAP_CONJOINT_EXT = 2, - VK_BLEND_OVERLAP_BEGIN_RANGE_EXT = VK_BLEND_OVERLAP_UNCORRELATED_EXT, - VK_BLEND_OVERLAP_END_RANGE_EXT = VK_BLEND_OVERLAP_CONJOINT_EXT, - VK_BLEND_OVERLAP_RANGE_SIZE_EXT = (VK_BLEND_OVERLAP_CONJOINT_EXT - VK_BLEND_OVERLAP_UNCORRELATED_EXT + 1), VK_BLEND_OVERLAP_MAX_ENUM_EXT = 0x7FFFFFFF } VkBlendOverlapEXT; typedef struct VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT { @@ -8993,9 +9314,6 @@ typedef enum VkCoverageModulationModeNV { VK_COVERAGE_MODULATION_MODE_RGB_NV = 1, VK_COVERAGE_MODULATION_MODE_ALPHA_NV = 2, VK_COVERAGE_MODULATION_MODE_RGBA_NV = 3, - VK_COVERAGE_MODULATION_MODE_BEGIN_RANGE_NV = VK_COVERAGE_MODULATION_MODE_NONE_NV, - VK_COVERAGE_MODULATION_MODE_END_RANGE_NV = VK_COVERAGE_MODULATION_MODE_RGBA_NV, - VK_COVERAGE_MODULATION_MODE_RANGE_SIZE_NV = (VK_COVERAGE_MODULATION_MODE_RGBA_NV - VK_COVERAGE_MODULATION_MODE_NONE_NV + 1), VK_COVERAGE_MODULATION_MODE_MAX_ENUM_NV = 0x7FFFFFFF } VkCoverageModulationModeNV; typedef VkFlags VkPipelineCoverageModulationStateCreateFlagsNV; @@ -9102,9 +9420,6 @@ VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkValidationCacheEXT) typedef enum VkValidationCacheHeaderVersionEXT { VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT = 1, - VK_VALIDATION_CACHE_HEADER_VERSION_BEGIN_RANGE_EXT = VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT, - VK_VALIDATION_CACHE_HEADER_VERSION_END_RANGE_EXT = VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT, - VK_VALIDATION_CACHE_HEADER_VERSION_RANGE_SIZE_EXT = (VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT - VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT + 1), VK_VALIDATION_CACHE_HEADER_VERSION_MAX_ENUM_EXT = 0x7FFFFFFF } VkValidationCacheHeaderVersionEXT; typedef VkFlags VkValidationCacheCreateFlagsEXT; @@ -9194,9 +9509,6 @@ typedef enum VkShadingRatePaletteEntryNV { VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X2_PIXELS_NV = 9, VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X4_PIXELS_NV = 10, VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV = 11, - VK_SHADING_RATE_PALETTE_ENTRY_BEGIN_RANGE_NV = VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV, - VK_SHADING_RATE_PALETTE_ENTRY_END_RANGE_NV = VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV, - VK_SHADING_RATE_PALETTE_ENTRY_RANGE_SIZE_NV = (VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV - VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV + 1), VK_SHADING_RATE_PALETTE_ENTRY_MAX_ENUM_NV = 0x7FFFFFFF } VkShadingRatePaletteEntryNV; @@ -9205,9 +9517,6 @@ typedef enum VkCoarseSampleOrderTypeNV { VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV = 1, VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV = 2, VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV = 3, - VK_COARSE_SAMPLE_ORDER_TYPE_BEGIN_RANGE_NV = VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV, - VK_COARSE_SAMPLE_ORDER_TYPE_END_RANGE_NV = VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV, - VK_COARSE_SAMPLE_ORDER_TYPE_RANGE_SIZE_NV = (VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV - VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV + 1), VK_COARSE_SAMPLE_ORDER_TYPE_MAX_ENUM_NV = 0x7FFFFFFF } VkCoarseSampleOrderTypeNV; typedef struct VkShadingRatePaletteNV { @@ -9287,88 +9596,118 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetCoarseSampleOrderNV( VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureNV) #define VK_NV_RAY_TRACING_SPEC_VERSION 3 #define VK_NV_RAY_TRACING_EXTENSION_NAME "VK_NV_ray_tracing" -#define VK_SHADER_UNUSED_NV (~0U) +#define VK_SHADER_UNUSED_KHR (~0U) +#define VK_SHADER_UNUSED_NV VK_SHADER_UNUSED_KHR -typedef enum VkAccelerationStructureTypeNV { - VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV = 0, - VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV = 1, - VK_ACCELERATION_STRUCTURE_TYPE_BEGIN_RANGE_NV = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV, - VK_ACCELERATION_STRUCTURE_TYPE_END_RANGE_NV = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV, - VK_ACCELERATION_STRUCTURE_TYPE_RANGE_SIZE_NV = (VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV - VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV + 1), - VK_ACCELERATION_STRUCTURE_TYPE_MAX_ENUM_NV = 0x7FFFFFFF -} VkAccelerationStructureTypeNV; +typedef enum VkRayTracingShaderGroupTypeKHR { + VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR = 0, + VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR = 1, + VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR = 2, + VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR, + VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR, + VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR, + VK_RAY_TRACING_SHADER_GROUP_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkRayTracingShaderGroupTypeKHR; +typedef VkRayTracingShaderGroupTypeKHR VkRayTracingShaderGroupTypeNV; -typedef enum VkRayTracingShaderGroupTypeNV { - VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV = 0, - VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV = 1, - VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV = 2, - VK_RAY_TRACING_SHADER_GROUP_TYPE_BEGIN_RANGE_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV, - VK_RAY_TRACING_SHADER_GROUP_TYPE_END_RANGE_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV, - VK_RAY_TRACING_SHADER_GROUP_TYPE_RANGE_SIZE_NV = (VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV - VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV + 1), - VK_RAY_TRACING_SHADER_GROUP_TYPE_MAX_ENUM_NV = 0x7FFFFFFF -} VkRayTracingShaderGroupTypeNV; -typedef enum VkGeometryTypeNV { - VK_GEOMETRY_TYPE_TRIANGLES_NV = 0, - VK_GEOMETRY_TYPE_AABBS_NV = 1, - VK_GEOMETRY_TYPE_BEGIN_RANGE_NV = VK_GEOMETRY_TYPE_TRIANGLES_NV, - VK_GEOMETRY_TYPE_END_RANGE_NV = VK_GEOMETRY_TYPE_AABBS_NV, - VK_GEOMETRY_TYPE_RANGE_SIZE_NV = (VK_GEOMETRY_TYPE_AABBS_NV - VK_GEOMETRY_TYPE_TRIANGLES_NV + 1), - VK_GEOMETRY_TYPE_MAX_ENUM_NV = 0x7FFFFFFF -} VkGeometryTypeNV; +typedef enum VkGeometryTypeKHR { + VK_GEOMETRY_TYPE_TRIANGLES_KHR = 0, + VK_GEOMETRY_TYPE_AABBS_KHR = 1, + VK_GEOMETRY_TYPE_INSTANCES_KHR = 2, + VK_GEOMETRY_TYPE_TRIANGLES_NV = VK_GEOMETRY_TYPE_TRIANGLES_KHR, + VK_GEOMETRY_TYPE_AABBS_NV = VK_GEOMETRY_TYPE_AABBS_KHR, + VK_GEOMETRY_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkGeometryTypeKHR; +typedef VkGeometryTypeKHR VkGeometryTypeNV; + + +typedef enum VkAccelerationStructureTypeKHR { + VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR = 0, + VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR = 1, + VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR = 2, + VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, + VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, + VK_ACCELERATION_STRUCTURE_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureTypeKHR; +typedef VkAccelerationStructureTypeKHR VkAccelerationStructureTypeNV; + + +typedef enum VkCopyAccelerationStructureModeKHR { + VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR = 0, + VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR = 1, + VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR = 2, + VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR = 3, + VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR, + VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR, + VK_COPY_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkCopyAccelerationStructureModeKHR; +typedef VkCopyAccelerationStructureModeKHR VkCopyAccelerationStructureModeNV; -typedef enum VkCopyAccelerationStructureModeNV { - VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV = 0, - VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV = 1, - VK_COPY_ACCELERATION_STRUCTURE_MODE_BEGIN_RANGE_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV, - VK_COPY_ACCELERATION_STRUCTURE_MODE_END_RANGE_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV, - VK_COPY_ACCELERATION_STRUCTURE_MODE_RANGE_SIZE_NV = (VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV - VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV + 1), - VK_COPY_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_NV = 0x7FFFFFFF -} VkCopyAccelerationStructureModeNV; typedef enum VkAccelerationStructureMemoryRequirementsTypeNV { VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV = 0, VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV = 1, VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV = 2, - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BEGIN_RANGE_NV = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV, - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_END_RANGE_NV = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV, - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_RANGE_SIZE_NV = (VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV + 1), VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_MAX_ENUM_NV = 0x7FFFFFFF } VkAccelerationStructureMemoryRequirementsTypeNV; -typedef enum VkGeometryFlagBitsNV { - VK_GEOMETRY_OPAQUE_BIT_NV = 0x00000001, - VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NV = 0x00000002, - VK_GEOMETRY_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF -} VkGeometryFlagBitsNV; -typedef VkFlags VkGeometryFlagsNV; +typedef enum VkGeometryFlagBitsKHR { + VK_GEOMETRY_OPAQUE_BIT_KHR = 0x00000001, + VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR = 0x00000002, + VK_GEOMETRY_OPAQUE_BIT_NV = VK_GEOMETRY_OPAQUE_BIT_KHR, + VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NV = VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR, + VK_GEOMETRY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkGeometryFlagBitsKHR; +typedef VkFlags VkGeometryFlagsKHR; +typedef VkGeometryFlagsKHR VkGeometryFlagsNV; -typedef enum VkGeometryInstanceFlagBitsNV { - VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV = 0x00000001, - VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV = 0x00000002, - VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV = 0x00000004, - VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NV = 0x00000008, - VK_GEOMETRY_INSTANCE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF -} VkGeometryInstanceFlagBitsNV; -typedef VkFlags VkGeometryInstanceFlagsNV; +typedef VkGeometryFlagBitsKHR VkGeometryFlagBitsNV; + + +typedef enum VkGeometryInstanceFlagBitsKHR { + VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR = 0x00000001, + VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR = 0x00000002, + VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR = 0x00000004, + VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR = 0x00000008, + VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR, + VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV = VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR, + VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV = VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR, + VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NV = VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR, + VK_GEOMETRY_INSTANCE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkGeometryInstanceFlagBitsKHR; +typedef VkFlags VkGeometryInstanceFlagsKHR; +typedef VkGeometryInstanceFlagsKHR VkGeometryInstanceFlagsNV; + +typedef VkGeometryInstanceFlagBitsKHR VkGeometryInstanceFlagBitsNV; + + +typedef enum VkBuildAccelerationStructureFlagBitsKHR { + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR = 0x00000001, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR = 0x00000002, + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR = 0x00000004, + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR = 0x00000008, + VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR = 0x00000010, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkBuildAccelerationStructureFlagBitsKHR; +typedef VkFlags VkBuildAccelerationStructureFlagsKHR; +typedef VkBuildAccelerationStructureFlagsKHR VkBuildAccelerationStructureFlagsNV; + +typedef VkBuildAccelerationStructureFlagBitsKHR VkBuildAccelerationStructureFlagBitsNV; -typedef enum VkBuildAccelerationStructureFlagBitsNV { - VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV = 0x00000001, - VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV = 0x00000002, - VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV = 0x00000004, - VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV = 0x00000008, - VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NV = 0x00000010, - VK_BUILD_ACCELERATION_STRUCTURE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF -} VkBuildAccelerationStructureFlagBitsNV; -typedef VkFlags VkBuildAccelerationStructureFlagsNV; typedef struct VkRayTracingShaderGroupCreateInfoNV { - VkStructureType sType; - const void* pNext; - VkRayTracingShaderGroupTypeNV type; - uint32_t generalShader; - uint32_t closestHitShader; - uint32_t anyHitShader; - uint32_t intersectionShader; + VkStructureType sType; + const void* pNext; + VkRayTracingShaderGroupTypeKHR type; + uint32_t generalShader; + uint32_t closestHitShader; + uint32_t anyHitShader; + uint32_t intersectionShader; } VkRayTracingShaderGroupCreateInfoNV; typedef struct VkRayTracingPipelineCreateInfoNV { @@ -9416,11 +9755,11 @@ typedef struct VkGeometryDataNV { } VkGeometryDataNV; typedef struct VkGeometryNV { - VkStructureType sType; - const void* pNext; - VkGeometryTypeNV geometryType; - VkGeometryDataNV geometry; - VkGeometryFlagsNV flags; + VkStructureType sType; + const void* pNext; + VkGeometryTypeKHR geometryType; + VkGeometryDataNV geometry; + VkGeometryFlagsKHR flags; } VkGeometryNV; typedef struct VkAccelerationStructureInfoNV { @@ -9477,14 +9816,43 @@ typedef struct VkPhysicalDeviceRayTracingPropertiesNV { uint32_t maxDescriptorSetAccelerationStructures; } VkPhysicalDeviceRayTracingPropertiesNV; +typedef struct VkTransformMatrixKHR { + float matrix[3][4]; +} VkTransformMatrixKHR; + +typedef VkTransformMatrixKHR VkTransformMatrixNV; + +typedef struct VkAabbPositionsKHR { + float minX; + float minY; + float minZ; + float maxX; + float maxY; + float maxZ; +} VkAabbPositionsKHR; + +typedef VkAabbPositionsKHR VkAabbPositionsNV; + +typedef struct VkAccelerationStructureInstanceKHR { + VkTransformMatrixKHR transform; + uint32_t instanceCustomIndex:24; + uint32_t mask:8; + uint32_t instanceShaderBindingTableRecordOffset:24; + VkGeometryInstanceFlagsKHR flags:8; + uint64_t accelerationStructureReference; +} VkAccelerationStructureInstanceKHR; + +typedef VkAccelerationStructureInstanceKHR VkAccelerationStructureInstanceNV; + typedef VkResult (VKAPI_PTR *PFN_vkCreateAccelerationStructureNV)(VkDevice device, const VkAccelerationStructureCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureNV* pAccelerationStructure); typedef void (VKAPI_PTR *PFN_vkDestroyAccelerationStructureNV)(VkDevice device, VkAccelerationStructureNV accelerationStructure, const VkAllocationCallbacks* pAllocator); typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureMemoryRequirementsNV)(VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements); typedef VkResult (VKAPI_PTR *PFN_vkBindAccelerationStructureMemoryNV)(VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoNV* pBindInfos); typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructureNV)(VkCommandBuffer commandBuffer, const VkAccelerationStructureInfoNV* pInfo, VkBuffer instanceData, VkDeviceSize instanceOffset, VkBool32 update, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkBuffer scratch, VkDeviceSize scratchOffset); -typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureNV)(VkCommandBuffer commandBuffer, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkCopyAccelerationStructureModeNV mode); +typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureNV)(VkCommandBuffer commandBuffer, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkCopyAccelerationStructureModeKHR mode); typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysNV)(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer, VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer, VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride, VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset, VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer, VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride, uint32_t width, uint32_t height, uint32_t depth); typedef VkResult (VKAPI_PTR *PFN_vkCreateRayTracingPipelinesNV)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingShaderGroupHandlesKHR)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData); typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingShaderGroupHandlesNV)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData); typedef VkResult (VKAPI_PTR *PFN_vkGetAccelerationStructureHandleNV)(VkDevice device, VkAccelerationStructureNV accelerationStructure, size_t dataSize, void* pData); typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructuresPropertiesNV)(VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureNV* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); @@ -9527,7 +9895,7 @@ VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureNV( VkCommandBuffer commandBuffer, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, - VkCopyAccelerationStructureModeNV mode); + VkCopyAccelerationStructureModeKHR mode); VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysNV( VkCommandBuffer commandBuffer, @@ -9554,6 +9922,14 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateRayTracingPipelinesNV( const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingShaderGroupHandlesKHR( + VkDevice device, + VkPipeline pipeline, + uint32_t firstGroup, + uint32_t groupCount, + size_t dataSize, + void* pData); + VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingShaderGroupHandlesNV( VkDevice device, VkPipeline pipeline, @@ -9618,6 +9994,11 @@ typedef struct VkFilterCubicImageViewImageFormatPropertiesEXT { +#define VK_QCOM_render_pass_shader_resolve 1 +#define VK_QCOM_RENDER_PASS_SHADER_RESOLVE_SPEC_VERSION 4 +#define VK_QCOM_RENDER_PASS_SHADER_RESOLVE_EXTENSION_NAME "VK_QCOM_render_pass_shader_resolve" + + #define VK_EXT_global_priority 1 #define VK_EXT_GLOBAL_PRIORITY_SPEC_VERSION 2 #define VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME "VK_EXT_global_priority" @@ -9627,9 +10008,6 @@ typedef enum VkQueueGlobalPriorityEXT { VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT = 256, VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT = 512, VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT = 1024, - VK_QUEUE_GLOBAL_PRIORITY_BEGIN_RANGE_EXT = VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT, - VK_QUEUE_GLOBAL_PRIORITY_END_RANGE_EXT = VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT, - VK_QUEUE_GLOBAL_PRIORITY_RANGE_SIZE_EXT = (VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT - VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT + 1), VK_QUEUE_GLOBAL_PRIORITY_MAX_ENUM_EXT = 0x7FFFFFFF } VkQueueGlobalPriorityEXT; typedef struct VkDeviceQueueGlobalPriorityCreateInfoEXT { @@ -9713,9 +10091,6 @@ typedef enum VkTimeDomainEXT { VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT = 1, VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT = 2, VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT = 3, - VK_TIME_DOMAIN_BEGIN_RANGE_EXT = VK_TIME_DOMAIN_DEVICE_EXT, - VK_TIME_DOMAIN_END_RANGE_EXT = VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT, - VK_TIME_DOMAIN_RANGE_SIZE_EXT = (VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT - VK_TIME_DOMAIN_DEVICE_EXT + 1), VK_TIME_DOMAIN_MAX_ENUM_EXT = 0x7FFFFFFF } VkTimeDomainEXT; typedef struct VkCalibratedTimestampInfoEXT { @@ -9774,9 +10149,6 @@ typedef enum VkMemoryOverallocationBehaviorAMD { VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD = 0, VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD = 1, VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD = 2, - VK_MEMORY_OVERALLOCATION_BEHAVIOR_BEGIN_RANGE_AMD = VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD, - VK_MEMORY_OVERALLOCATION_BEHAVIOR_END_RANGE_AMD = VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD, - VK_MEMORY_OVERALLOCATION_BEHAVIOR_RANGE_SIZE_AMD = (VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD - VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD + 1), VK_MEMORY_OVERALLOCATION_BEHAVIOR_MAX_ENUM_AMD = 0x7FFFFFFF } VkMemoryOverallocationBehaviorAMD; typedef struct VkDeviceMemoryOverallocationCreateInfoAMD { @@ -10014,40 +10386,28 @@ typedef struct VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL { #define VK_INTEL_performance_query 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPerformanceConfigurationINTEL) -#define VK_INTEL_PERFORMANCE_QUERY_SPEC_VERSION 1 +#define VK_INTEL_PERFORMANCE_QUERY_SPEC_VERSION 2 #define VK_INTEL_PERFORMANCE_QUERY_EXTENSION_NAME "VK_INTEL_performance_query" typedef enum VkPerformanceConfigurationTypeINTEL { VK_PERFORMANCE_CONFIGURATION_TYPE_COMMAND_QUEUE_METRICS_DISCOVERY_ACTIVATED_INTEL = 0, - VK_PERFORMANCE_CONFIGURATION_TYPE_BEGIN_RANGE_INTEL = VK_PERFORMANCE_CONFIGURATION_TYPE_COMMAND_QUEUE_METRICS_DISCOVERY_ACTIVATED_INTEL, - VK_PERFORMANCE_CONFIGURATION_TYPE_END_RANGE_INTEL = VK_PERFORMANCE_CONFIGURATION_TYPE_COMMAND_QUEUE_METRICS_DISCOVERY_ACTIVATED_INTEL, - VK_PERFORMANCE_CONFIGURATION_TYPE_RANGE_SIZE_INTEL = (VK_PERFORMANCE_CONFIGURATION_TYPE_COMMAND_QUEUE_METRICS_DISCOVERY_ACTIVATED_INTEL - VK_PERFORMANCE_CONFIGURATION_TYPE_COMMAND_QUEUE_METRICS_DISCOVERY_ACTIVATED_INTEL + 1), VK_PERFORMANCE_CONFIGURATION_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF } VkPerformanceConfigurationTypeINTEL; typedef enum VkQueryPoolSamplingModeINTEL { VK_QUERY_POOL_SAMPLING_MODE_MANUAL_INTEL = 0, - VK_QUERY_POOL_SAMPLING_MODE_BEGIN_RANGE_INTEL = VK_QUERY_POOL_SAMPLING_MODE_MANUAL_INTEL, - VK_QUERY_POOL_SAMPLING_MODE_END_RANGE_INTEL = VK_QUERY_POOL_SAMPLING_MODE_MANUAL_INTEL, - VK_QUERY_POOL_SAMPLING_MODE_RANGE_SIZE_INTEL = (VK_QUERY_POOL_SAMPLING_MODE_MANUAL_INTEL - VK_QUERY_POOL_SAMPLING_MODE_MANUAL_INTEL + 1), VK_QUERY_POOL_SAMPLING_MODE_MAX_ENUM_INTEL = 0x7FFFFFFF } VkQueryPoolSamplingModeINTEL; typedef enum VkPerformanceOverrideTypeINTEL { VK_PERFORMANCE_OVERRIDE_TYPE_NULL_HARDWARE_INTEL = 0, VK_PERFORMANCE_OVERRIDE_TYPE_FLUSH_GPU_CACHES_INTEL = 1, - VK_PERFORMANCE_OVERRIDE_TYPE_BEGIN_RANGE_INTEL = VK_PERFORMANCE_OVERRIDE_TYPE_NULL_HARDWARE_INTEL, - VK_PERFORMANCE_OVERRIDE_TYPE_END_RANGE_INTEL = VK_PERFORMANCE_OVERRIDE_TYPE_FLUSH_GPU_CACHES_INTEL, - VK_PERFORMANCE_OVERRIDE_TYPE_RANGE_SIZE_INTEL = (VK_PERFORMANCE_OVERRIDE_TYPE_FLUSH_GPU_CACHES_INTEL - VK_PERFORMANCE_OVERRIDE_TYPE_NULL_HARDWARE_INTEL + 1), VK_PERFORMANCE_OVERRIDE_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF } VkPerformanceOverrideTypeINTEL; typedef enum VkPerformanceParameterTypeINTEL { VK_PERFORMANCE_PARAMETER_TYPE_HW_COUNTERS_SUPPORTED_INTEL = 0, VK_PERFORMANCE_PARAMETER_TYPE_STREAM_MARKER_VALID_BITS_INTEL = 1, - VK_PERFORMANCE_PARAMETER_TYPE_BEGIN_RANGE_INTEL = VK_PERFORMANCE_PARAMETER_TYPE_HW_COUNTERS_SUPPORTED_INTEL, - VK_PERFORMANCE_PARAMETER_TYPE_END_RANGE_INTEL = VK_PERFORMANCE_PARAMETER_TYPE_STREAM_MARKER_VALID_BITS_INTEL, - VK_PERFORMANCE_PARAMETER_TYPE_RANGE_SIZE_INTEL = (VK_PERFORMANCE_PARAMETER_TYPE_STREAM_MARKER_VALID_BITS_INTEL - VK_PERFORMANCE_PARAMETER_TYPE_HW_COUNTERS_SUPPORTED_INTEL + 1), VK_PERFORMANCE_PARAMETER_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF } VkPerformanceParameterTypeINTEL; @@ -10057,9 +10417,6 @@ typedef enum VkPerformanceValueTypeINTEL { VK_PERFORMANCE_VALUE_TYPE_FLOAT_INTEL = 2, VK_PERFORMANCE_VALUE_TYPE_BOOL_INTEL = 3, VK_PERFORMANCE_VALUE_TYPE_STRING_INTEL = 4, - VK_PERFORMANCE_VALUE_TYPE_BEGIN_RANGE_INTEL = VK_PERFORMANCE_VALUE_TYPE_UINT32_INTEL, - VK_PERFORMANCE_VALUE_TYPE_END_RANGE_INTEL = VK_PERFORMANCE_VALUE_TYPE_STRING_INTEL, - VK_PERFORMANCE_VALUE_TYPE_RANGE_SIZE_INTEL = (VK_PERFORMANCE_VALUE_TYPE_STRING_INTEL - VK_PERFORMANCE_VALUE_TYPE_UINT32_INTEL + 1), VK_PERFORMANCE_VALUE_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF } VkPerformanceValueTypeINTEL; typedef union VkPerformanceValueDataINTEL { @@ -10081,11 +10438,13 @@ typedef struct VkInitializePerformanceApiInfoINTEL { void* pUserData; } VkInitializePerformanceApiInfoINTEL; -typedef struct VkQueryPoolCreateInfoINTEL { +typedef struct VkQueryPoolPerformanceQueryCreateInfoINTEL { VkStructureType sType; const void* pNext; VkQueryPoolSamplingModeINTEL performanceCountersSampling; -} VkQueryPoolCreateInfoINTEL; +} VkQueryPoolPerformanceQueryCreateInfoINTEL; + +typedef VkQueryPoolPerformanceQueryCreateInfoINTEL VkQueryPoolCreateInfoINTEL; typedef struct VkPerformanceMarkerInfoINTEL { VkStructureType sType; @@ -10301,6 +10660,18 @@ typedef struct VkPhysicalDeviceCoherentMemoryFeaturesAMD { +#define VK_EXT_shader_image_atomic_int64 1 +#define VK_EXT_SHADER_IMAGE_ATOMIC_INT64_SPEC_VERSION 1 +#define VK_EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME "VK_EXT_shader_image_atomic_int64" +typedef struct VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderImageInt64Atomics; + VkBool32 sparseImageInt64Atomics; +} VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT; + + + #define VK_EXT_memory_budget 1 #define VK_EXT_MEMORY_BUDGET_SPEC_VERSION 1 #define VK_EXT_MEMORY_BUDGET_EXTENSION_NAME "VK_EXT_memory_budget" @@ -10414,16 +10785,15 @@ typedef VkImageStencilUsageCreateInfo VkImageStencilUsageCreateInfoEXT; #define VK_EXT_validation_features 1 -#define VK_EXT_VALIDATION_FEATURES_SPEC_VERSION 2 +#define VK_EXT_VALIDATION_FEATURES_SPEC_VERSION 4 #define VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME "VK_EXT_validation_features" typedef enum VkValidationFeatureEnableEXT { VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT = 0, VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT = 1, VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT = 2, - VK_VALIDATION_FEATURE_ENABLE_BEGIN_RANGE_EXT = VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT, - VK_VALIDATION_FEATURE_ENABLE_END_RANGE_EXT = VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT, - VK_VALIDATION_FEATURE_ENABLE_RANGE_SIZE_EXT = (VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT - VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT + 1), + VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT = 3, + VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT = 4, VK_VALIDATION_FEATURE_ENABLE_MAX_ENUM_EXT = 0x7FFFFFFF } VkValidationFeatureEnableEXT; @@ -10435,9 +10805,6 @@ typedef enum VkValidationFeatureDisableEXT { VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT = 4, VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT = 5, VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT = 6, - VK_VALIDATION_FEATURE_DISABLE_BEGIN_RANGE_EXT = VK_VALIDATION_FEATURE_DISABLE_ALL_EXT, - VK_VALIDATION_FEATURE_DISABLE_END_RANGE_EXT = VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT, - VK_VALIDATION_FEATURE_DISABLE_RANGE_SIZE_EXT = (VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT - VK_VALIDATION_FEATURE_DISABLE_ALL_EXT + 1), VK_VALIDATION_FEATURE_DISABLE_MAX_ENUM_EXT = 0x7FFFFFFF } VkValidationFeatureDisableEXT; typedef struct VkValidationFeaturesEXT { @@ -10467,9 +10834,6 @@ typedef enum VkComponentTypeNV { VK_COMPONENT_TYPE_UINT16_NV = 8, VK_COMPONENT_TYPE_UINT32_NV = 9, VK_COMPONENT_TYPE_UINT64_NV = 10, - VK_COMPONENT_TYPE_BEGIN_RANGE_NV = VK_COMPONENT_TYPE_FLOAT16_NV, - VK_COMPONENT_TYPE_END_RANGE_NV = VK_COMPONENT_TYPE_UINT64_NV, - VK_COMPONENT_TYPE_RANGE_SIZE_NV = (VK_COMPONENT_TYPE_UINT64_NV - VK_COMPONENT_TYPE_FLOAT16_NV + 1), VK_COMPONENT_TYPE_MAX_ENUM_NV = 0x7FFFFFFF } VkComponentTypeNV; @@ -10478,9 +10842,6 @@ typedef enum VkScopeNV { VK_SCOPE_WORKGROUP_NV = 2, VK_SCOPE_SUBGROUP_NV = 3, VK_SCOPE_QUEUE_FAMILY_NV = 5, - VK_SCOPE_BEGIN_RANGE_NV = VK_SCOPE_DEVICE_NV, - VK_SCOPE_END_RANGE_NV = VK_SCOPE_QUEUE_FAMILY_NV, - VK_SCOPE_RANGE_SIZE_NV = (VK_SCOPE_QUEUE_FAMILY_NV - VK_SCOPE_DEVICE_NV + 1), VK_SCOPE_MAX_ENUM_NV = 0x7FFFFFFF } VkScopeNV; typedef struct VkCooperativeMatrixPropertiesNV { @@ -10526,9 +10887,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCooperativeMatrixPropertiesNV( typedef enum VkCoverageReductionModeNV { VK_COVERAGE_REDUCTION_MODE_MERGE_NV = 0, VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV = 1, - VK_COVERAGE_REDUCTION_MODE_BEGIN_RANGE_NV = VK_COVERAGE_REDUCTION_MODE_MERGE_NV, - VK_COVERAGE_REDUCTION_MODE_END_RANGE_NV = VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV, - VK_COVERAGE_REDUCTION_MODE_RANGE_SIZE_NV = (VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV - VK_COVERAGE_REDUCTION_MODE_MERGE_NV + 1), VK_COVERAGE_REDUCTION_MODE_MAX_ENUM_NV = 0x7FFFFFFF } VkCoverageReductionModeNV; typedef VkFlags VkPipelineCoverageReductionStateCreateFlagsNV; @@ -10618,9 +10976,6 @@ typedef enum VkLineRasterizationModeEXT { VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT = 1, VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT = 2, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT = 3, - VK_LINE_RASTERIZATION_MODE_BEGIN_RANGE_EXT = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT, - VK_LINE_RASTERIZATION_MODE_END_RANGE_EXT = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT, - VK_LINE_RASTERIZATION_MODE_RANGE_SIZE_EXT = (VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT - VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT + 1), VK_LINE_RASTERIZATION_MODE_MAX_ENUM_EXT = 0x7FFFFFFF } VkLineRasterizationModeEXT; typedef struct VkPhysicalDeviceLineRasterizationFeaturesEXT { @@ -10659,6 +11014,28 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetLineStippleEXT( #endif +#define VK_EXT_shader_atomic_float 1 +#define VK_EXT_SHADER_ATOMIC_FLOAT_SPEC_VERSION 1 +#define VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME "VK_EXT_shader_atomic_float" +typedef struct VkPhysicalDeviceShaderAtomicFloatFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderBufferFloat32Atomics; + VkBool32 shaderBufferFloat32AtomicAdd; + VkBool32 shaderBufferFloat64Atomics; + VkBool32 shaderBufferFloat64AtomicAdd; + VkBool32 shaderSharedFloat32Atomics; + VkBool32 shaderSharedFloat32AtomicAdd; + VkBool32 shaderSharedFloat64Atomics; + VkBool32 shaderSharedFloat64AtomicAdd; + VkBool32 shaderImageFloat32Atomics; + VkBool32 shaderImageFloat32AtomicAdd; + VkBool32 sparseImageFloat32Atomics; + VkBool32 sparseImageFloat32AtomicAdd; +} VkPhysicalDeviceShaderAtomicFloatFeaturesEXT; + + + #define VK_EXT_host_query_reset 1 #define VK_EXT_HOST_QUERY_RESET_SPEC_VERSION 1 #define VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME "VK_EXT_host_query_reset" @@ -10686,6 +11063,90 @@ typedef struct VkPhysicalDeviceIndexTypeUint8FeaturesEXT { +#define VK_EXT_extended_dynamic_state 1 +#define VK_EXT_EXTENDED_DYNAMIC_STATE_SPEC_VERSION 1 +#define VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME "VK_EXT_extended_dynamic_state" +typedef struct VkPhysicalDeviceExtendedDynamicStateFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 extendedDynamicState; +} VkPhysicalDeviceExtendedDynamicStateFeaturesEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetCullModeEXT)(VkCommandBuffer commandBuffer, VkCullModeFlags cullMode); +typedef void (VKAPI_PTR *PFN_vkCmdSetFrontFaceEXT)(VkCommandBuffer commandBuffer, VkFrontFace frontFace); +typedef void (VKAPI_PTR *PFN_vkCmdSetPrimitiveTopologyEXT)(VkCommandBuffer commandBuffer, VkPrimitiveTopology primitiveTopology); +typedef void (VKAPI_PTR *PFN_vkCmdSetViewportWithCountEXT)(VkCommandBuffer commandBuffer, uint32_t viewportCount, const VkViewport* pViewports); +typedef void (VKAPI_PTR *PFN_vkCmdSetScissorWithCountEXT)(VkCommandBuffer commandBuffer, uint32_t scissorCount, const VkRect2D* pScissors); +typedef void (VKAPI_PTR *PFN_vkCmdBindVertexBuffers2EXT)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes, const VkDeviceSize* pStrides); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthTestEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthTestEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthWriteEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthWriteEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthCompareOpEXT)(VkCommandBuffer commandBuffer, VkCompareOp depthCompareOp); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBoundsTestEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthBoundsTestEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetStencilTestEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 stencilTestEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetStencilOpEXT)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetCullModeEXT( + VkCommandBuffer commandBuffer, + VkCullModeFlags cullMode); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetFrontFaceEXT( + VkCommandBuffer commandBuffer, + VkFrontFace frontFace); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetPrimitiveTopologyEXT( + VkCommandBuffer commandBuffer, + VkPrimitiveTopology primitiveTopology); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportWithCountEXT( + VkCommandBuffer commandBuffer, + uint32_t viewportCount, + const VkViewport* pViewports); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetScissorWithCountEXT( + VkCommandBuffer commandBuffer, + uint32_t scissorCount, + const VkRect2D* pScissors); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindVertexBuffers2EXT( + VkCommandBuffer commandBuffer, + uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer* pBuffers, + const VkDeviceSize* pOffsets, + const VkDeviceSize* pSizes, + const VkDeviceSize* pStrides); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthTestEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthTestEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthWriteEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthWriteEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthCompareOpEXT( + VkCommandBuffer commandBuffer, + VkCompareOp depthCompareOp); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBoundsTestEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthBoundsTestEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilTestEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 stencilTestEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilOpEXT( + VkCommandBuffer commandBuffer, + VkStencilFaceFlags faceMask, + VkStencilOp failOp, + VkStencilOp passOp, + VkStencilOp depthFailOp, + VkCompareOp compareOp); +#endif + + #define VK_EXT_shader_demote_to_helper_invocation 1 #define VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_SPEC_VERSION 1 #define VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME "VK_EXT_shader_demote_to_helper_invocation" @@ -10697,6 +11158,196 @@ typedef struct VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT { +#define VK_NV_device_generated_commands 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutNV) +#define VK_NV_DEVICE_GENERATED_COMMANDS_SPEC_VERSION 3 +#define VK_NV_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME "VK_NV_device_generated_commands" + +typedef enum VkIndirectCommandsTokenTypeNV { + VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV = 0, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_STATE_FLAGS_NV = 1, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NV = 2, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NV = 3, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV = 4, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NV = 5, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NV = 6, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_TASKS_NV = 7, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkIndirectCommandsTokenTypeNV; + +typedef enum VkIndirectStateFlagBitsNV { + VK_INDIRECT_STATE_FLAG_FRONTFACE_BIT_NV = 0x00000001, + VK_INDIRECT_STATE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkIndirectStateFlagBitsNV; +typedef VkFlags VkIndirectStateFlagsNV; + +typedef enum VkIndirectCommandsLayoutUsageFlagBitsNV { + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_NV = 0x00000001, + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NV = 0x00000002, + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NV = 0x00000004, + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkIndirectCommandsLayoutUsageFlagBitsNV; +typedef VkFlags VkIndirectCommandsLayoutUsageFlagsNV; +typedef struct VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t maxGraphicsShaderGroupCount; + uint32_t maxIndirectSequenceCount; + uint32_t maxIndirectCommandsTokenCount; + uint32_t maxIndirectCommandsStreamCount; + uint32_t maxIndirectCommandsTokenOffset; + uint32_t maxIndirectCommandsStreamStride; + uint32_t minSequencesCountBufferOffsetAlignment; + uint32_t minSequencesIndexBufferOffsetAlignment; + uint32_t minIndirectCommandsBufferOffsetAlignment; +} VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV; + +typedef struct VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 deviceGeneratedCommands; +} VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV; + +typedef struct VkGraphicsShaderGroupCreateInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t stageCount; + const VkPipelineShaderStageCreateInfo* pStages; + const VkPipelineVertexInputStateCreateInfo* pVertexInputState; + const VkPipelineTessellationStateCreateInfo* pTessellationState; +} VkGraphicsShaderGroupCreateInfoNV; + +typedef struct VkGraphicsPipelineShaderGroupsCreateInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t groupCount; + const VkGraphicsShaderGroupCreateInfoNV* pGroups; + uint32_t pipelineCount; + const VkPipeline* pPipelines; +} VkGraphicsPipelineShaderGroupsCreateInfoNV; + +typedef struct VkBindShaderGroupIndirectCommandNV { + uint32_t groupIndex; +} VkBindShaderGroupIndirectCommandNV; + +typedef struct VkBindIndexBufferIndirectCommandNV { + VkDeviceAddress bufferAddress; + uint32_t size; + VkIndexType indexType; +} VkBindIndexBufferIndirectCommandNV; + +typedef struct VkBindVertexBufferIndirectCommandNV { + VkDeviceAddress bufferAddress; + uint32_t size; + uint32_t stride; +} VkBindVertexBufferIndirectCommandNV; + +typedef struct VkSetStateFlagsIndirectCommandNV { + uint32_t data; +} VkSetStateFlagsIndirectCommandNV; + +typedef struct VkIndirectCommandsStreamNV { + VkBuffer buffer; + VkDeviceSize offset; +} VkIndirectCommandsStreamNV; + +typedef struct VkIndirectCommandsLayoutTokenNV { + VkStructureType sType; + const void* pNext; + VkIndirectCommandsTokenTypeNV tokenType; + uint32_t stream; + uint32_t offset; + uint32_t vertexBindingUnit; + VkBool32 vertexDynamicStride; + VkPipelineLayout pushconstantPipelineLayout; + VkShaderStageFlags pushconstantShaderStageFlags; + uint32_t pushconstantOffset; + uint32_t pushconstantSize; + VkIndirectStateFlagsNV indirectStateFlags; + uint32_t indexTypeCount; + const VkIndexType* pIndexTypes; + const uint32_t* pIndexTypeValues; +} VkIndirectCommandsLayoutTokenNV; + +typedef struct VkIndirectCommandsLayoutCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkIndirectCommandsLayoutUsageFlagsNV flags; + VkPipelineBindPoint pipelineBindPoint; + uint32_t tokenCount; + const VkIndirectCommandsLayoutTokenNV* pTokens; + uint32_t streamCount; + const uint32_t* pStreamStrides; +} VkIndirectCommandsLayoutCreateInfoNV; + +typedef struct VkGeneratedCommandsInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineBindPoint pipelineBindPoint; + VkPipeline pipeline; + VkIndirectCommandsLayoutNV indirectCommandsLayout; + uint32_t streamCount; + const VkIndirectCommandsStreamNV* pStreams; + uint32_t sequencesCount; + VkBuffer preprocessBuffer; + VkDeviceSize preprocessOffset; + VkDeviceSize preprocessSize; + VkBuffer sequencesCountBuffer; + VkDeviceSize sequencesCountOffset; + VkBuffer sequencesIndexBuffer; + VkDeviceSize sequencesIndexOffset; +} VkGeneratedCommandsInfoNV; + +typedef struct VkGeneratedCommandsMemoryRequirementsInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineBindPoint pipelineBindPoint; + VkPipeline pipeline; + VkIndirectCommandsLayoutNV indirectCommandsLayout; + uint32_t maxSequencesCount; +} VkGeneratedCommandsMemoryRequirementsInfoNV; + +typedef void (VKAPI_PTR *PFN_vkGetGeneratedCommandsMemoryRequirementsNV)(VkDevice device, const VkGeneratedCommandsMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkCmdPreprocessGeneratedCommandsNV)(VkCommandBuffer commandBuffer, const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); +typedef void (VKAPI_PTR *PFN_vkCmdExecuteGeneratedCommandsNV)(VkCommandBuffer commandBuffer, VkBool32 isPreprocessed, const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBindPipelineShaderGroupNV)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline, uint32_t groupIndex); +typedef VkResult (VKAPI_PTR *PFN_vkCreateIndirectCommandsLayoutNV)(VkDevice device, const VkIndirectCommandsLayoutCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkIndirectCommandsLayoutNV* pIndirectCommandsLayout); +typedef void (VKAPI_PTR *PFN_vkDestroyIndirectCommandsLayoutNV)(VkDevice device, VkIndirectCommandsLayoutNV indirectCommandsLayout, const VkAllocationCallbacks* pAllocator); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetGeneratedCommandsMemoryRequirementsNV( + VkDevice device, + const VkGeneratedCommandsMemoryRequirementsInfoNV* pInfo, + VkMemoryRequirements2* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkCmdPreprocessGeneratedCommandsNV( + VkCommandBuffer commandBuffer, + const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdExecuteGeneratedCommandsNV( + VkCommandBuffer commandBuffer, + VkBool32 isPreprocessed, + const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindPipelineShaderGroupNV( + VkCommandBuffer commandBuffer, + VkPipelineBindPoint pipelineBindPoint, + VkPipeline pipeline, + uint32_t groupIndex); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateIndirectCommandsLayoutNV( + VkDevice device, + const VkIndirectCommandsLayoutCreateInfoNV* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkIndirectCommandsLayoutNV* pIndirectCommandsLayout); + +VKAPI_ATTR void VKAPI_CALL vkDestroyIndirectCommandsLayoutNV( + VkDevice device, + VkIndirectCommandsLayoutNV indirectCommandsLayout, + const VkAllocationCallbacks* pAllocator); +#endif + + #define VK_EXT_texel_buffer_alignment 1 #define VK_EXT_TEXEL_BUFFER_ALIGNMENT_SPEC_VERSION 1 #define VK_EXT_TEXEL_BUFFER_ALIGNMENT_EXTENSION_NAME "VK_EXT_texel_buffer_alignment" @@ -10717,10 +11368,815 @@ typedef struct VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT { +#define VK_QCOM_render_pass_transform 1 +#define VK_QCOM_RENDER_PASS_TRANSFORM_SPEC_VERSION 1 +#define VK_QCOM_RENDER_PASS_TRANSFORM_EXTENSION_NAME "VK_QCOM_render_pass_transform" +typedef struct VkRenderPassTransformBeginInfoQCOM { + VkStructureType sType; + void* pNext; + VkSurfaceTransformFlagBitsKHR transform; +} VkRenderPassTransformBeginInfoQCOM; + +typedef struct VkCommandBufferInheritanceRenderPassTransformInfoQCOM { + VkStructureType sType; + void* pNext; + VkSurfaceTransformFlagBitsKHR transform; + VkRect2D renderArea; +} VkCommandBufferInheritanceRenderPassTransformInfoQCOM; + + + +#define VK_EXT_device_memory_report 1 +#define VK_EXT_DEVICE_MEMORY_REPORT_SPEC_VERSION 2 +#define VK_EXT_DEVICE_MEMORY_REPORT_EXTENSION_NAME "VK_EXT_device_memory_report" + +typedef enum VkDeviceMemoryReportEventTypeEXT { + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATE_EXT = 0, + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_FREE_EXT = 1, + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_IMPORT_EXT = 2, + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_UNIMPORT_EXT = 3, + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATION_FAILED_EXT = 4, + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDeviceMemoryReportEventTypeEXT; +typedef VkFlags VkDeviceMemoryReportFlagsEXT; +typedef struct VkPhysicalDeviceDeviceMemoryReportFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 deviceMemoryReport; +} VkPhysicalDeviceDeviceMemoryReportFeaturesEXT; + +typedef struct VkDeviceMemoryReportCallbackDataEXT { + VkStructureType sType; + const void* pNext; + VkDeviceMemoryReportFlagsEXT flags; + VkDeviceMemoryReportEventTypeEXT type; + uint64_t memoryObjectId; + VkDeviceSize size; + VkObjectType objectType; + uint64_t objectHandle; + uint32_t heapIndex; +} VkDeviceMemoryReportCallbackDataEXT; + +typedef void (VKAPI_PTR *PFN_vkDeviceMemoryReportCallbackEXT)( + const VkDeviceMemoryReportCallbackDataEXT* pCallbackData, + void* pUserData); + +typedef struct VkDeviceDeviceMemoryReportCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceMemoryReportFlagsEXT flags; + PFN_vkDeviceMemoryReportCallbackEXT pfnUserCallback; + void* pUserData; +} VkDeviceDeviceMemoryReportCreateInfoEXT; + + + +#define VK_EXT_robustness2 1 +#define VK_EXT_ROBUSTNESS_2_SPEC_VERSION 1 +#define VK_EXT_ROBUSTNESS_2_EXTENSION_NAME "VK_EXT_robustness2" +typedef struct VkPhysicalDeviceRobustness2FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 robustBufferAccess2; + VkBool32 robustImageAccess2; + VkBool32 nullDescriptor; +} VkPhysicalDeviceRobustness2FeaturesEXT; + +typedef struct VkPhysicalDeviceRobustness2PropertiesEXT { + VkStructureType sType; + void* pNext; + VkDeviceSize robustStorageBufferAccessSizeAlignment; + VkDeviceSize robustUniformBufferAccessSizeAlignment; +} VkPhysicalDeviceRobustness2PropertiesEXT; + + + +#define VK_EXT_custom_border_color 1 +#define VK_EXT_CUSTOM_BORDER_COLOR_SPEC_VERSION 12 +#define VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME "VK_EXT_custom_border_color" +typedef struct VkSamplerCustomBorderColorCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkClearColorValue customBorderColor; + VkFormat format; +} VkSamplerCustomBorderColorCreateInfoEXT; + +typedef struct VkPhysicalDeviceCustomBorderColorPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxCustomBorderColorSamplers; +} VkPhysicalDeviceCustomBorderColorPropertiesEXT; + +typedef struct VkPhysicalDeviceCustomBorderColorFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 customBorderColors; + VkBool32 customBorderColorWithoutFormat; +} VkPhysicalDeviceCustomBorderColorFeaturesEXT; + + + #define VK_GOOGLE_user_type 1 #define VK_GOOGLE_USER_TYPE_SPEC_VERSION 1 #define VK_GOOGLE_USER_TYPE_EXTENSION_NAME "VK_GOOGLE_user_type" + +#define VK_EXT_private_data 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPrivateDataSlotEXT) +#define VK_EXT_PRIVATE_DATA_SPEC_VERSION 1 +#define VK_EXT_PRIVATE_DATA_EXTENSION_NAME "VK_EXT_private_data" + +typedef enum VkPrivateDataSlotCreateFlagBitsEXT { + VK_PRIVATE_DATA_SLOT_CREATE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkPrivateDataSlotCreateFlagBitsEXT; +typedef VkFlags VkPrivateDataSlotCreateFlagsEXT; +typedef struct VkPhysicalDevicePrivateDataFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 privateData; +} VkPhysicalDevicePrivateDataFeaturesEXT; + +typedef struct VkDevicePrivateDataCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t privateDataSlotRequestCount; +} VkDevicePrivateDataCreateInfoEXT; + +typedef struct VkPrivateDataSlotCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkPrivateDataSlotCreateFlagsEXT flags; +} VkPrivateDataSlotCreateInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkCreatePrivateDataSlotEXT)(VkDevice device, const VkPrivateDataSlotCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPrivateDataSlotEXT* pPrivateDataSlot); +typedef void (VKAPI_PTR *PFN_vkDestroyPrivateDataSlotEXT)(VkDevice device, VkPrivateDataSlotEXT privateDataSlot, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkSetPrivateDataEXT)(VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlotEXT privateDataSlot, uint64_t data); +typedef void (VKAPI_PTR *PFN_vkGetPrivateDataEXT)(VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlotEXT privateDataSlot, uint64_t* pData); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreatePrivateDataSlotEXT( + VkDevice device, + const VkPrivateDataSlotCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkPrivateDataSlotEXT* pPrivateDataSlot); + +VKAPI_ATTR void VKAPI_CALL vkDestroyPrivateDataSlotEXT( + VkDevice device, + VkPrivateDataSlotEXT privateDataSlot, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkSetPrivateDataEXT( + VkDevice device, + VkObjectType objectType, + uint64_t objectHandle, + VkPrivateDataSlotEXT privateDataSlot, + uint64_t data); + +VKAPI_ATTR void VKAPI_CALL vkGetPrivateDataEXT( + VkDevice device, + VkObjectType objectType, + uint64_t objectHandle, + VkPrivateDataSlotEXT privateDataSlot, + uint64_t* pData); +#endif + + +#define VK_EXT_pipeline_creation_cache_control 1 +#define VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_SPEC_VERSION 3 +#define VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME "VK_EXT_pipeline_creation_cache_control" +typedef struct VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 pipelineCreationCacheControl; +} VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT; + + + +#define VK_NV_device_diagnostics_config 1 +#define VK_NV_DEVICE_DIAGNOSTICS_CONFIG_SPEC_VERSION 1 +#define VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME "VK_NV_device_diagnostics_config" + +typedef enum VkDeviceDiagnosticsConfigFlagBitsNV { + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV = 0x00000001, + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV = 0x00000002, + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV = 0x00000004, + VK_DEVICE_DIAGNOSTICS_CONFIG_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkDeviceDiagnosticsConfigFlagBitsNV; +typedef VkFlags VkDeviceDiagnosticsConfigFlagsNV; +typedef struct VkPhysicalDeviceDiagnosticsConfigFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 diagnosticsConfig; +} VkPhysicalDeviceDiagnosticsConfigFeaturesNV; + +typedef struct VkDeviceDiagnosticsConfigCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkDeviceDiagnosticsConfigFlagsNV flags; +} VkDeviceDiagnosticsConfigCreateInfoNV; + + + +#define VK_QCOM_render_pass_store_ops 1 +#define VK_QCOM_render_pass_store_ops_SPEC_VERSION 2 +#define VK_QCOM_render_pass_store_ops_EXTENSION_NAME "VK_QCOM_render_pass_store_ops" + + +#define VK_NV_fragment_shading_rate_enums 1 +#define VK_NV_FRAGMENT_SHADING_RATE_ENUMS_SPEC_VERSION 1 +#define VK_NV_FRAGMENT_SHADING_RATE_ENUMS_EXTENSION_NAME "VK_NV_fragment_shading_rate_enums" + +typedef enum VkFragmentShadingRateTypeNV { + VK_FRAGMENT_SHADING_RATE_TYPE_FRAGMENT_SIZE_NV = 0, + VK_FRAGMENT_SHADING_RATE_TYPE_ENUMS_NV = 1, + VK_FRAGMENT_SHADING_RATE_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkFragmentShadingRateTypeNV; + +typedef enum VkFragmentShadingRateNV { + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_PIXEL_NV = 0, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_1X2_PIXELS_NV = 1, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X1_PIXELS_NV = 4, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X2_PIXELS_NV = 5, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X4_PIXELS_NV = 6, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X2_PIXELS_NV = 9, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X4_PIXELS_NV = 10, + VK_FRAGMENT_SHADING_RATE_2_INVOCATIONS_PER_PIXEL_NV = 11, + VK_FRAGMENT_SHADING_RATE_4_INVOCATIONS_PER_PIXEL_NV = 12, + VK_FRAGMENT_SHADING_RATE_8_INVOCATIONS_PER_PIXEL_NV = 13, + VK_FRAGMENT_SHADING_RATE_16_INVOCATIONS_PER_PIXEL_NV = 14, + VK_FRAGMENT_SHADING_RATE_NO_INVOCATIONS_NV = 15, + VK_FRAGMENT_SHADING_RATE_MAX_ENUM_NV = 0x7FFFFFFF +} VkFragmentShadingRateNV; +typedef struct VkPhysicalDeviceFragmentShadingRateEnumsFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 fragmentShadingRateEnums; + VkBool32 supersampleFragmentShadingRates; + VkBool32 noInvocationFragmentShadingRates; +} VkPhysicalDeviceFragmentShadingRateEnumsFeaturesNV; + +typedef struct VkPhysicalDeviceFragmentShadingRateEnumsPropertiesNV { + VkStructureType sType; + void* pNext; + VkSampleCountFlagBits maxFragmentShadingRateInvocationCount; +} VkPhysicalDeviceFragmentShadingRateEnumsPropertiesNV; + +typedef struct VkPipelineFragmentShadingRateEnumStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkFragmentShadingRateTypeNV shadingRateType; + VkFragmentShadingRateNV shadingRate; + VkFragmentShadingRateCombinerOpKHR combinerOps[2]; +} VkPipelineFragmentShadingRateEnumStateCreateInfoNV; + +typedef void (VKAPI_PTR *PFN_vkCmdSetFragmentShadingRateEnumNV)(VkCommandBuffer commandBuffer, VkFragmentShadingRateNV shadingRate, const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetFragmentShadingRateEnumNV( + VkCommandBuffer commandBuffer, + VkFragmentShadingRateNV shadingRate, + const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); +#endif + + +#define VK_EXT_fragment_density_map2 1 +#define VK_EXT_FRAGMENT_DENSITY_MAP_2_SPEC_VERSION 1 +#define VK_EXT_FRAGMENT_DENSITY_MAP_2_EXTENSION_NAME "VK_EXT_fragment_density_map2" +typedef struct VkPhysicalDeviceFragmentDensityMap2FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 fragmentDensityMapDeferred; +} VkPhysicalDeviceFragmentDensityMap2FeaturesEXT; + +typedef struct VkPhysicalDeviceFragmentDensityMap2PropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 subsampledLoads; + VkBool32 subsampledCoarseReconstructionEarlyAccess; + uint32_t maxSubsampledArrayLayers; + uint32_t maxDescriptorSetSubsampledSamplers; +} VkPhysicalDeviceFragmentDensityMap2PropertiesEXT; + + + +#define VK_QCOM_rotated_copy_commands 1 +#define VK_QCOM_ROTATED_COPY_COMMANDS_SPEC_VERSION 0 +#define VK_QCOM_ROTATED_COPY_COMMANDS_EXTENSION_NAME "VK_QCOM_rotated_copy_commands" +typedef struct VkCopyCommandTransformInfoQCOM { + VkStructureType sType; + const void* pNext; + VkSurfaceTransformFlagBitsKHR transform; +} VkCopyCommandTransformInfoQCOM; + + + +#define VK_EXT_image_robustness 1 +#define VK_EXT_IMAGE_ROBUSTNESS_SPEC_VERSION 1 +#define VK_EXT_IMAGE_ROBUSTNESS_EXTENSION_NAME "VK_EXT_image_robustness" +typedef struct VkPhysicalDeviceImageRobustnessFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 robustImageAccess; +} VkPhysicalDeviceImageRobustnessFeaturesEXT; + + + +#define VK_EXT_4444_formats 1 +#define VK_EXT_4444_FORMATS_SPEC_VERSION 1 +#define VK_EXT_4444_FORMATS_EXTENSION_NAME "VK_EXT_4444_formats" +typedef struct VkPhysicalDevice4444FormatsFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 formatA4R4G4B4; + VkBool32 formatA4B4G4R4; +} VkPhysicalDevice4444FormatsFeaturesEXT; + + + +#define VK_NV_acquire_winrt_display 1 +#define VK_NV_ACQUIRE_WINRT_DISPLAY_SPEC_VERSION 1 +#define VK_NV_ACQUIRE_WINRT_DISPLAY_EXTENSION_NAME "VK_NV_acquire_winrt_display" +typedef VkResult (VKAPI_PTR *PFN_vkAcquireWinrtDisplayNV)(VkPhysicalDevice physicalDevice, VkDisplayKHR display); +typedef VkResult (VKAPI_PTR *PFN_vkGetWinrtDisplayNV)(VkPhysicalDevice physicalDevice, uint32_t deviceRelativeId, VkDisplayKHR* pDisplay); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireWinrtDisplayNV( + VkPhysicalDevice physicalDevice, + VkDisplayKHR display); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetWinrtDisplayNV( + VkPhysicalDevice physicalDevice, + uint32_t deviceRelativeId, + VkDisplayKHR* pDisplay); +#endif + + +#define VK_VALVE_mutable_descriptor_type 1 +#define VK_VALVE_MUTABLE_DESCRIPTOR_TYPE_SPEC_VERSION 1 +#define VK_VALVE_MUTABLE_DESCRIPTOR_TYPE_EXTENSION_NAME "VK_VALVE_mutable_descriptor_type" +typedef struct VkPhysicalDeviceMutableDescriptorTypeFeaturesVALVE { + VkStructureType sType; + void* pNext; + VkBool32 mutableDescriptorType; +} VkPhysicalDeviceMutableDescriptorTypeFeaturesVALVE; + +typedef struct VkMutableDescriptorTypeListVALVE { + uint32_t descriptorTypeCount; + const VkDescriptorType* pDescriptorTypes; +} VkMutableDescriptorTypeListVALVE; + +typedef struct VkMutableDescriptorTypeCreateInfoVALVE { + VkStructureType sType; + const void* pNext; + uint32_t mutableDescriptorTypeListCount; + const VkMutableDescriptorTypeListVALVE* pMutableDescriptorTypeLists; +} VkMutableDescriptorTypeCreateInfoVALVE; + + + +#define VK_KHR_acceleration_structure 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureKHR) +#define VK_KHR_ACCELERATION_STRUCTURE_SPEC_VERSION 11 +#define VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME "VK_KHR_acceleration_structure" + +typedef enum VkBuildAccelerationStructureModeKHR { + VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR = 0, + VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR = 1, + VK_BUILD_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkBuildAccelerationStructureModeKHR; + +typedef enum VkAccelerationStructureBuildTypeKHR { + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR = 0, + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR = 1, + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR = 2, + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureBuildTypeKHR; + +typedef enum VkAccelerationStructureCompatibilityKHR { + VK_ACCELERATION_STRUCTURE_COMPATIBILITY_COMPATIBLE_KHR = 0, + VK_ACCELERATION_STRUCTURE_COMPATIBILITY_INCOMPATIBLE_KHR = 1, + VK_ACCELERATION_STRUCTURE_COMPATIBILITY_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureCompatibilityKHR; + +typedef enum VkAccelerationStructureCreateFlagBitsKHR { + VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR = 0x00000001, + VK_ACCELERATION_STRUCTURE_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureCreateFlagBitsKHR; +typedef VkFlags VkAccelerationStructureCreateFlagsKHR; +typedef union VkDeviceOrHostAddressKHR { + VkDeviceAddress deviceAddress; + void* hostAddress; +} VkDeviceOrHostAddressKHR; + +typedef union VkDeviceOrHostAddressConstKHR { + VkDeviceAddress deviceAddress; + const void* hostAddress; +} VkDeviceOrHostAddressConstKHR; + +typedef struct VkAccelerationStructureBuildRangeInfoKHR { + uint32_t primitiveCount; + uint32_t primitiveOffset; + uint32_t firstVertex; + uint32_t transformOffset; +} VkAccelerationStructureBuildRangeInfoKHR; + +typedef struct VkAccelerationStructureGeometryTrianglesDataKHR { + VkStructureType sType; + const void* pNext; + VkFormat vertexFormat; + VkDeviceOrHostAddressConstKHR vertexData; + VkDeviceSize vertexStride; + uint32_t maxVertex; + VkIndexType indexType; + VkDeviceOrHostAddressConstKHR indexData; + VkDeviceOrHostAddressConstKHR transformData; +} VkAccelerationStructureGeometryTrianglesDataKHR; + +typedef struct VkAccelerationStructureGeometryAabbsDataKHR { + VkStructureType sType; + const void* pNext; + VkDeviceOrHostAddressConstKHR data; + VkDeviceSize stride; +} VkAccelerationStructureGeometryAabbsDataKHR; + +typedef struct VkAccelerationStructureGeometryInstancesDataKHR { + VkStructureType sType; + const void* pNext; + VkBool32 arrayOfPointers; + VkDeviceOrHostAddressConstKHR data; +} VkAccelerationStructureGeometryInstancesDataKHR; + +typedef union VkAccelerationStructureGeometryDataKHR { + VkAccelerationStructureGeometryTrianglesDataKHR triangles; + VkAccelerationStructureGeometryAabbsDataKHR aabbs; + VkAccelerationStructureGeometryInstancesDataKHR instances; +} VkAccelerationStructureGeometryDataKHR; + +typedef struct VkAccelerationStructureGeometryKHR { + VkStructureType sType; + const void* pNext; + VkGeometryTypeKHR geometryType; + VkAccelerationStructureGeometryDataKHR geometry; + VkGeometryFlagsKHR flags; +} VkAccelerationStructureGeometryKHR; + +typedef struct VkAccelerationStructureBuildGeometryInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureTypeKHR type; + VkBuildAccelerationStructureFlagsKHR flags; + VkBuildAccelerationStructureModeKHR mode; + VkAccelerationStructureKHR srcAccelerationStructure; + VkAccelerationStructureKHR dstAccelerationStructure; + uint32_t geometryCount; + const VkAccelerationStructureGeometryKHR* pGeometries; + const VkAccelerationStructureGeometryKHR* const* ppGeometries; + VkDeviceOrHostAddressKHR scratchData; +} VkAccelerationStructureBuildGeometryInfoKHR; + +typedef struct VkAccelerationStructureCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureCreateFlagsKHR createFlags; + VkBuffer buffer; + VkDeviceSize offset; + VkDeviceSize size; + VkAccelerationStructureTypeKHR type; + VkDeviceAddress deviceAddress; +} VkAccelerationStructureCreateInfoKHR; + +typedef struct VkWriteDescriptorSetAccelerationStructureKHR { + VkStructureType sType; + const void* pNext; + uint32_t accelerationStructureCount; + const VkAccelerationStructureKHR* pAccelerationStructures; +} VkWriteDescriptorSetAccelerationStructureKHR; + +typedef struct VkPhysicalDeviceAccelerationStructureFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 accelerationStructure; + VkBool32 accelerationStructureCaptureReplay; + VkBool32 accelerationStructureIndirectBuild; + VkBool32 accelerationStructureHostCommands; + VkBool32 descriptorBindingAccelerationStructureUpdateAfterBind; +} VkPhysicalDeviceAccelerationStructureFeaturesKHR; + +typedef struct VkPhysicalDeviceAccelerationStructurePropertiesKHR { + VkStructureType sType; + void* pNext; + uint64_t maxGeometryCount; + uint64_t maxInstanceCount; + uint64_t maxPrimitiveCount; + uint32_t maxPerStageDescriptorAccelerationStructures; + uint32_t maxPerStageDescriptorUpdateAfterBindAccelerationStructures; + uint32_t maxDescriptorSetAccelerationStructures; + uint32_t maxDescriptorSetUpdateAfterBindAccelerationStructures; + uint32_t minAccelerationStructureScratchOffsetAlignment; +} VkPhysicalDeviceAccelerationStructurePropertiesKHR; + +typedef struct VkAccelerationStructureDeviceAddressInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureKHR accelerationStructure; +} VkAccelerationStructureDeviceAddressInfoKHR; + +typedef struct VkAccelerationStructureVersionInfoKHR { + VkStructureType sType; + const void* pNext; + const uint8_t* pVersionData; +} VkAccelerationStructureVersionInfoKHR; + +typedef struct VkCopyAccelerationStructureToMemoryInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureKHR src; + VkDeviceOrHostAddressKHR dst; + VkCopyAccelerationStructureModeKHR mode; +} VkCopyAccelerationStructureToMemoryInfoKHR; + +typedef struct VkCopyMemoryToAccelerationStructureInfoKHR { + VkStructureType sType; + const void* pNext; + VkDeviceOrHostAddressConstKHR src; + VkAccelerationStructureKHR dst; + VkCopyAccelerationStructureModeKHR mode; +} VkCopyMemoryToAccelerationStructureInfoKHR; + +typedef struct VkCopyAccelerationStructureInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureKHR src; + VkAccelerationStructureKHR dst; + VkCopyAccelerationStructureModeKHR mode; +} VkCopyAccelerationStructureInfoKHR; + +typedef struct VkAccelerationStructureBuildSizesInfoKHR { + VkStructureType sType; + const void* pNext; + VkDeviceSize accelerationStructureSize; + VkDeviceSize updateScratchSize; + VkDeviceSize buildScratchSize; +} VkAccelerationStructureBuildSizesInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateAccelerationStructureKHR)(VkDevice device, const VkAccelerationStructureCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureKHR* pAccelerationStructure); +typedef void (VKAPI_PTR *PFN_vkDestroyAccelerationStructureKHR)(VkDevice device, VkAccelerationStructureKHR accelerationStructure, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructuresKHR)(VkCommandBuffer commandBuffer, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos); +typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructuresIndirectKHR)(VkCommandBuffer commandBuffer, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkDeviceAddress* pIndirectDeviceAddresses, const uint32_t* pIndirectStrides, const uint32_t* const* ppMaxPrimitiveCounts); +typedef VkResult (VKAPI_PTR *PFN_vkBuildAccelerationStructuresKHR)(VkDevice device, VkDeferredOperationKHR deferredOperation, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos); +typedef VkResult (VKAPI_PTR *PFN_vkCopyAccelerationStructureKHR)(VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyAccelerationStructureInfoKHR* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCopyAccelerationStructureToMemoryKHR)(VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCopyMemoryToAccelerationStructureKHR)(VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkWriteAccelerationStructuresPropertiesKHR)(VkDevice device, uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, size_t dataSize, void* pData, size_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureKHR)(VkCommandBuffer commandBuffer, const VkCopyAccelerationStructureInfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureToMemoryKHR)(VkCommandBuffer commandBuffer, const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyMemoryToAccelerationStructureKHR)(VkCommandBuffer commandBuffer, const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); +typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetAccelerationStructureDeviceAddressKHR)(VkDevice device, const VkAccelerationStructureDeviceAddressInfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructuresPropertiesKHR)(VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); +typedef void (VKAPI_PTR *PFN_vkGetDeviceAccelerationStructureCompatibilityKHR)(VkDevice device, const VkAccelerationStructureVersionInfoKHR* pVersionInfo, VkAccelerationStructureCompatibilityKHR* pCompatibility); +typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureBuildSizesKHR)(VkDevice device, VkAccelerationStructureBuildTypeKHR buildType, const VkAccelerationStructureBuildGeometryInfoKHR* pBuildInfo, const uint32_t* pMaxPrimitiveCounts, VkAccelerationStructureBuildSizesInfoKHR* pSizeInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateAccelerationStructureKHR( + VkDevice device, + const VkAccelerationStructureCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkAccelerationStructureKHR* pAccelerationStructure); + +VKAPI_ATTR void VKAPI_CALL vkDestroyAccelerationStructureKHR( + VkDevice device, + VkAccelerationStructureKHR accelerationStructure, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructuresKHR( + VkCommandBuffer commandBuffer, + uint32_t infoCount, + const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, + const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos); + +VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructuresIndirectKHR( + VkCommandBuffer commandBuffer, + uint32_t infoCount, + const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, + const VkDeviceAddress* pIndirectDeviceAddresses, + const uint32_t* pIndirectStrides, + const uint32_t* const* ppMaxPrimitiveCounts); + +VKAPI_ATTR VkResult VKAPI_CALL vkBuildAccelerationStructuresKHR( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + uint32_t infoCount, + const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, + const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos); + +VKAPI_ATTR VkResult VKAPI_CALL vkCopyAccelerationStructureKHR( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + const VkCopyAccelerationStructureInfoKHR* pInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkCopyAccelerationStructureToMemoryKHR( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkCopyMemoryToAccelerationStructureKHR( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkWriteAccelerationStructuresPropertiesKHR( + VkDevice device, + uint32_t accelerationStructureCount, + const VkAccelerationStructureKHR* pAccelerationStructures, + VkQueryType queryType, + size_t dataSize, + void* pData, + size_t stride); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureKHR( + VkCommandBuffer commandBuffer, + const VkCopyAccelerationStructureInfoKHR* pInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureToMemoryKHR( + VkCommandBuffer commandBuffer, + const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryToAccelerationStructureKHR( + VkCommandBuffer commandBuffer, + const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); + +VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetAccelerationStructureDeviceAddressKHR( + VkDevice device, + const VkAccelerationStructureDeviceAddressInfoKHR* pInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructuresPropertiesKHR( + VkCommandBuffer commandBuffer, + uint32_t accelerationStructureCount, + const VkAccelerationStructureKHR* pAccelerationStructures, + VkQueryType queryType, + VkQueryPool queryPool, + uint32_t firstQuery); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceAccelerationStructureCompatibilityKHR( + VkDevice device, + const VkAccelerationStructureVersionInfoKHR* pVersionInfo, + VkAccelerationStructureCompatibilityKHR* pCompatibility); + +VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureBuildSizesKHR( + VkDevice device, + VkAccelerationStructureBuildTypeKHR buildType, + const VkAccelerationStructureBuildGeometryInfoKHR* pBuildInfo, + const uint32_t* pMaxPrimitiveCounts, + VkAccelerationStructureBuildSizesInfoKHR* pSizeInfo); +#endif + + +#define VK_KHR_ray_tracing_pipeline 1 +#define VK_KHR_RAY_TRACING_PIPELINE_SPEC_VERSION 1 +#define VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME "VK_KHR_ray_tracing_pipeline" + +typedef enum VkShaderGroupShaderKHR { + VK_SHADER_GROUP_SHADER_GENERAL_KHR = 0, + VK_SHADER_GROUP_SHADER_CLOSEST_HIT_KHR = 1, + VK_SHADER_GROUP_SHADER_ANY_HIT_KHR = 2, + VK_SHADER_GROUP_SHADER_INTERSECTION_KHR = 3, + VK_SHADER_GROUP_SHADER_MAX_ENUM_KHR = 0x7FFFFFFF +} VkShaderGroupShaderKHR; +typedef struct VkRayTracingShaderGroupCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkRayTracingShaderGroupTypeKHR type; + uint32_t generalShader; + uint32_t closestHitShader; + uint32_t anyHitShader; + uint32_t intersectionShader; + const void* pShaderGroupCaptureReplayHandle; +} VkRayTracingShaderGroupCreateInfoKHR; + +typedef struct VkRayTracingPipelineInterfaceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t maxPipelineRayPayloadSize; + uint32_t maxPipelineRayHitAttributeSize; +} VkRayTracingPipelineInterfaceCreateInfoKHR; + +typedef struct VkRayTracingPipelineCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkPipelineCreateFlags flags; + uint32_t stageCount; + const VkPipelineShaderStageCreateInfo* pStages; + uint32_t groupCount; + const VkRayTracingShaderGroupCreateInfoKHR* pGroups; + uint32_t maxPipelineRayRecursionDepth; + const VkPipelineLibraryCreateInfoKHR* pLibraryInfo; + const VkRayTracingPipelineInterfaceCreateInfoKHR* pLibraryInterface; + const VkPipelineDynamicStateCreateInfo* pDynamicState; + VkPipelineLayout layout; + VkPipeline basePipelineHandle; + int32_t basePipelineIndex; +} VkRayTracingPipelineCreateInfoKHR; + +typedef struct VkPhysicalDeviceRayTracingPipelineFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 rayTracingPipeline; + VkBool32 rayTracingPipelineShaderGroupHandleCaptureReplay; + VkBool32 rayTracingPipelineShaderGroupHandleCaptureReplayMixed; + VkBool32 rayTracingPipelineTraceRaysIndirect; + VkBool32 rayTraversalPrimitiveCulling; +} VkPhysicalDeviceRayTracingPipelineFeaturesKHR; + +typedef struct VkPhysicalDeviceRayTracingPipelinePropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t shaderGroupHandleSize; + uint32_t maxRayRecursionDepth; + uint32_t maxShaderGroupStride; + uint32_t shaderGroupBaseAlignment; + uint32_t shaderGroupHandleCaptureReplaySize; + uint32_t maxRayDispatchInvocationCount; + uint32_t shaderGroupHandleAlignment; + uint32_t maxRayHitAttributeSize; +} VkPhysicalDeviceRayTracingPipelinePropertiesKHR; + +typedef struct VkStridedDeviceAddressRegionKHR { + VkDeviceAddress deviceAddress; + VkDeviceSize stride; + VkDeviceSize size; +} VkStridedDeviceAddressRegionKHR; + +typedef struct VkTraceRaysIndirectCommandKHR { + uint32_t width; + uint32_t height; + uint32_t depth; +} VkTraceRaysIndirectCommandKHR; + +typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysKHR)(VkCommandBuffer commandBuffer, const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, uint32_t width, uint32_t height, uint32_t depth); +typedef VkResult (VKAPI_PTR *PFN_vkCreateRayTracingPipelinesKHR)(VkDevice device, VkDeferredOperationKHR deferredOperation, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoKHR* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData); +typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysIndirectKHR)(VkCommandBuffer commandBuffer, const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, VkDeviceAddress indirectDeviceAddress); +typedef VkDeviceSize (VKAPI_PTR *PFN_vkGetRayTracingShaderGroupStackSizeKHR)(VkDevice device, VkPipeline pipeline, uint32_t group, VkShaderGroupShaderKHR groupShader); +typedef void (VKAPI_PTR *PFN_vkCmdSetRayTracingPipelineStackSizeKHR)(VkCommandBuffer commandBuffer, uint32_t pipelineStackSize); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysKHR( + VkCommandBuffer commandBuffer, + const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, + uint32_t width, + uint32_t height, + uint32_t depth); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateRayTracingPipelinesKHR( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + VkPipelineCache pipelineCache, + uint32_t createInfoCount, + const VkRayTracingPipelineCreateInfoKHR* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkPipeline* pPipelines); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingCaptureReplayShaderGroupHandlesKHR( + VkDevice device, + VkPipeline pipeline, + uint32_t firstGroup, + uint32_t groupCount, + size_t dataSize, + void* pData); + +VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysIndirectKHR( + VkCommandBuffer commandBuffer, + const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, + VkDeviceAddress indirectDeviceAddress); + +VKAPI_ATTR VkDeviceSize VKAPI_CALL vkGetRayTracingShaderGroupStackSizeKHR( + VkDevice device, + VkPipeline pipeline, + uint32_t group, + VkShaderGroupShaderKHR groupShader); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetRayTracingPipelineStackSizeKHR( + VkCommandBuffer commandBuffer, + uint32_t pipelineStackSize); +#endif + + +#define VK_KHR_ray_query 1 +#define VK_KHR_RAY_QUERY_SPEC_VERSION 1 +#define VK_KHR_RAY_QUERY_EXTENSION_NAME "VK_KHR_ray_query" +typedef struct VkPhysicalDeviceRayQueryFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 rayQuery; +} VkPhysicalDeviceRayQueryFeaturesKHR; + + #ifdef __cplusplus } #endif diff --git a/thirdparty/include/vulkan/vulkan_directfb.h b/thirdparty/include/vulkan/vulkan_directfb.h new file mode 100644 index 000000000..8eaac6e48 --- /dev/null +++ b/thirdparty/include/vulkan/vulkan_directfb.h @@ -0,0 +1,54 @@ +#ifndef VULKAN_DIRECTFB_H_ +#define VULKAN_DIRECTFB_H_ 1 + +/* +** Copyright 2015-2021 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +#define VK_EXT_directfb_surface 1 +#define VK_EXT_DIRECTFB_SURFACE_SPEC_VERSION 1 +#define VK_EXT_DIRECTFB_SURFACE_EXTENSION_NAME "VK_EXT_directfb_surface" +typedef VkFlags VkDirectFBSurfaceCreateFlagsEXT; +typedef struct VkDirectFBSurfaceCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkDirectFBSurfaceCreateFlagsEXT flags; + IDirectFB* dfb; + IDirectFBSurface* surface; +} VkDirectFBSurfaceCreateInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateDirectFBSurfaceEXT)(VkInstance instance, const VkDirectFBSurfaceCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); +typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceDirectFBPresentationSupportEXT)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, IDirectFB* dfb); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDirectFBSurfaceEXT( + VkInstance instance, + const VkDirectFBSurfaceCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); + +VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceDirectFBPresentationSupportEXT( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + IDirectFB* dfb); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/include/vulkan/vulkan_fuchsia.h b/thirdparty/include/vulkan/vulkan_fuchsia.h index e97901480..75284eca7 100644 --- a/thirdparty/include/vulkan/vulkan_fuchsia.h +++ b/thirdparty/include/vulkan/vulkan_fuchsia.h @@ -2,19 +2,9 @@ #define VULKAN_FUCHSIA_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +** SPDX-License-Identifier: Apache-2.0 */ /* diff --git a/thirdparty/include/vulkan/vulkan_ggp.h b/thirdparty/include/vulkan/vulkan_ggp.h index 09b337e6d..9a6a582c5 100644 --- a/thirdparty/include/vulkan/vulkan_ggp.h +++ b/thirdparty/include/vulkan/vulkan_ggp.h @@ -2,19 +2,9 @@ #define VULKAN_GGP_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +** SPDX-License-Identifier: Apache-2.0 */ /* diff --git a/thirdparty/include/vulkan/vulkan_ios.h b/thirdparty/include/vulkan/vulkan_ios.h index 9f8199938..6e7e6afea 100644 --- a/thirdparty/include/vulkan/vulkan_ios.h +++ b/thirdparty/include/vulkan/vulkan_ios.h @@ -2,19 +2,9 @@ #define VULKAN_IOS_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +** SPDX-License-Identifier: Apache-2.0 */ /* @@ -30,7 +20,7 @@ extern "C" { #define VK_MVK_ios_surface 1 -#define VK_MVK_IOS_SURFACE_SPEC_VERSION 2 +#define VK_MVK_IOS_SURFACE_SPEC_VERSION 3 #define VK_MVK_IOS_SURFACE_EXTENSION_NAME "VK_MVK_ios_surface" typedef VkFlags VkIOSSurfaceCreateFlagsMVK; typedef struct VkIOSSurfaceCreateInfoMVK { diff --git a/thirdparty/include/vulkan/vulkan_macos.h b/thirdparty/include/vulkan/vulkan_macos.h index 8c9684778..c49b123d0 100644 --- a/thirdparty/include/vulkan/vulkan_macos.h +++ b/thirdparty/include/vulkan/vulkan_macos.h @@ -2,19 +2,9 @@ #define VULKAN_MACOS_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +** SPDX-License-Identifier: Apache-2.0 */ /* @@ -30,7 +20,7 @@ extern "C" { #define VK_MVK_macos_surface 1 -#define VK_MVK_MACOS_SURFACE_SPEC_VERSION 2 +#define VK_MVK_MACOS_SURFACE_SPEC_VERSION 3 #define VK_MVK_MACOS_SURFACE_EXTENSION_NAME "VK_MVK_macos_surface" typedef VkFlags VkMacOSSurfaceCreateFlagsMVK; typedef struct VkMacOSSurfaceCreateInfoMVK { diff --git a/thirdparty/include/vulkan/vulkan_metal.h b/thirdparty/include/vulkan/vulkan_metal.h index c85d24387..5cf4a703a 100644 --- a/thirdparty/include/vulkan/vulkan_metal.h +++ b/thirdparty/include/vulkan/vulkan_metal.h @@ -2,19 +2,9 @@ #define VULKAN_METAL_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +** SPDX-License-Identifier: Apache-2.0 */ /* diff --git a/thirdparty/include/vulkan/vulkan_vi.h b/thirdparty/include/vulkan/vulkan_vi.h index ee877d9b9..9e0dcca20 100644 --- a/thirdparty/include/vulkan/vulkan_vi.h +++ b/thirdparty/include/vulkan/vulkan_vi.h @@ -2,19 +2,9 @@ #define VULKAN_VI_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +** SPDX-License-Identifier: Apache-2.0 */ /* diff --git a/thirdparty/include/vulkan/vulkan_wayland.h b/thirdparty/include/vulkan/vulkan_wayland.h index 5278c188b..2a329be9d 100644 --- a/thirdparty/include/vulkan/vulkan_wayland.h +++ b/thirdparty/include/vulkan/vulkan_wayland.h @@ -2,19 +2,9 @@ #define VULKAN_WAYLAND_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +** SPDX-License-Identifier: Apache-2.0 */ /* diff --git a/thirdparty/include/vulkan/vulkan_win32.h b/thirdparty/include/vulkan/vulkan_win32.h index a6c4af0e8..1b680f0b1 100644 --- a/thirdparty/include/vulkan/vulkan_win32.h +++ b/thirdparty/include/vulkan/vulkan_win32.h @@ -2,19 +2,9 @@ #define VULKAN_WIN32_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +** SPDX-License-Identifier: Apache-2.0 */ /* @@ -272,9 +262,6 @@ typedef enum VkFullScreenExclusiveEXT { VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT = 1, VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT = 2, VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT = 3, - VK_FULL_SCREEN_EXCLUSIVE_BEGIN_RANGE_EXT = VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT, - VK_FULL_SCREEN_EXCLUSIVE_END_RANGE_EXT = VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT, - VK_FULL_SCREEN_EXCLUSIVE_RANGE_SIZE_EXT = (VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT - VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT + 1), VK_FULL_SCREEN_EXCLUSIVE_MAX_ENUM_EXT = 0x7FFFFFFF } VkFullScreenExclusiveEXT; typedef struct VkSurfaceFullScreenExclusiveInfoEXT { diff --git a/thirdparty/include/vulkan/vulkan_xcb.h b/thirdparty/include/vulkan/vulkan_xcb.h index 43d1407a8..5ba2ad850 100644 --- a/thirdparty/include/vulkan/vulkan_xcb.h +++ b/thirdparty/include/vulkan/vulkan_xcb.h @@ -2,19 +2,9 @@ #define VULKAN_XCB_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +** SPDX-License-Identifier: Apache-2.0 */ /* diff --git a/thirdparty/include/vulkan/vulkan_xlib.h b/thirdparty/include/vulkan/vulkan_xlib.h index 7beada925..75c75dc2e 100644 --- a/thirdparty/include/vulkan/vulkan_xlib.h +++ b/thirdparty/include/vulkan/vulkan_xlib.h @@ -2,19 +2,9 @@ #define VULKAN_XLIB_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +** SPDX-License-Identifier: Apache-2.0 */ /* diff --git a/thirdparty/include/vulkan/vulkan_xlib_xrandr.h b/thirdparty/include/vulkan/vulkan_xlib_xrandr.h index 8e9e150d8..fa2749342 100644 --- a/thirdparty/include/vulkan/vulkan_xlib_xrandr.h +++ b/thirdparty/include/vulkan/vulkan_xlib_xrandr.h @@ -2,19 +2,9 @@ #define VULKAN_XLIB_XRANDR_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +** SPDX-License-Identifier: Apache-2.0 */ /* From d058a127e11dea76b037c3d217cb80062fb32044 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Mon, 15 Feb 2021 18:14:47 +0100 Subject: [PATCH 053/278] Renderer/RenderPass: Implement RenderPass correctly --- .../OpenGLRenderer/OpenGLRenderPass.hpp | 2 +- include/Nazara/Renderer/Enums.hpp | 113 +++++++++-- include/Nazara/Renderer/RenderPass.hpp | 51 ++++- include/Nazara/Renderer/RenderPass.inl | 33 ++++ include/Nazara/VulkanRenderer/Utils.hpp | 11 ++ include/Nazara/VulkanRenderer/Utils.inl | 166 ++++++++++++++++- .../VulkanRenderer/VulkanRenderPass.hpp | 4 +- .../VulkanRenderer/VulkanRenderPass.inl | 11 -- src/Nazara/VulkanRenderer/VkRenderWindow.cpp | 175 +++++++++--------- .../VulkanCommandBufferBuilder.cpp | 2 +- .../VulkanRenderer/VulkanRenderPass.cpp | 108 +++++++++++ 11 files changed, 543 insertions(+), 133 deletions(-) diff --git a/include/Nazara/OpenGLRenderer/OpenGLRenderPass.hpp b/include/Nazara/OpenGLRenderer/OpenGLRenderPass.hpp index 8c4ff18cd..d60870578 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLRenderPass.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLRenderPass.hpp @@ -17,7 +17,7 @@ namespace Nz class NAZARA_OPENGLRENDERER_API OpenGLRenderPass final : public RenderPass { public: - OpenGLRenderPass() = default; + using RenderPass::RenderPass; OpenGLRenderPass(const OpenGLRenderPass&) = delete; OpenGLRenderPass(OpenGLRenderPass&&) noexcept = default; ~OpenGLRenderPass() = default; diff --git a/include/Nazara/Renderer/Enums.hpp b/include/Nazara/Renderer/Enums.hpp index 0b44ae629..2e3f95286 100644 --- a/include/Nazara/Renderer/Enums.hpp +++ b/include/Nazara/Renderer/Enums.hpp @@ -11,6 +11,96 @@ namespace Nz { + enum class AttachmentLoadOp + { + Clear, + Discard, + Load + }; + + enum class AttachmentStoreOp + { + Discard, + Store + }; + + enum class MemoryAccess + { + ColorRead, + ColorWrite, + DepthStencilRead, + DepthStencilWrite, + IndexBufferRead, + IndirectCommandRead, + HostRead, + HostWrite, + MemoryRead, + MemoryWrite, + ShaderRead, + ShaderWrite, + TransferRead, + TransferWrite, + UniformBufferRead, + VertexBufferRead, + + Max = VertexBufferRead + }; + + template<> + struct EnumAsFlags + { + static constexpr MemoryAccess max = MemoryAccess::Max; + }; + + using MemoryAccessFlags = Flags; + + enum class PipelineStage + { + TopOfPipe, + + ColorOutput, + DrawIndirect, + FragmentShader, + FragmentTestsEarly, + FragmentTestsLate, + GeometryShader, + TessellationControlShader, + TessellationEvaluationShader, + Transfer, + TransformFeedback, + VertexInput, + VertexShader, + + BottomOfPipe, + + Max = BottomOfPipe + }; + + template<> + struct EnumAsFlags + { + static constexpr PipelineStage max = PipelineStage::Max; + }; + + using PipelineStageFlags = Flags; + + enum class QueueType + { + Compute, + Graphics, + Transfer, + + Max = Transfer + }; + + template<> + struct EnumAsFlags + { + static constexpr QueueType max = QueueType::Max; + }; + + using QueueTypeFlags = Flags; + enum class RenderAPI { Direct3D, ///< Microsoft Render API, only works on MS platforms @@ -53,22 +143,17 @@ namespace Nz SpirV }; - enum class QueueType + enum class TextureLayout { - Compute, - Graphics, - Transfer, - - Max = Transfer + ColorInput, + ColorOutput, + DepthStencilInput, + DepthStencilOutput, + Present, + TransferSource, + TransferDestination, + Undefined }; - - template<> - struct EnumAsFlags - { - static constexpr QueueType max = QueueType::Max; - }; - - using QueueTypeFlags = Flags; } #endif // NAZARA_ENUMS_RENDERER_HPP diff --git a/include/Nazara/Renderer/RenderPass.hpp b/include/Nazara/Renderer/RenderPass.hpp index 10f57ddbe..d971069e2 100644 --- a/include/Nazara/Renderer/RenderPass.hpp +++ b/include/Nazara/Renderer/RenderPass.hpp @@ -11,6 +11,9 @@ #include #include #include +#include +#include +#include namespace Nz { @@ -18,20 +21,64 @@ namespace Nz { public: struct Attachment; + struct SubpassDependency; + struct SubpassDescription; - RenderPass() = default; + inline RenderPass(std::vector attachments, std::vector subpassDescriptions, std::vector subpassDependencies); RenderPass(const RenderPass&) = delete; RenderPass(RenderPass&&) noexcept = default; virtual ~RenderPass(); + inline const Attachment& GetAttachment(std::size_t attachmentIndex) const; + inline std::size_t GetAttachmentCount() const; + inline const std::vector& GetAttachments() const; + inline const std::vector& GetSubpassDescriptions() const; + inline const std::vector& GetsubpassDependencies() const; + RenderPass& operator=(const RenderPass&) = delete; RenderPass& operator=(RenderPass&&) noexcept = default; struct Attachment { PixelFormat format; - // TODO + AttachmentLoadOp loadOp = AttachmentLoadOp::Load; + AttachmentLoadOp stencilLoadOp = AttachmentLoadOp::Load; + AttachmentStoreOp storeOp = AttachmentStoreOp::Store; + AttachmentStoreOp stencilStoreOp = AttachmentStoreOp::Store; + TextureLayout initialLayout = TextureLayout::Undefined; + TextureLayout finalLayout = TextureLayout::Present; }; + + struct AttachmentReference + { + std::size_t attachmentIndex; + TextureLayout attachmentLayout = TextureLayout::ColorInput; + }; + + struct SubpassDependency + { + std::size_t fromSubpassIndex; + PipelineStageFlags fromStages; + MemoryAccessFlags fromAccessFlags; + std::size_t toSubpassIndex; + PipelineStageFlags toStages; + MemoryAccessFlags toAccessFlags; + bool tilable = false; + }; + + struct SubpassDescription + { + std::vector colorAttachment; + std::vector inputAttachments; + std::optional depthStencilAttachment; + }; + + static constexpr std::size_t ExternalSubpassIndex = std::numeric_limits::max(); + + protected: + std::vector m_attachments; + std::vector m_subpassDependencies; + std::vector m_subpassDescriptions; }; } diff --git a/include/Nazara/Renderer/RenderPass.inl b/include/Nazara/Renderer/RenderPass.inl index c2c3865a3..a7360cd30 100644 --- a/include/Nazara/Renderer/RenderPass.inl +++ b/include/Nazara/Renderer/RenderPass.inl @@ -3,10 +3,43 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include namespace Nz { + inline RenderPass::RenderPass(std::vector attachments, std::vector subpassDescriptions, std::vector subpassDependencies) : + m_attachments(std::move(attachments)), + m_subpassDescriptions(std::move(subpassDescriptions)), + m_subpassDependencies(std::move(subpassDependencies)) + { + } + + inline auto Nz::RenderPass::GetAttachment(std::size_t attachmentIndex) const -> const Attachment& + { + assert(attachmentIndex < m_attachments.size()); + return m_attachments[attachmentIndex]; + } + + inline std::size_t RenderPass::GetAttachmentCount() const + { + return m_attachments.size(); + } + + inline auto RenderPass::GetAttachments() const -> const std::vector& + { + return m_attachments; + } + + inline auto RenderPass::GetSubpassDescriptions() const -> const std::vector& + { + return m_subpassDescriptions; + } + + inline auto RenderPass::GetsubpassDependencies() const -> const std::vector& + { + return m_subpassDependencies; + } } #include diff --git a/include/Nazara/VulkanRenderer/Utils.hpp b/include/Nazara/VulkanRenderer/Utils.hpp index c1267da83..b337d3d10 100644 --- a/include/Nazara/VulkanRenderer/Utils.hpp +++ b/include/Nazara/VulkanRenderer/Utils.hpp @@ -11,14 +11,24 @@ #include #include #include +#include #include namespace Nz { + inline std::optional FromVulkan(VkFormat format); + + inline VkAttachmentLoadOp ToVulkan(AttachmentLoadOp loadOp); + inline VkAttachmentStoreOp ToVulkan(AttachmentStoreOp storeOp); inline VkBufferUsageFlags ToVulkan(BufferType bufferType); inline VkFormat ToVulkan(ComponentType componentType); inline VkCullModeFlagBits ToVulkan(FaceSide faceSide); inline VkPolygonMode ToVulkan(FaceFilling faceFilling); + inline VkAccessFlagBits ToVulkan(MemoryAccess memoryAccess); + inline VkAccessFlags ToVulkan(MemoryAccessFlags memoryAccessFlags); + inline VkPipelineStageFlagBits ToVulkan(PipelineStage pipelineStage); + inline VkPipelineStageFlags ToVulkan(PipelineStageFlags pipelineStages); + inline VkFormat ToVulkan(PixelFormat pixelFormat); inline VkPrimitiveTopology ToVulkan(PrimitiveMode primitiveMode); inline VkCompareOp ToVulkan(RendererComparison comparison); inline VkFilter ToVulkan(SamplerFilter samplerFilter); @@ -28,6 +38,7 @@ namespace Nz inline VkShaderStageFlagBits ToVulkan(ShaderStageType stageType); inline VkShaderStageFlags ToVulkan(ShaderStageTypeFlags stageType); inline VkStencilOp ToVulkan(StencilOperation stencilOp); + inline VkImageLayout ToVulkan(TextureLayout textureLayout); inline VkVertexInputRate ToVulkan(VertexInputRate inputRate); NAZARA_VULKANRENDERER_API std::string TranslateVulkanError(VkResult code); diff --git a/include/Nazara/VulkanRenderer/Utils.inl b/include/Nazara/VulkanRenderer/Utils.inl index 242e7c6e0..90eba6933 100644 --- a/include/Nazara/VulkanRenderer/Utils.inl +++ b/include/Nazara/VulkanRenderer/Utils.inl @@ -10,6 +10,45 @@ namespace Nz { + std::optional FromVulkan(VkFormat format) + { + switch (format) + { + case VK_FORMAT_B8G8R8A8_UNORM: return PixelFormat::PixelFormat_BGRA8; + case VK_FORMAT_D24_UNORM_S8_UINT: return PixelFormat::PixelFormat_Depth24Stencil8; + case VK_FORMAT_D32_SFLOAT: return PixelFormat::PixelFormat_Depth32; + case VK_FORMAT_R8G8B8A8_UNORM: return PixelFormat::PixelFormat_RGBA8; + default: break; + } + + return std::nullopt; + } + + VkAttachmentLoadOp ToVulkan(AttachmentLoadOp loadOp) + { + switch (loadOp) + { + case AttachmentLoadOp::Clear: return VK_ATTACHMENT_LOAD_OP_CLEAR; + case AttachmentLoadOp::Discard: return VK_ATTACHMENT_LOAD_OP_DONT_CARE; + case AttachmentLoadOp::Load: return VK_ATTACHMENT_LOAD_OP_LOAD; + } + + NazaraError("Unhandled AttachmentLoadOp 0x" + NumberToString(UnderlyingCast(loadOp), 16)); + return {}; + } + + VkAttachmentStoreOp ToVulkan(AttachmentStoreOp storeOp) + { + switch (storeOp) + { + case AttachmentStoreOp::Discard: return VK_ATTACHMENT_STORE_OP_DONT_CARE; + case AttachmentStoreOp::Store: return VK_ATTACHMENT_STORE_OP_STORE; + } + + NazaraError("Unhandled AttachmentStoreOp 0x" + NumberToString(UnderlyingCast(storeOp), 16)); + return {}; + } + inline VkBufferUsageFlags ToVulkan(BufferType bufferType) { switch (bufferType) @@ -73,6 +112,97 @@ namespace Nz NazaraError("Unhandled FaceFilling 0x" + NumberToString(faceFilling, 16)); return VK_POLYGON_MODE_FILL; } + + inline VkAccessFlagBits ToVulkan(MemoryAccess memoryAccess) + { + switch (memoryAccess) + { + case MemoryAccess::ColorRead: return VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; + case MemoryAccess::ColorWrite: return VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + case MemoryAccess::DepthStencilRead: return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; + case MemoryAccess::DepthStencilWrite: return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + case MemoryAccess::IndexBufferRead: return VK_ACCESS_INDEX_READ_BIT; + case MemoryAccess::IndirectCommandRead: return VK_ACCESS_INDIRECT_COMMAND_READ_BIT; + case MemoryAccess::HostRead: return VK_ACCESS_HOST_READ_BIT; + case MemoryAccess::HostWrite: return VK_ACCESS_HOST_WRITE_BIT; + case MemoryAccess::MemoryRead: return VK_ACCESS_MEMORY_READ_BIT; + case MemoryAccess::MemoryWrite: return VK_ACCESS_MEMORY_WRITE_BIT; + case MemoryAccess::ShaderRead: return VK_ACCESS_SHADER_READ_BIT; + case MemoryAccess::ShaderWrite: return VK_ACCESS_SHADER_WRITE_BIT; + case MemoryAccess::TransferRead: return VK_ACCESS_TRANSFER_READ_BIT; + case MemoryAccess::TransferWrite: return VK_ACCESS_TRANSFER_WRITE_BIT; + case MemoryAccess::UniformBufferRead: return VK_ACCESS_UNIFORM_READ_BIT; + case MemoryAccess::VertexBufferRead: return VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; + } + + NazaraError("Unhandled MemoryAccess 0x" + NumberToString(UnderlyingCast(memoryAccess), 16)); + return {}; + } + + inline VkAccessFlags ToVulkan(MemoryAccessFlags memoryAccessFlags) + { + VkShaderStageFlags accessBits = 0; + for (int i = 0; i <= UnderlyingCast(MemoryAccess::Max); ++i) + { + MemoryAccess memoryAccess = static_cast(i); + if (memoryAccessFlags.Test(memoryAccess)) + accessBits |= ToVulkan(memoryAccess); + } + + return accessBits; + } + + VkPipelineStageFlagBits ToVulkan(PipelineStage pipelineStage) + { + switch (pipelineStage) + { + case PipelineStage::TopOfPipe: return VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + case PipelineStage::ColorOutput: return VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + case PipelineStage::DrawIndirect: return VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT; + case PipelineStage::FragmentShader: return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + case PipelineStage::FragmentTestsEarly: return VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + case PipelineStage::FragmentTestsLate: return VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + case PipelineStage::GeometryShader: return VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT; + case PipelineStage::TessellationControlShader: return VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT; + case PipelineStage::TessellationEvaluationShader: return VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT; + case PipelineStage::Transfer: return VK_PIPELINE_STAGE_TRANSFER_BIT; + case PipelineStage::TransformFeedback: return VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT; + case PipelineStage::VertexInput: return VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; + case PipelineStage::VertexShader: return VK_PIPELINE_STAGE_VERTEX_SHADER_BIT; + case PipelineStage::BottomOfPipe: return VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + } + + NazaraError("Unhandled PipelineStage 0x" + NumberToString(UnderlyingCast(pipelineStage), 16)); + return {}; + } + + VkPipelineStageFlags ToVulkan(PipelineStageFlags pipelineStages) + { + VkShaderStageFlags pipelineStageBits = 0; + for (int i = 0; i <= UnderlyingCast(PipelineStage::Max); ++i) + { + PipelineStage pipelineStage = static_cast(i); + if (pipelineStages.Test(pipelineStage)) + pipelineStageBits |= ToVulkan(pipelineStage); + } + + return pipelineStageBits; + } + + VkFormat ToVulkan(PixelFormat pixelFormat) + { + switch (pixelFormat) + { + case PixelFormat::PixelFormat_BGRA8: return VK_FORMAT_B8G8R8A8_UNORM; + case PixelFormat::PixelFormat_Depth24Stencil8: return VK_FORMAT_D24_UNORM_S8_UINT; + case PixelFormat::PixelFormat_Depth32: return VK_FORMAT_D32_SFLOAT; + case PixelFormat::PixelFormat_RGBA8: return VK_FORMAT_R8G8B8A8_UNORM; + default: break; + } + + NazaraError("Unhandled PixelFormat 0x" + NumberToString(pixelFormat, 16)); + return {}; + } inline VkPrimitiveTopology ToVulkan(PrimitiveMode primitiveMode) { @@ -172,14 +302,12 @@ namespace Nz inline VkShaderStageFlags ToVulkan(ShaderStageTypeFlags stageType) { VkShaderStageFlags shaderStageBits = 0; - - if (stageType.Test(ShaderStageType::Fragment)) - shaderStageBits |= VK_SHADER_STAGE_FRAGMENT_BIT; - - if (stageType.Test(ShaderStageType::Vertex)) - shaderStageBits |= VK_SHADER_STAGE_VERTEX_BIT; - - static_assert(UnderlyingCast(ShaderStageType::Max) + 1 == 2); + for (int i = 0; i <= UnderlyingCast(ShaderStageType::Max); ++i) + { + ShaderStageType shaderStage = static_cast(i); + if (stageType.Test(shaderStage)) + shaderStageBits |= ToVulkan(shaderStage); + } return shaderStageBits; } @@ -198,8 +326,26 @@ namespace Nz case StencilOperation_Zero: return VK_STENCIL_OP_ZERO; } - NazaraError("Unhandled RendererComparison 0x" + NumberToString(stencilOp, 16)); - return VK_STENCIL_OP_KEEP; + NazaraError("Unhandled StencilOperation 0x" + NumberToString(stencilOp, 16)); + return {}; + } + + VkImageLayout ToVulkan(TextureLayout textureLayout) + { + switch (textureLayout) + { + case TextureLayout::ColorInput: return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + case TextureLayout::ColorOutput: return VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR; + case TextureLayout::DepthStencilInput: return VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL; + case TextureLayout::DepthStencilOutput: return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL; + case TextureLayout::Present: return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + case TextureLayout::TransferSource: return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + case TextureLayout::TransferDestination: return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + case TextureLayout::Undefined: return VK_IMAGE_LAYOUT_UNDEFINED; + } + + NazaraError("Unhandled TextureLayout 0x" + NumberToString(UnderlyingCast(textureLayout), 16)); + return {}; } inline VkVertexInputRate ToVulkan(VertexInputRate inputRate) diff --git a/include/Nazara/VulkanRenderer/VulkanRenderPass.hpp b/include/Nazara/VulkanRenderer/VulkanRenderPass.hpp index 87bc54fa9..7b66c1bcb 100644 --- a/include/Nazara/VulkanRenderer/VulkanRenderPass.hpp +++ b/include/Nazara/VulkanRenderer/VulkanRenderPass.hpp @@ -18,12 +18,11 @@ namespace Nz class NAZARA_VULKANRENDERER_API VulkanRenderPass final : public RenderPass { public: - inline VulkanRenderPass(Vk::RenderPass renderPass, std::initializer_list formats); //< FIXME + VulkanRenderPass(Vk::Device& device, std::vector attachments, std::vector subpassDescriptions, std::vector subpassDependencies); VulkanRenderPass(const VulkanRenderPass&) = delete; VulkanRenderPass(VulkanRenderPass&&) noexcept = default; ~VulkanRenderPass() = default; - inline PixelFormat GetAttachmentFormat(std::size_t attachmentIndex) const; inline Vk::RenderPass& GetRenderPass(); inline const Vk::RenderPass& GetRenderPass() const; @@ -31,7 +30,6 @@ namespace Nz VulkanRenderPass& operator=(VulkanRenderPass&&) noexcept = default; private: - std::vector m_formats; Vk::RenderPass m_renderPass; }; } diff --git a/include/Nazara/VulkanRenderer/VulkanRenderPass.inl b/include/Nazara/VulkanRenderer/VulkanRenderPass.inl index d21e1a67c..ce153800d 100644 --- a/include/Nazara/VulkanRenderer/VulkanRenderPass.inl +++ b/include/Nazara/VulkanRenderer/VulkanRenderPass.inl @@ -7,17 +7,6 @@ namespace Nz { - inline VulkanRenderPass::VulkanRenderPass(Vk::RenderPass renderPass, std::initializer_list formats) : - m_formats(std::begin(formats), std::end(formats)), - m_renderPass(std::move(renderPass)) - { - } - - inline PixelFormat VulkanRenderPass::GetAttachmentFormat(std::size_t attachmentIndex) const - { - return m_formats[attachmentIndex]; - } - inline Vk::RenderPass& VulkanRenderPass::GetRenderPass() { return m_renderPass; diff --git a/src/Nazara/VulkanRenderer/VkRenderWindow.cpp b/src/Nazara/VulkanRenderer/VkRenderWindow.cpp index 111ed0840..98c8d8d67 100644 --- a/src/Nazara/VulkanRenderer/VkRenderWindow.cpp +++ b/src/Nazara/VulkanRenderer/VkRenderWindow.cpp @@ -22,7 +22,6 @@ namespace Nz VkRenderWindow::VkRenderWindow(RenderWindow& owner) : m_currentFrame(0), m_owner(owner), - m_depthStencilFormat(VK_FORMAT_MAX_ENUM), m_shouldRecreateSwapchain(false) { } @@ -151,6 +150,7 @@ namespace Nz } }(); + m_depthStencilFormat = VK_FORMAT_MAX_ENUM; if (!parameters.depthFormats.empty()) { for (PixelFormat format : parameters.depthFormats) @@ -177,8 +177,7 @@ namespace Nz break; case PixelFormat_Stencil16: - m_depthStencilFormat = VK_FORMAT_MAX_ENUM; - break; + continue; default: { @@ -400,98 +399,92 @@ namespace Nz bool VkRenderWindow::SetupRenderPass() { - std::array attachments = { - { - { - 0, // VkAttachmentDescriptionFlags flags; - m_surfaceFormat.format, // VkFormat format; - VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; - VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; - VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; - VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; - VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; - VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR // VkImageLayout finalLayout; - }, - { - 0, // VkAttachmentDescriptionFlags flags; - m_depthStencilFormat, // VkFormat format; - VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; - VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; - VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp storeOp; - VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; - VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; - VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout; - }, - } - }; - - VkAttachmentReference colorReference = { - 0, // uint32_t attachment; - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; - }; - - VkAttachmentReference depthReference = { - 1, // uint32_t attachment; - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout layout; - }; - - VkSubpassDescription subpass = { - 0, // VkSubpassDescriptionFlags flags; - VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; - 0U, // uint32_t inputAttachmentCount; - nullptr, // const VkAttachmentReference* pInputAttachments; - 1U, // uint32_t colorAttachmentCount; - &colorReference, // const VkAttachmentReference* pColorAttachments; - nullptr, // const VkAttachmentReference* pResolveAttachments; - (m_depthStencilFormat != VK_FORMAT_MAX_ENUM) ? &depthReference : nullptr, // const VkAttachmentReference* pDepthStencilAttachment; - 0U, // uint32_t preserveAttachmentCount; - nullptr // const uint32_t* pPreserveAttachments; - }; - - std::array dependencies; - // First dependency at the start of the render pass - // Does the transition from final to initial layout - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; // Producer of the dependency - dependencies[0].dstSubpass = 0; // Consumer is our single subpass that will wait for the execution dependency - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[0].srcAccessMask = 0; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - // Second dependency at the end the render pass - // Does the transition from the initial to the final layout - dependencies[1].srcSubpass = 0; // Producer of the dependency is our single subpass - dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; // Consumer are all commands outside of the render pass - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - VkRenderPassCreateInfo createInfo = { - VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; - nullptr, // const void* pNext; - 0, // VkRenderPassCreateFlags flags; - (m_depthStencilFormat != VK_FORMAT_MAX_ENUM) ? 2U : 1U, // uint32_t attachmentCount; - attachments.data(), // const VkAttachmentDescription* pAttachments; - 1U, // uint32_t subpassCount; - &subpass, // const VkSubpassDescription* pSubpasses; - UInt32(dependencies.size()), // uint32_t dependencyCount; - dependencies.data() // const VkSubpassDependency* pDependencies; - }; - - Vk::RenderPass renderPass; - if (!renderPass.Create(*m_device, createInfo)) + std::optional colorFormat = FromVulkan(m_surfaceFormat.format); + if (!colorFormat) { - NazaraError("Failed to create render pass: " + TranslateVulkanError(renderPass.GetLastErrorCode())); + NazaraError("unhandled vulkan pixel format (0x" + NumberToString(m_surfaceFormat.format, 16) + ")"); return false; } - std::initializer_list fixmeplease = { PixelFormat::PixelFormat_RGB8, PixelFormat::PixelFormat_Depth24Stencil8 }; - m_renderPass.emplace(std::move(renderPass), fixmeplease); + std::vector attachments; + attachments.push_back({ + *colorFormat, + AttachmentLoadOp::Clear, + AttachmentLoadOp::Discard, + AttachmentStoreOp::Store, + AttachmentStoreOp::Discard, + TextureLayout::Undefined, + TextureLayout::Present + }); + + RenderPass::AttachmentReference colorReference = { + 0, + TextureLayout::ColorInput + }; + + std::vector subpasses = { + { + { + { colorReference }, + {}, + std::nullopt + } + } + }; + + std::vector subpassDependencies = { + { + { + RenderPass::ExternalSubpassIndex, + PipelineStage::ColorOutput, + {}, + + 0, + PipelineStage::ColorOutput, + MemoryAccess::ColorWrite, + + true //< tilable + }, + { + 0, + PipelineStage::ColorOutput, + MemoryAccess::ColorWrite, + + RenderPass::ExternalSubpassIndex, + PipelineStage::BottomOfPipe, + MemoryAccess::MemoryRead, + + true //< tilable + } + } + }; + + if (m_depthStencilFormat != VK_FORMAT_MAX_ENUM) + { + std::optional depthStencilFormat = FromVulkan(m_depthStencilFormat); + if (!depthStencilFormat) + { + NazaraError("unhandled vulkan pixel format (0x" + NumberToString(m_depthStencilFormat, 16) + ")"); + return false; + } + + attachments.push_back({ + *depthStencilFormat, + AttachmentLoadOp::Clear, + AttachmentLoadOp::Discard, + AttachmentStoreOp::Discard, + AttachmentStoreOp::Discard, + TextureLayout::Undefined, + TextureLayout::DepthStencilInput + }); + + subpasses.front().depthStencilAttachment = RenderPass::AttachmentReference{ + 1, + TextureLayout::DepthStencilInput + }; + } + + m_renderPass.emplace(*m_device, std::move(attachments), std::move(subpasses), std::move(subpassDependencies)); return true; } diff --git a/src/Nazara/VulkanRenderer/VulkanCommandBufferBuilder.cpp b/src/Nazara/VulkanRenderer/VulkanCommandBufferBuilder.cpp index 8e027e923..f6f3c465b 100644 --- a/src/Nazara/VulkanRenderer/VulkanCommandBufferBuilder.cpp +++ b/src/Nazara/VulkanRenderer/VulkanCommandBufferBuilder.cpp @@ -56,7 +56,7 @@ namespace Nz { auto& vkValues = vkClearValues[index]; - if (PixelFormatInfo::GetContent(vkRenderPass.GetAttachmentFormat(index)) == PixelFormatContent_ColorRGBA) + if (PixelFormatInfo::GetContent(vkRenderPass.GetAttachment(index).format) == PixelFormatContent_ColorRGBA) { vkValues.color.float32[0] = values.color.r / 255.f; vkValues.color.float32[1] = values.color.g / 255.f; diff --git a/src/Nazara/VulkanRenderer/VulkanRenderPass.cpp b/src/Nazara/VulkanRenderer/VulkanRenderPass.cpp index e9c406cfc..2d497d6ab 100644 --- a/src/Nazara/VulkanRenderer/VulkanRenderPass.cpp +++ b/src/Nazara/VulkanRenderer/VulkanRenderPass.cpp @@ -3,8 +3,116 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include +#include +#include #include namespace Nz { + inline VulkanRenderPass::VulkanRenderPass(Vk::Device& device, std::vector attachments, std::vector subpassDescriptions, std::vector subpassDependencies) : + RenderPass(std::move(attachments), std::move(subpassDescriptions), std::move(subpassDependencies)) + { + std::size_t totalAttachmentReference = 0; + for (const SubpassDescription& subpassInfo : m_subpassDescriptions) + { + totalAttachmentReference += subpassInfo.colorAttachment.size(); + totalAttachmentReference += subpassInfo.inputAttachments.size(); + + if (subpassInfo.depthStencilAttachment) + totalAttachmentReference++; + } + + StackVector vkAttachments = NazaraStackVector(VkAttachmentDescription, m_attachments.size()); + for (const Attachment& attachmentInfo : m_attachments) + { + vkAttachments.push_back({ + 0, + ToVulkan(attachmentInfo.format), + VK_SAMPLE_COUNT_1_BIT, + ToVulkan(attachmentInfo.loadOp), + ToVulkan(attachmentInfo.storeOp), + ToVulkan(attachmentInfo.stencilLoadOp), + ToVulkan(attachmentInfo.stencilStoreOp), + ToVulkan(attachmentInfo.initialLayout), + ToVulkan(attachmentInfo.finalLayout) + }); + } + + StackVector vkAttachmentReferences = NazaraStackVector(VkAttachmentReference, totalAttachmentReference); + + StackVector vkSubpassDescs = NazaraStackVector(VkSubpassDescription, m_subpassDescriptions.size()); + for (const SubpassDescription& subpassInfo : m_subpassDescriptions) + { + std::size_t colorAttachmentIndex = vkAttachmentReferences.size(); + for (const AttachmentReference& attachmentRef : subpassInfo.colorAttachment) + { + vkAttachmentReferences.push_back({ + UInt32(attachmentRef.attachmentIndex), + ToVulkan(attachmentRef.attachmentLayout) + }); + } + + std::size_t inputAttachmentIndex = vkAttachmentReferences.size(); + for (const AttachmentReference& attachmentRef : subpassInfo.inputAttachments) + { + vkAttachmentReferences.push_back({ + UInt32(attachmentRef.attachmentIndex), + ToVulkan(attachmentRef.attachmentLayout) + }); + } + + std::size_t depthStencilAttachmentIndex = vkAttachmentReferences.size(); + if (subpassInfo.depthStencilAttachment) + { + auto& depthStencilRef = *subpassInfo.depthStencilAttachment; + vkAttachmentReferences.push_back({ + UInt32(depthStencilRef.attachmentIndex), + ToVulkan(depthStencilRef.attachmentLayout) + }); + } + + vkSubpassDescs.push_back({ + VkSubpassDescriptionFlags(0), + VK_PIPELINE_BIND_POINT_GRAPHICS, + UInt32(subpassInfo.inputAttachments.size()), + &vkAttachmentReferences[inputAttachmentIndex], + UInt32(subpassInfo.colorAttachment.size()), + &vkAttachmentReferences[colorAttachmentIndex], + nullptr, + (subpassInfo.depthStencilAttachment) ? &vkAttachmentReferences[depthStencilAttachmentIndex] : nullptr, + 0, + nullptr + }); + } + + StackVector vkSubpassDeps = NazaraStackVector(VkSubpassDependency, m_subpassDependencies.size()); + for (const SubpassDependency& subpassDependency : m_subpassDependencies) + { + vkSubpassDeps.push_back({ + UInt32(subpassDependency.fromSubpassIndex), + UInt32(subpassDependency.toSubpassIndex), + ToVulkan(subpassDependency.fromStages), + ToVulkan(subpassDependency.toStages), + ToVulkan(subpassDependency.fromAccessFlags), + ToVulkan(subpassDependency.toAccessFlags), + VkDependencyFlags((subpassDependency.tilable) ? VK_DEPENDENCY_BY_REGION_BIT : 0) + }); + } + + VkRenderPassCreateInfo renderPassInfo = { + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // sType + nullptr, // pNext + 0, // flags + UInt32(vkAttachments.size()), // attachmentCount + vkAttachments.data(), // pAttachments + UInt32(vkSubpassDescs.size()), // subpassCount + vkSubpassDescs.data(), // pSubpasses + UInt32(vkSubpassDeps.size()), // dependencyCount + vkSubpassDeps.data() // pDependencies + }; + + if (!m_renderPass.Create(device, renderPassInfo)) + throw std::runtime_error("failed to instantiate Vulkan render pass: " + TranslateVulkanError(m_renderPass.GetLastErrorCode())); + } } From 08c2f711b04adaef005adeb879d30a6d3ed4d91e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Mon, 15 Feb 2021 18:16:19 +0100 Subject: [PATCH 054/278] Graphics/Material: Add UpdateBuffers --- examples/GraphicsTest/main.cpp | 10 +++++----- include/Nazara/Graphics/Material.hpp | 4 ++++ src/Nazara/Graphics/Material.cpp | 18 ++++++++++++++++++ 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/examples/GraphicsTest/main.cpp b/examples/GraphicsTest/main.cpp index e967a930a..b5578fd88 100644 --- a/examples/GraphicsTest/main.cpp +++ b/examples/GraphicsTest/main.cpp @@ -106,16 +106,12 @@ int main() const Nz::BasicMaterial::UniformOffsets& materialSettingOffsets = Nz::BasicMaterial::GetOffsets(); std::vector viewerDataBuffer(viewerUboOffsets.totalSize); - std::vector materialSettings(materialSettingOffsets.totalSize); Nz::Vector2ui windowSize = window.GetSize(); Nz::AccessByOffset(viewerDataBuffer.data(), viewerUboOffsets.viewMatrixOffset) = Nz::Matrix4f::Translate(Nz::Vector3f::Backward() * 1); Nz::AccessByOffset(viewerDataBuffer.data(), viewerUboOffsets.projMatrixOffset) = Nz::Matrix4f::Perspective(70.f, float(windowSize.x) / windowSize.y, 0.1f, 1000.f); - Nz::AccessByOffset(materialSettings.data(), materialSettingOffsets.alphaThreshold) = 0.5f; - Nz::AccessByOffset(materialSettings.data(), materialSettingOffsets.diffuseColor) = Nz::Vector4f(1.f, 1.f, 1.f, 1.f); - std::vector instanceDataBuffer(instanceUboOffsets.totalSize); Nz::ModelInstance modelInstance(material->GetSettings()); @@ -283,7 +279,8 @@ int main() if (viewerUboUpdate) { - auto& allocation = frame.GetUploadPool().Allocate(viewerDataBuffer.size()); + Nz::UploadPool& uploadPool = frame.GetUploadPool(); + auto& allocation = uploadPool.Allocate(viewerDataBuffer.size()); std::memcpy(allocation.mappedPtr, viewerDataBuffer.data(), viewerDataBuffer.size()); @@ -293,6 +290,9 @@ int main() { builder.PreTransferBarrier(); builder.CopyBuffer(allocation, viewerDataUBO.get()); + + material->UpdateBuffers(uploadPool, builder); + builder.PostTransferBarrier(); } builder.EndDebugRegion(); diff --git a/include/Nazara/Graphics/Material.hpp b/include/Nazara/Graphics/Material.hpp index 7cfb01008..71a120f32 100644 --- a/include/Nazara/Graphics/Material.hpp +++ b/include/Nazara/Graphics/Material.hpp @@ -29,6 +29,9 @@ namespace Nz { + class CommandBufferBuilder; + class UploadPool; + class NAZARA_GRAPHICS_API Material : public RefCounted, public Resource { public: @@ -98,6 +101,7 @@ namespace Nz inline void SetTextureSampler(std::size_t textureIndex, TextureSamplerInfo samplerInfo); inline void SetUniformBuffer(std::size_t bufferIndex, std::shared_ptr uniformBuffer); + void UpdateBuffers(UploadPool& uploadPool, CommandBufferBuilder& builder); void UpdateShaderBinding(ShaderBinding& shaderBinding) const; // Signals: diff --git a/src/Nazara/Graphics/Material.cpp b/src/Nazara/Graphics/Material.cpp index 77ed2dd3c..f0170b1c2 100644 --- a/src/Nazara/Graphics/Material.cpp +++ b/src/Nazara/Graphics/Material.cpp @@ -5,7 +5,9 @@ #include #include #include +#include #include +#include #include #include @@ -53,6 +55,22 @@ namespace Nz } } + void Material::UpdateBuffers(UploadPool& uploadPool, CommandBufferBuilder& builder) + { + for (auto& ubo : m_uniformBuffers) + { + if (ubo.dataInvalidated) + { + auto& allocation = uploadPool.Allocate(ubo.data.size()); + std::memcpy(allocation.mappedPtr, ubo.data.data(), ubo.data.size()); + + builder.CopyBuffer(allocation, ubo.buffer.get()); + + ubo.dataInvalidated = false; + } + } + } + void Material::UpdateShaderBinding(ShaderBinding& shaderBinding) const { // TODO: Use StackVector From a6b5246633a69360d06c25eff5c8d9010fead1f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Mon, 15 Feb 2021 18:17:10 +0100 Subject: [PATCH 055/278] OpenGLRenderer: Fix clear values --- .../OpenGLRenderer/OpenGLCommandBuffer.hpp | 1 + .../OpenGLRenderer/OpenGLCommandBuffer.inl | 3 +++ .../OpenGLRenderer/OpenGLFramebuffer.hpp | 2 ++ .../OpenGLWindowFramebuffer.hpp | 2 ++ .../OpenGLRenderer/Wrapper/CoreFunctions.hpp | 2 ++ .../OpenGLRenderer/OpenGLCommandBuffer.cpp | 19 ++++++++++++++++++- .../OpenGLWindowFramebuffer.cpp | 5 +++++ 7 files changed, 33 insertions(+), 1 deletion(-) diff --git a/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp b/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp index cc9ac019c..40a6f645e 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp @@ -132,6 +132,7 @@ namespace Nz struct SetFrameBufferData { + std::array clearValues; //< TODO: Remove hard limit? const OpenGLFramebuffer* framebuffer; }; diff --git a/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.inl b/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.inl index bec54f598..1dd4b4d30 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.inl +++ b/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.inl @@ -138,6 +138,9 @@ namespace Nz SetFrameBufferData setFramebuffer; setFramebuffer.framebuffer = &framebuffer; + assert(clearValues.size() < setFramebuffer.clearValues.size()); + std::copy(clearValues.begin(), clearValues.end(), setFramebuffer.clearValues.begin()); + m_commands.emplace_back(std::move(setFramebuffer)); } diff --git a/include/Nazara/OpenGLRenderer/OpenGLFramebuffer.hpp b/include/Nazara/OpenGLRenderer/OpenGLFramebuffer.hpp index d6bc34dee..e5228039b 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLFramebuffer.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLFramebuffer.hpp @@ -30,6 +30,8 @@ namespace Nz virtual void Activate() const = 0; + virtual std::size_t GetColorBufferCount() const = 0; + inline Type GetType() const; OpenGLFramebuffer& operator=(const OpenGLFramebuffer&) = delete; diff --git a/include/Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.hpp b/include/Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.hpp index 0e702f98c..e1a7cb998 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.hpp @@ -24,6 +24,8 @@ namespace Nz void Activate() const override; + std::size_t GetColorBufferCount() const override; + OpenGLWindowFramebuffer& operator=(const OpenGLWindowFramebuffer&) = delete; OpenGLWindowFramebuffer& operator=(OpenGLWindowFramebuffer&&) = delete; diff --git a/include/Nazara/OpenGLRenderer/Wrapper/CoreFunctions.hpp b/include/Nazara/OpenGLRenderer/Wrapper/CoreFunctions.hpp index 1996b8e4f..ab3a25631 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/CoreFunctions.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper/CoreFunctions.hpp @@ -35,6 +35,8 @@ typedef void (GL_APIENTRYP PFNGLSPECIALIZESHADERARBPROC) (GLuint shader, const G cb(glBufferData, PFNGLBUFFERDATAPROC) \ cb(glBufferSubData, PFNGLBUFFERSUBDATAPROC) \ cb(glClear, PFNGLCLEARPROC) \ + cb(glClearBufferfi, PFNGLCLEARBUFFERFIPROC) \ + cb(glClearBufferuiv, PFNGLCLEARBUFFERUIVPROC) \ cb(glClearColor, PFNGLCLEARCOLORPROC) \ cb(glClearDepthf, PFNGLCLEARDEPTHFPROC) \ cb(glClearStencil, PFNGLCLEARSTENCILPROC) \ diff --git a/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp b/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp index 3308adf01..4c47d6a54 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp @@ -93,7 +93,24 @@ namespace Nz command.framebuffer->Activate(); context = GL::Context::GetCurrentContext(); - context->glClearColor(0.5, 0.5, 0.5, 1.0); + + if (command.framebuffer->GetType() == OpenGLFramebuffer::Type::FBO) + { + std::size_t colorBufferCount = command.framebuffer->GetColorBufferCount(); + for (std::size_t i = 0; i < colorBufferCount; ++i) + { + Nz::Color color = command.clearValues[i].color; + std::array clearColor = { color.r, color.g, color.b, color.a }; + + context->glClearBufferuiv(GL_COLOR, GLint(i), clearColor.data()); + } + } + else + { + Nz::Color color = command.clearValues[0].color; + context->glClearColor(color.r, color.g, color.b, color.a); + } + context->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } else diff --git a/src/Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.cpp b/src/Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.cpp index 48b900a5c..a7e8283f6 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.cpp @@ -17,4 +17,9 @@ namespace Nz context.BindFramebuffer(GL::FramebufferTarget::Draw, 0); } + + std::size_t OpenGLWindowFramebuffer::GetColorBufferCount() const + { + return 1; + } } From 080fd9c7eb7edabab10fa96332689c687f5b941d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Mon, 15 Feb 2021 18:17:30 +0100 Subject: [PATCH 056/278] Minor fixes --- include/Nazara/Graphics.hpp | 1 + .../Shaders/basicmaterial.frag.shader | Bin 1745 -> 1745 bytes .../Shaders/basicmaterial.frag.shader.h | 2 +- .../OpenGLRenderer/OpenGLRenderWindow.cpp | 1 + src/Nazara/VulkanRenderer/VkRenderWindow.cpp | 2 +- .../VulkanRenderPipelineLayout.cpp | 2 +- 6 files changed, 5 insertions(+), 3 deletions(-) diff --git a/include/Nazara/Graphics.hpp b/include/Nazara/Graphics.hpp index 6601a7947..4678274e6 100644 --- a/include/Nazara/Graphics.hpp +++ b/include/Nazara/Graphics.hpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #endif // NAZARA_GLOBAL_GRAPHICS_HPP diff --git a/src/Nazara/Graphics/Resources/Shaders/basicmaterial.frag.shader b/src/Nazara/Graphics/Resources/Shaders/basicmaterial.frag.shader index b789061b34422e7e9b735af10d87e53e0151a760..2d5a5cc5b2cf372d676dfd7261db76b25a7e7a51 100644 GIT binary patch delta 82 zcmcb}dy#j;6_&}HSru6sfPjDU238eTMi`5i3CMzB{>dq<-awTFlhxT)NiZ<50Oh!$ O@+@VEMFv1N0}BAa77gkE delta 55 ucmcb}dy#j;6&6N@$ro94z@*A#IaUrR%bisK$O>WghVl=v`U6=!Y-<6`R1aVP diff --git a/src/Nazara/Graphics/Resources/Shaders/basicmaterial.frag.shader.h b/src/Nazara/Graphics/Resources/Shaders/basicmaterial.frag.shader.h index b75d536e2..a28bb1626 100644 --- a/src/Nazara/Graphics/Resources/Shaders/basicmaterial.frag.shader.h +++ b/src/Nazara/Graphics/Resources/Shaders/basicmaterial.frag.shader.h @@ -1 +1 @@ -78,83,72,82,0,0,0,1,0,0,0,0,0,0,0,3,0,0,0,19,72,65,83,95,68,73,70,70,85,83,69,95,84,69,88,84,85,82,69,0,0,0,17,72,65,83,95,65,76,80,72,65,95,84,69,88,84,85,82,69,0,0,0,10,65,76,80,72,65,95,84,69,83,84,0,0,0,3,0,0,0,13,66,97,115,105,99,83,101,116,116,105,110,103,115,0,0,0,2,0,0,0,14,65,108,112,104,97,84,104,114,101,115,104,111,108,100,0,0,0,0,1,0,0,0,12,68,105,102,102,117,115,101,67,111,108,111,114,0,0,0,0,4,0,0,0,12,73,110,115,116,97,110,99,101,68,97,116,97,0,0,0,2,0,0,0,11,119,111,114,108,100,77,97,116,114,105,120,0,0,0,0,9,0,0,0,14,105,110,118,87,111,114,108,100,77,97,116,114,105,120,0,0,0,0,9,0,0,0,10,86,105,101,119,101,114,68,97,116,97,0,0,0,9,0,0,0,16,112,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,0,0,0,0,9,0,0,0,19,105,110,118,80,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,0,0,0,0,9,0,0,0,10,118,105,101,119,77,97,116,114,105,120,0,0,0,0,9,0,0,0,13,105,110,118,86,105,101,119,77,97,116,114,105,120,0,0,0,0,9,0,0,0,14,118,105,101,119,80,114,111,106,77,97,116,114,105,120,0,0,0,0,9,0,0,0,17,105,110,118,86,105,101,119,80,114,111,106,77,97,116,114,105,120,0,0,0,0,9,0,0,0,16,114,101,110,100,101,114,84,97,114,103,101,116,83,105,122,101,0,0,0,0,2,0,0,0,19,105,110,118,82,101,110,100,101,114,84,97,114,103,101,116,83,105,122,101,0,0,0,0,2,0,0,0,11,101,121,101,80,111,115,105,116,105,111,110,0,0,0,0,3,0,0,0,2,0,0,0,10,118,101,114,116,78,111,114,109,97,108,0,0,0,0,3,1,0,0,0,0,0,0,0,6,118,101,114,116,85,86,0,0,0,0,2,1,0,0,0,1,0,0,0,1,0,0,0,13,82,101,110,100,101,114,84,97,114,103,101,116,48,0,0,0,0,4,1,0,0,0,0,0,0,0,6,0,0,0,10,118,105,101,119,101,114,68,97,116,97,1,0,0,0,10,86,105,101,119,101,114,68,97,116,97,1,0,0,0,5,1,0,0,0,0,0,0,0,12,105,110,115,116,97,110,99,101,68,97,116,97,1,0,0,0,12,73,110,115,116,97,110,99,101,68,97,116,97,1,0,0,0,4,1,0,0,0,0,0,0,0,8,115,101,116,116,105,110,103,115,1,0,0,0,13,66,97,115,105,99,83,101,116,116,105,110,103,115,1,0,0,0,3,1,0,0,0,0,0,0,0,16,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,0,0,0,0,10,1,0,0,0,0,0,0,0,0,18,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,0,0,0,0,10,1,0,0,0,1,0,0,0,0,14,84,101,120,116,117,114,101,79,118,101,114,108,97,121,0,0,0,0,10,1,0,0,0,2,0,0,0,0,1,0,0,0,4,109,97,105,110,0,0,0,11,0,0,0,0,0,0,0,16,0,0,0,6,0,0,0,8,0,0,0,2,0,0,0,8,108,105,103,104,116,68,105,114,0,0,0,0,3,0,0,0,5,0,0,0,5,0,0,0,0,191,52,253,244,63,52,253,244,0,0,0,8,0,0,0,2,0,0,0,11,108,105,103,104,116,70,97,99,116,111,114,0,0,0,0,1,0,0,0,12,0,0,0,1,0,0,0,2,0,0,0,11,0,0,0,1,0,0,0,10,118,101,114,116,78,111,114,109,97,108,0,0,0,0,3,0,0,0,11,0,0,0,2,0,0,0,8,108,105,103,104,116,68,105,114,0,0,0,0,3,0,0,0,8,0,0,0,2,0,0,0,12,116,101,120,116,117,114,101,67,111,108,111,114,0,0,0,0,4,0,0,0,2,0,0,0,2,0,0,0,11,0,0,0,2,0,0,0,11,108,105,103,104,116,70,97,99,116,111,114,0,0,0,0,1,0,0,0,6,0,0,0,19,72,65,83,95,68,73,70,70,85,83,69,95,84,69,88,84,85,82,69,0,0,0,2,0,0,0,2,0,0,0,14,0,0,0,11,0,0,0,5,0,0,0,18,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,0,0,0,0,10,0,0,0,11,0,0,0,1,0,0,0,6,118,101,114,116,85,86,0,0,0,0,2,0,0,0,0,0,0,0,11,0,0,0,5,0,0,0,8,115,101,116,116,105,110,103,115,1,0,0,0,13,66,97,115,105,99,83,101,116,116,105,110,103,115,0,0,0,0,4,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,11,0,0,0,5,0,0,0,8,115,101,116,116,105,110,103,115,1,0,0,0,13,66,97,115,105,99,83,101,116,116,105,110,103,115,0,0,0,0,4,0,0,0,1,0,0,0,1,0,0,0,8,0,0,0,2,0,0,0,4,118,97,114,48,0,0,0,0,4,0,0,0,6,0,0,0,17,72,65,83,95,65,76,80,72,65,95,84,69,88,84,85,82,69,0,0,0,4,0,0,0,4,0,0,0,15,0,0,0,0,0,0,0,1,0,0,0,11,0,0,0,2,0,0,0,12,116,101,120,116,117,114,101,67,111,108,111,114,0,0,0,0,4,0,0,0,0,0,0,0,15,0,0,0,0,0,0,0,1,0,0,0,11,0,0,0,2,0,0,0,12,116,101,120,116,117,114,101,67,111,108,111,114,0,0,0,0,4,0,0,0,1,0,0,0,15,0,0,0,0,0,0,0,1,0,0,0,11,0,0,0,2,0,0,0,12,116,101,120,116,117,114,101,67,111,108,111,114,0,0,0,0,4,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,15,0,0,0,0,0,0,0,1,0,0,0,14,0,0,0,11,0,0,0,5,0,0,0,16,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,0,0,0,0,10,0,0,0,11,0,0,0,1,0,0,0,6,118,101,114,116,85,86,0,0,0,0,2,0,0,0,0,0,0,0,15,0,0,0,0,0,0,0,1,0,0,0,11,0,0,0,2,0,0,0,12,116,101,120,116,117,114,101,67,111,108,111,114,0,0,0,0,4,0,0,0,3,0,0,0,11,0,0,0,2,0,0,0,12,116,101,120,116,117,114,101,67,111,108,111,114,0,0,0,0,4,0,0,0,3,0,0,0,1,0,0,0,2,0,0,0,4,0,0,0,6,0,0,0,10,65,76,80,72,65,95,84,69,83,84,0,0,0,2,0,0,0,8,0,0,0,15,0,0,0,0,0,0,0,1,0,0,0,11,0,0,0,2,0,0,0,4,118,97,114,48,0,0,0,0,4,0,0,0,3,0,0,0,0,0,0,0,11,0,0,0,5,0,0,0,8,115,101,116,116,105,110,103,115,1,0,0,0,13,66,97,115,105,99,83,101,116,116,105,110,103,115,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,5,0,0,0,0,1,0,0,0,9,255,255,255,255,0,0,0,10,0,0,0,1,0,0,0,0,0,0,0,11,0,0,0,3,0,0,0,13,82,101,110,100,101,114,84,97,114,103,101,116,48,0,0,0,0,4,0,0,0,11,0,0,0,2,0,0,0,4,118,97,114,48,0,0,0,0,4, \ No newline at end of file +78,83,72,82,0,0,0,1,0,0,0,0,0,0,0,3,0,0,0,19,72,65,83,95,68,73,70,70,85,83,69,95,84,69,88,84,85,82,69,0,0,0,17,72,65,83,95,65,76,80,72,65,95,84,69,88,84,85,82,69,0,0,0,10,65,76,80,72,65,95,84,69,83,84,0,0,0,3,0,0,0,13,66,97,115,105,99,83,101,116,116,105,110,103,115,0,0,0,2,0,0,0,14,65,108,112,104,97,84,104,114,101,115,104,111,108,100,0,0,0,0,1,0,0,0,12,68,105,102,102,117,115,101,67,111,108,111,114,0,0,0,0,4,0,0,0,12,73,110,115,116,97,110,99,101,68,97,116,97,0,0,0,2,0,0,0,11,119,111,114,108,100,77,97,116,114,105,120,0,0,0,0,9,0,0,0,14,105,110,118,87,111,114,108,100,77,97,116,114,105,120,0,0,0,0,9,0,0,0,10,86,105,101,119,101,114,68,97,116,97,0,0,0,9,0,0,0,16,112,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,0,0,0,0,9,0,0,0,19,105,110,118,80,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,0,0,0,0,9,0,0,0,10,118,105,101,119,77,97,116,114,105,120,0,0,0,0,9,0,0,0,13,105,110,118,86,105,101,119,77,97,116,114,105,120,0,0,0,0,9,0,0,0,14,118,105,101,119,80,114,111,106,77,97,116,114,105,120,0,0,0,0,9,0,0,0,17,105,110,118,86,105,101,119,80,114,111,106,77,97,116,114,105,120,0,0,0,0,9,0,0,0,16,114,101,110,100,101,114,84,97,114,103,101,116,83,105,122,101,0,0,0,0,2,0,0,0,19,105,110,118,82,101,110,100,101,114,84,97,114,103,101,116,83,105,122,101,0,0,0,0,2,0,0,0,11,101,121,101,80,111,115,105,116,105,111,110,0,0,0,0,3,0,0,0,2,0,0,0,10,118,101,114,116,78,111,114,109,97,108,0,0,0,0,3,1,0,0,0,0,0,0,0,6,118,101,114,116,85,86,0,0,0,0,2,1,0,0,0,1,0,0,0,1,0,0,0,13,82,101,110,100,101,114,84,97,114,103,101,116,48,0,0,0,0,4,1,0,0,0,0,0,0,0,6,0,0,0,10,118,105,101,119,101,114,68,97,116,97,1,0,0,0,10,86,105,101,119,101,114,68,97,116,97,1,0,0,0,5,1,0,0,0,0,0,0,0,12,105,110,115,116,97,110,99,101,68,97,116,97,1,0,0,0,12,73,110,115,116,97,110,99,101,68,97,116,97,1,0,0,0,4,1,0,0,0,0,0,0,0,8,115,101,116,116,105,110,103,115,1,0,0,0,13,66,97,115,105,99,83,101,116,116,105,110,103,115,1,0,0,0,3,1,0,0,0,0,0,0,0,16,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,0,0,0,0,10,1,0,0,0,0,0,0,0,0,18,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,0,0,0,0,10,1,0,0,0,1,0,0,0,0,14,84,101,120,116,117,114,101,79,118,101,114,108,97,121,0,0,0,0,10,1,0,0,0,2,0,0,0,0,1,0,0,0,4,109,97,105,110,0,0,0,11,0,0,0,0,0,0,0,16,0,0,0,6,0,0,0,8,0,0,0,2,0,0,0,8,108,105,103,104,116,68,105,114,0,0,0,0,3,0,0,0,5,0,0,0,5,0,0,0,0,191,52,253,244,63,52,253,244,0,0,0,8,0,0,0,2,0,0,0,11,108,105,103,104,116,70,97,99,116,111,114,0,0,0,0,1,0,0,0,12,0,0,0,1,0,0,0,2,0,0,0,11,0,0,0,1,0,0,0,10,118,101,114,116,78,111,114,109,97,108,0,0,0,0,3,0,0,0,11,0,0,0,2,0,0,0,8,108,105,103,104,116,68,105,114,0,0,0,0,3,0,0,0,8,0,0,0,2,0,0,0,12,116,101,120,116,117,114,101,67,111,108,111,114,0,0,0,0,4,0,0,0,2,0,0,0,2,0,0,0,11,0,0,0,2,0,0,0,11,108,105,103,104,116,70,97,99,116,111,114,0,0,0,0,1,0,0,0,6,0,0,0,19,72,65,83,95,68,73,70,70,85,83,69,95,84,69,88,84,85,82,69,0,0,0,2,0,0,0,2,0,0,0,14,0,0,0,11,0,0,0,5,0,0,0,18,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,0,0,0,0,10,0,0,0,11,0,0,0,1,0,0,0,6,118,101,114,116,85,86,0,0,0,0,2,0,0,0,0,0,0,0,11,0,0,0,5,0,0,0,8,115,101,116,116,105,110,103,115,1,0,0,0,13,66,97,115,105,99,83,101,116,116,105,110,103,115,0,0,0,0,4,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,11,0,0,0,5,0,0,0,8,115,101,116,116,105,110,103,115,1,0,0,0,13,66,97,115,105,99,83,101,116,116,105,110,103,115,0,0,0,0,4,0,0,0,1,0,0,0,1,0,0,0,8,0,0,0,2,0,0,0,4,118,97,114,48,0,0,0,0,4,0,0,0,6,0,0,0,17,72,65,83,95,65,76,80,72,65,95,84,69,88,84,85,82,69,0,0,0,4,0,0,0,4,0,0,0,15,0,0,0,1,0,0,0,11,0,0,0,2,0,0,0,12,116,101,120,116,117,114,101,67,111,108,111,114,0,0,0,0,4,0,0,0,0,0,0,0,15,0,0,0,1,0,0,0,11,0,0,0,2,0,0,0,12,116,101,120,116,117,114,101,67,111,108,111,114,0,0,0,0,4,0,0,0,1,0,0,0,15,0,0,0,1,0,0,0,11,0,0,0,2,0,0,0,12,116,101,120,116,117,114,101,67,111,108,111,114,0,0,0,0,4,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,15,0,0,0,1,0,0,0,14,0,0,0,11,0,0,0,5,0,0,0,16,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,0,0,0,0,10,0,0,0,11,0,0,0,1,0,0,0,6,118,101,114,116,85,86,0,0,0,0,2,0,0,0,0,0,0,0,15,0,0,0,1,0,0,0,11,0,0,0,2,0,0,0,12,116,101,120,116,117,114,101,67,111,108,111,114,0,0,0,0,4,0,0,0,3,0,0,0,11,0,0,0,2,0,0,0,12,116,101,120,116,117,114,101,67,111,108,111,114,0,0,0,0,4,0,0,0,3,0,0,0,1,0,0,0,2,0,0,0,4,0,0,0,6,0,0,0,10,65,76,80,72,65,95,84,69,83,84,0,0,0,2,0,0,0,8,0,0,0,15,0,0,0,1,0,0,0,11,0,0,0,2,0,0,0,4,118,97,114,48,0,0,0,0,4,0,0,0,3,0,0,0,0,0,0,0,11,0,0,0,5,0,0,0,8,115,101,116,116,105,110,103,115,1,0,0,0,13,66,97,115,105,99,83,101,116,116,105,110,103,115,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,5,0,0,0,0,1,0,0,0,9,255,255,255,255,0,0,0,10,0,0,0,1,0,0,0,0,0,0,0,11,0,0,0,3,0,0,0,13,82,101,110,100,101,114,84,97,114,103,101,116,48,0,0,0,0,4,0,0,0,11,0,0,0,2,0,0,0,4,118,97,114,48,0,0,0,0,4,0,0,4,0,0,0,11,0,0,0,2,0,0,0,4,118,97,114,48,0,0,0,0,4, \ No newline at end of file diff --git a/src/Nazara/OpenGLRenderer/OpenGLRenderWindow.cpp b/src/Nazara/OpenGLRenderer/OpenGLRenderWindow.cpp index 2489b8695..cd84e7cd2 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLRenderWindow.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLRenderWindow.cpp @@ -14,6 +14,7 @@ namespace Nz { OpenGLRenderWindow::OpenGLRenderWindow(RenderWindow& owner) : m_currentFrame(0), + m_renderPass({}, {}, {}), m_framebuffer(*this), m_owner(owner) { diff --git a/src/Nazara/VulkanRenderer/VkRenderWindow.cpp b/src/Nazara/VulkanRenderer/VkRenderWindow.cpp index 98c8d8d67..9091e04c2 100644 --- a/src/Nazara/VulkanRenderer/VkRenderWindow.cpp +++ b/src/Nazara/VulkanRenderer/VkRenderWindow.cpp @@ -89,7 +89,7 @@ namespace Nz case VK_ERROR_SURFACE_LOST_KHR: //< TODO: Handle it by recreating the surface? case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT: default: - throw std::runtime_error("Failed to acquire next image: " + TranslateVulkanError(m_swapchain.GetLastErrorCode())); + throw std::runtime_error("failed to acquire next image: " + TranslateVulkanError(m_swapchain.GetLastErrorCode())); } if (m_inflightFences[imageIndex]) diff --git a/src/Nazara/VulkanRenderer/VulkanRenderPipelineLayout.cpp b/src/Nazara/VulkanRenderer/VulkanRenderPipelineLayout.cpp index ad76aa5b9..a8882e78a 100644 --- a/src/Nazara/VulkanRenderer/VulkanRenderPipelineLayout.cpp +++ b/src/Nazara/VulkanRenderer/VulkanRenderPipelineLayout.cpp @@ -84,7 +84,7 @@ namespace Nz DescriptorPool pool; if (!pool.descriptorPool.Create(*m_device, MaxSet, UInt32(poolSizes.size()), poolSizes.data(), VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT)) - throw std::runtime_error("Failed to allocate new descriptor pool: " + TranslateVulkanError(pool.descriptorPool.GetLastErrorCode())); + throw std::runtime_error("failed to allocate new descriptor pool: " + TranslateVulkanError(pool.descriptorPool.GetLastErrorCode())); pool.freeBindings.Resize(MaxSet, true); pool.storage = std::make_unique(MaxSet); From 8ec11d61937cae2e0af6245a71b791447c5481f1 Mon Sep 17 00:00:00 2001 From: SirLynix Date: Tue, 16 Feb 2021 17:06:38 +0100 Subject: [PATCH 057/278] Fix Linux compilation --- thirdparty/src/chipmunk/cpHastySpace.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/thirdparty/src/chipmunk/cpHastySpace.c b/thirdparty/src/chipmunk/cpHastySpace.c index 7093bfc48..49de81cb7 100644 --- a/thirdparty/src/chipmunk/cpHastySpace.c +++ b/thirdparty/src/chipmunk/cpHastySpace.c @@ -8,7 +8,9 @@ //#include #ifndef _WIN32 +#ifdef __MACOSX__ #include +#endif #include #else #ifndef WIN32_LEAN_AND_MEAN From 32dcc112580f4c01c2d216e395352d11b2066c61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 19 Feb 2021 14:45:37 +0100 Subject: [PATCH 058/278] Core/Flags: Add AutoFlag property to disable automatic bit shifting --- include/Nazara/Core/Flags.hpp | 25 ++++++++++++++++--------- include/Nazara/Core/Flags.inl | 5 ++++- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/include/Nazara/Core/Flags.hpp b/include/Nazara/Core/Flags.hpp index 36ff02f6b..e87d21158 100644 --- a/include/Nazara/Core/Flags.hpp +++ b/include/Nazara/Core/Flags.hpp @@ -18,17 +18,22 @@ namespace Nz { }; - // From: https://stackoverflow.com/questions/11927032/sfinae-check-for-static-member-using-decltype - template - class IsEnumFlag + template + struct IsEnumFlag : std::false_type {}; + + template + struct IsEnumFlag::max)>> : std::true_type {}; + + template + struct GetEnumAutoFlag : std::false_type { - template::max)>::value>::type> - static std::true_type check(int); + static constexpr bool value = true; + }; - template static std::false_type check(...); - - public: - static constexpr bool value = decltype(check(0))::value; + template + struct GetEnumAutoFlag> : std::true_type + { + static constexpr bool value = T::AutoFlag; }; template @@ -36,8 +41,10 @@ namespace Nz { static_assert(std::is_enum::value, "Type must be an enumeration"); static_assert(IsEnumFlag::value, "Enum has not been enabled as flags by an EnumAsFlags specialization"); + static_assert(std::is_same_v::max)>, E>, "EnumAsFlags field max should be of the same type as the enum"); static constexpr std::size_t MaxValue = static_cast(EnumAsFlags::max); + static constexpr bool AutoFlag = GetEnumAutoFlag::value; using BitField16 = std::conditional_t<(MaxValue >= 8), UInt16, UInt8>; using BitField32 = std::conditional_t<(MaxValue >= 16), UInt32, BitField16>; diff --git a/include/Nazara/Core/Flags.inl b/include/Nazara/Core/Flags.inl index 36a001c4f..cb51a277a 100644 --- a/include/Nazara/Core/Flags.inl +++ b/include/Nazara/Core/Flags.inl @@ -258,7 +258,10 @@ namespace Nz template constexpr typename Flags::BitField Flags::GetFlagValue(E enumValue) { - return 1U << static_cast(enumValue); + if constexpr (AutoFlag) + return 1U << static_cast(enumValue); + else + return enumValue; } /*! From 32569eef5e5ba9b12a5b1c0e90f0e2163ee7b0d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 19 Feb 2021 14:47:24 +0100 Subject: [PATCH 059/278] Add SpirV masks and update grammar --- build/scripts/actions/spirv.lua | 33 +- include/Nazara/Shader/SpirvData.hpp | 344 +++++++++- src/Nazara/Shader/SpirvData.cpp | 958 +++++++++++++++++++--------- 3 files changed, 1010 insertions(+), 325 deletions(-) diff --git a/build/scripts/actions/spirv.lua b/build/scripts/actions/spirv.lua index b47c81fa9..6843e548a 100644 --- a/build/scripts/actions/spirv.lua +++ b/build/scripts/actions/spirv.lua @@ -60,6 +60,7 @@ ACTION.Function = function() #define NAZARA_SPIRVDATA_HPP #include +#include #include namespace Nz @@ -90,7 +91,7 @@ headerFile:write([[ for _, operand in pairs(result.operand_kinds) do headerFile:write("\t\t" .. operand.kind .. ",\n") end - + headerFile:write([[ }; @@ -98,24 +99,46 @@ headerFile:write([[ -- SpirV enums for _, operand in pairs(result.operand_kinds) do - if (operand.category == "ValueEnum") then + if (operand.category == "ValueEnum" or operand.category == "BitEnum") then + local enumName = "Spirv" .. operand.kind headerFile:write([[ - enum class Spirv]] .. operand.kind .. [[ + enum class ]] .. enumName .. [[ { ]]) + local maxName + local maxValue for _, enumerant in pairs(operand.enumerants) do + local value = enumerant.value + local eName = enumerant.enumerant:match("^%d") and operand.kind .. enumerant.enumerant or enumerant.enumerant headerFile:write([[ - ]] .. eName .. [[ = ]] .. enumerant.value .. [[, + ]] .. eName .. [[ = ]] .. value .. [[, ]]) + + if (not maxValue or value > maxValue) then + maxName = eName + end end headerFile:write([[ }; ]]) + if (operand.category == "BitEnum") then + headerFile:write([[ + template<> + struct EnumAsFlags<]] .. enumName .. [[> + { + static constexpr ]] .. enumName .. [[ max = ]] .. enumName .. "::" .. maxName .. [[; + + static constexpr bool AutoFlag = false; + }; + + +]]) + end end end @@ -220,4 +243,4 @@ namespace Nz } ]]) -end \ No newline at end of file +end diff --git a/include/Nazara/Shader/SpirvData.hpp b/include/Nazara/Shader/SpirvData.hpp index eccc122ad..3295d2edb 100644 --- a/include/Nazara/Shader/SpirvData.hpp +++ b/include/Nazara/Shader/SpirvData.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020 Jérôme Leclercq +// Copyright (C) 2021 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" @@ -10,6 +10,7 @@ #define NAZARA_SPIRVDATA_HPP #include +#include #include namespace Nz @@ -367,7 +368,12 @@ namespace Nz OpSubgroupAnyKHR = 4429, OpSubgroupAllEqualKHR = 4430, OpSubgroupReadInvocationKHR = 4432, - OpTypeRayQueryProvisionalKHR = 4472, + OpTraceRayKHR = 4445, + OpExecuteCallableKHR = 4446, + OpConvertUToAccelerationStructureKHR = 4447, + OpIgnoreIntersectionKHR = 4448, + OpTerminateRayKHR = 4449, + OpTypeRayQueryKHR = 4472, OpRayQueryInitializeKHR = 4473, OpRayQueryTerminateKHR = 4474, OpRayQueryGenerateIntersectionKHR = 4475, @@ -391,15 +397,11 @@ namespace Nz OpReportIntersectionNV = 5334, OpReportIntersectionKHR = 5334, OpIgnoreIntersectionNV = 5335, - OpIgnoreIntersectionKHR = 5335, OpTerminateRayNV = 5336, - OpTerminateRayKHR = 5336, OpTraceNV = 5337, - OpTraceRayKHR = 5337, OpTypeAccelerationStructureNV = 5341, OpTypeAccelerationStructureKHR = 5341, OpExecuteCallableNV = 5344, - OpExecuteCallableKHR = 5344, OpTypeCooperativeMatrixNV = 5358, OpCooperativeMatrixLoadNV = 5359, OpCooperativeMatrixStoreNV = 5360, @@ -433,8 +435,13 @@ namespace Nz OpUSubSatINTEL = 5596, OpIMul32x16INTEL = 5597, OpUMul32x16INTEL = 5598, - OpFunctionPointerINTEL = 5600, + OpConstFunctionPointerINTEL = 5600, OpFunctionPointerCallINTEL = 5601, + OpAsmTargetINTEL = 5609, + OpAsmINTEL = 5610, + OpAsmCallINTEL = 5611, + OpAtomicFMinEXT = 5614, + OpAtomicFMaxEXT = 5615, OpDecorateString = 5632, OpDecorateStringGOOGLE = 5632, OpMemberDecorateString = 5633, @@ -557,7 +564,12 @@ namespace Nz OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, OpSubgroupAvcSicGetInterRawSadsINTEL = 5816, + OpVariableLengthArrayINTEL = 5818, + OpSaveMemoryINTEL = 5819, + OpRestoreMemoryINTEL = 5820, OpLoopControlINTEL = 5887, + OpPtrCastToCrossWorkgroupINTEL = 5934, + OpCrossWorkgroupCastToPtrINTEL = 5938, OpReadPipeBlockingINTEL = 5946, OpWritePipeBlockingINTEL = 5947, OpFPGARegINTEL = 5949, @@ -579,6 +591,10 @@ namespace Nz OpRayQueryGetIntersectionObjectToWorldKHR = 6031, OpRayQueryGetIntersectionWorldToObjectKHR = 6032, OpAtomicFAddEXT = 6035, + OpTypeBufferSurfaceINTEL = 6086, + OpTypeStructContinuedINTEL = 6090, + OpConstantCompositeContinuedINTEL = 6091, + OpSpecConstantCompositeContinuedINTEL = 6092, }; enum class SpirvOperandKind @@ -592,6 +608,7 @@ namespace Nz MemoryAccess, KernelProfilingInfo, RayFlags, + FragmentShadingRate, SourceLanguage, ExecutionModel, AddressingModel, @@ -605,6 +622,8 @@ namespace Nz ImageChannelOrder, ImageChannelDataType, FPRoundingMode, + FPDenormMode, + FPOperationMode, LinkageType, AccessQualifier, FunctionParameterAttribute, @@ -632,6 +651,235 @@ namespace Nz PairIdRefIdRef, }; + enum class SpirvImageOperands + { + None = 0x0000, + Bias = 0x0001, + Lod = 0x0002, + Grad = 0x0004, + ConstOffset = 0x0008, + Offset = 0x0010, + ConstOffsets = 0x0020, + Sample = 0x0040, + MinLod = 0x0080, + MakeTexelAvailable = 0x0100, + MakeTexelAvailableKHR = 0x0100, + MakeTexelVisible = 0x0200, + MakeTexelVisibleKHR = 0x0200, + NonPrivateTexel = 0x0400, + NonPrivateTexelKHR = 0x0400, + VolatileTexel = 0x0800, + VolatileTexelKHR = 0x0800, + SignExtend = 0x1000, + ZeroExtend = 0x2000, + }; + + template<> + struct EnumAsFlags + { + static constexpr SpirvImageOperands max = SpirvImageOperands::ZeroExtend; + + static constexpr bool AutoFlag = false; + }; + + + enum class SpirvFPFastMathMode + { + None = 0x0000, + NotNaN = 0x0001, + NotInf = 0x0002, + NSZ = 0x0004, + AllowRecip = 0x0008, + Fast = 0x0010, + AllowContractFastINTEL = 0x10000, + AllowReassocINTEL = 0x20000, + }; + + template<> + struct EnumAsFlags + { + static constexpr SpirvFPFastMathMode max = SpirvFPFastMathMode::AllowReassocINTEL; + + static constexpr bool AutoFlag = false; + }; + + + enum class SpirvSelectionControl + { + None = 0x0000, + Flatten = 0x0001, + DontFlatten = 0x0002, + }; + + template<> + struct EnumAsFlags + { + static constexpr SpirvSelectionControl max = SpirvSelectionControl::DontFlatten; + + static constexpr bool AutoFlag = false; + }; + + + enum class SpirvLoopControl + { + None = 0x0000, + Unroll = 0x0001, + DontUnroll = 0x0002, + DependencyInfinite = 0x0004, + DependencyLength = 0x0008, + MinIterations = 0x0010, + MaxIterations = 0x0020, + IterationMultiple = 0x0040, + PeelCount = 0x0080, + PartialCount = 0x0100, + InitiationIntervalINTEL = 0x10000, + MaxConcurrencyINTEL = 0x20000, + DependencyArrayINTEL = 0x40000, + PipelineEnableINTEL = 0x80000, + LoopCoalesceINTEL = 0x100000, + MaxInterleavingINTEL = 0x200000, + SpeculatedIterationsINTEL = 0x400000, + NoFusionINTEL = 0x800000, + }; + + template<> + struct EnumAsFlags + { + static constexpr SpirvLoopControl max = SpirvLoopControl::NoFusionINTEL; + + static constexpr bool AutoFlag = false; + }; + + + enum class SpirvFunctionControl + { + None = 0x0000, + Inline = 0x0001, + DontInline = 0x0002, + Pure = 0x0004, + Const = 0x0008, + }; + + template<> + struct EnumAsFlags + { + static constexpr SpirvFunctionControl max = SpirvFunctionControl::Const; + + static constexpr bool AutoFlag = false; + }; + + + enum class SpirvMemorySemantics + { + Relaxed = 0x0000, + None = 0x0000, + Acquire = 0x0002, + Release = 0x0004, + AcquireRelease = 0x0008, + SequentiallyConsistent = 0x0010, + UniformMemory = 0x0040, + SubgroupMemory = 0x0080, + WorkgroupMemory = 0x0100, + CrossWorkgroupMemory = 0x0200, + AtomicCounterMemory = 0x0400, + ImageMemory = 0x0800, + OutputMemory = 0x1000, + OutputMemoryKHR = 0x1000, + MakeAvailable = 0x2000, + MakeAvailableKHR = 0x2000, + MakeVisible = 0x4000, + MakeVisibleKHR = 0x4000, + Volatile = 0x8000, + }; + + template<> + struct EnumAsFlags + { + static constexpr SpirvMemorySemantics max = SpirvMemorySemantics::Volatile; + + static constexpr bool AutoFlag = false; + }; + + + enum class SpirvMemoryAccess + { + None = 0x0000, + Volatile = 0x0001, + Aligned = 0x0002, + Nontemporal = 0x0004, + MakePointerAvailable = 0x0008, + MakePointerAvailableKHR = 0x0008, + MakePointerVisible = 0x0010, + MakePointerVisibleKHR = 0x0010, + NonPrivatePointer = 0x0020, + NonPrivatePointerKHR = 0x0020, + }; + + template<> + struct EnumAsFlags + { + static constexpr SpirvMemoryAccess max = SpirvMemoryAccess::NonPrivatePointerKHR; + + static constexpr bool AutoFlag = false; + }; + + + enum class SpirvKernelProfilingInfo + { + None = 0x0000, + CmdExecTime = 0x0001, + }; + + template<> + struct EnumAsFlags + { + static constexpr SpirvKernelProfilingInfo max = SpirvKernelProfilingInfo::CmdExecTime; + + static constexpr bool AutoFlag = false; + }; + + + enum class SpirvRayFlags + { + NoneKHR = 0x0000, + OpaqueKHR = 0x0001, + NoOpaqueKHR = 0x0002, + TerminateOnFirstHitKHR = 0x0004, + SkipClosestHitShaderKHR = 0x0008, + CullBackFacingTrianglesKHR = 0x0010, + CullFrontFacingTrianglesKHR = 0x0020, + CullOpaqueKHR = 0x0040, + CullNoOpaqueKHR = 0x0080, + SkipTrianglesKHR = 0x0100, + SkipAABBsKHR = 0x0200, + }; + + template<> + struct EnumAsFlags + { + static constexpr SpirvRayFlags max = SpirvRayFlags::SkipAABBsKHR; + + static constexpr bool AutoFlag = false; + }; + + + enum class SpirvFragmentShadingRate + { + Vertical2Pixels = 0x0001, + Vertical4Pixels = 0x0002, + Horizontal2Pixels = 0x0004, + Horizontal4Pixels = 0x0008, + }; + + template<> + struct EnumAsFlags + { + static constexpr SpirvFragmentShadingRate max = SpirvFragmentShadingRate::Horizontal4Pixels; + + static constexpr bool AutoFlag = false; + }; + + enum class SpirvSourceLanguage { Unknown = 0, @@ -743,10 +991,16 @@ namespace Nz SampleInterlockUnorderedEXT = 5369, ShadingRateInterlockOrderedEXT = 5370, ShadingRateInterlockUnorderedEXT = 5371, + SharedLocalMemorySizeINTEL = 5618, + RoundingModeRTPINTEL = 5620, + RoundingModeRTNINTEL = 5621, + FloatingPointModeALTINTEL = 5622, + FloatingPointModeIEEEINTEL = 5623, MaxWorkgroupSizeINTEL = 5893, MaxWorkDimINTEL = 5894, NoGlobalOffsetINTEL = 5895, NumSIMDWorkitemsINTEL = 5896, + SchedulerTargetFmaxMhzINTEL = 5903, }; enum class SpirvStorageClass @@ -779,6 +1033,8 @@ namespace Nz PhysicalStorageBuffer = 5349, PhysicalStorageBufferEXT = 5349, CodeSectionINTEL = 5605, + DeviceOnlyINTEL = 5936, + HostOnlyINTEL = 5937, }; enum class SpirvDim @@ -849,6 +1105,8 @@ namespace Nz Rg8ui = 37, R16ui = 38, R8ui = 39, + R64ui = 40, + R64i = 41, }; enum class SpirvImageChannelOrder @@ -904,6 +1162,18 @@ namespace Nz RTN = 3, }; + enum class SpirvFPDenormMode + { + Preserve = 0, + FlushToZero = 1, + }; + + enum class SpirvFPOperationMode + { + IEEE = 0, + ALT = 1, + }; + enum class SpirvLinkageType { Export = 0, @@ -995,12 +1265,22 @@ namespace Nz RestrictPointerEXT = 5355, AliasedPointer = 5356, AliasedPointerEXT = 5356, + SIMTCallINTEL = 5599, ReferencedIndirectlyINTEL = 5602, + ClobberINTEL = 5607, + SideEffectsINTEL = 5608, + VectorComputeVariableINTEL = 5624, + FuncParamIOKindINTEL = 5625, + VectorComputeFunctionINTEL = 5626, + StackCallINTEL = 5627, + GlobalVariableOffsetINTEL = 5628, CounterBuffer = 5634, HlslCounterBufferGOOGLE = 5634, UserSemantic = 5635, HlslSemanticGOOGLE = 5635, UserTypeGOOGLE = 5636, + FunctionRoundingModeINTEL = 5822, + FunctionDenormModeINTEL = 5823, RegisterINTEL = 5825, MemoryINTEL = 5826, NumbanksINTEL = 5827, @@ -1013,6 +1293,17 @@ namespace Nz MergeINTEL = 5834, BankBitsINTEL = 5835, ForcePow2DepthINTEL = 5836, + BurstCoalesceINTEL = 5899, + CacheSizeINTEL = 5900, + DontStaticallyCoalesceINTEL = 5901, + PrefetchINTEL = 5902, + StallEnableINTEL = 5905, + FuseLoopsInFunctionINTEL = 5907, + BufferLocationINTEL = 5921, + IOPipeStorageINTEL = 5944, + FunctionFloatingPointModeINTEL = 6080, + SingleElementVectorINTEL = 6085, + VectorComputeCallableFunctionINTEL = 6087, }; enum class SpirvBuiltIn @@ -1059,20 +1350,22 @@ namespace Nz VertexIndex = 42, InstanceIndex = 43, SubgroupEqMask = 4416, - SubgroupGeMask = 4417, - SubgroupGtMask = 4418, - SubgroupLeMask = 4419, - SubgroupLtMask = 4420, SubgroupEqMaskKHR = 4416, + SubgroupGeMask = 4417, SubgroupGeMaskKHR = 4417, + SubgroupGtMask = 4418, SubgroupGtMaskKHR = 4418, + SubgroupLeMask = 4419, SubgroupLeMaskKHR = 4419, + SubgroupLtMask = 4420, SubgroupLtMaskKHR = 4420, BaseVertex = 4424, BaseInstance = 4425, DrawIndex = 4426, + PrimitiveShadingRateKHR = 4432, DeviceIndex = 4438, ViewIndex = 4440, + ShadingRateKHR = 4444, BaryCoordNoPerspAMD = 4992, BaryCoordNoPerspCentroidAMD = 4993, BaryCoordNoPerspSampleAMD = 4994, @@ -1124,7 +1417,6 @@ namespace Nz WorldToObjectNV = 5331, WorldToObjectKHR = 5331, HitTNV = 5332, - HitTKHR = 5332, HitKindNV = 5333, HitKindKHR = 5333, IncomingRayFlagsNV = 5351, @@ -1237,8 +1529,12 @@ namespace Nz GroupNonUniformQuad = 68, ShaderLayer = 69, ShaderViewportIndex = 70, + FragmentShadingRateKHR = 4422, SubgroupBallotKHR = 4423, DrawParameters = 4427, + WorkgroupMemoryExplicitLayoutKHR = 4428, + WorkgroupMemoryExplicitLayout8BitAccessKHR = 4429, + WorkgroupMemoryExplicitLayout16BitAccessKHR = 4430, SubgroupVoteKHR = 4431, StorageBuffer16BitAccess = 4433, StorageUniformBufferBlock16 = 4433, @@ -1261,12 +1557,15 @@ namespace Nz RoundingModeRTE = 4467, RoundingModeRTZ = 4468, RayQueryProvisionalKHR = 4471, - RayTraversalPrimitiveCullingProvisionalKHR = 4478, + RayQueryKHR = 4472, + RayTraversalPrimitiveCullingKHR = 4478, + RayTracingKHR = 4479, Float16ImageAMD = 5008, ImageGatherBiasLodAMD = 5009, FragmentMaskAMD = 5010, StencilExportEXT = 5013, ImageReadWriteLodAMD = 5015, + Int64ImageEXT = 5016, ShaderClockKHR = 5055, SampleMaskOverrideCoverageNV = 5249, GeometryShaderPassthroughNV = 5251, @@ -1326,21 +1625,40 @@ namespace Nz SubgroupBufferBlockIOINTEL = 5569, SubgroupImageBlockIOINTEL = 5570, SubgroupImageMediaBlockIOINTEL = 5579, + RoundToInfinityINTEL = 5582, + FloatingPointModeINTEL = 5583, IntegerFunctions2INTEL = 5584, FunctionPointersINTEL = 5603, IndirectReferencesINTEL = 5604, + AsmINTEL = 5606, + AtomicFloat32MinMaxEXT = 5612, + AtomicFloat64MinMaxEXT = 5613, + AtomicFloat16MinMaxEXT = 5616, + VectorComputeINTEL = 5617, + VectorAnyINTEL = 5619, SubgroupAvcMotionEstimationINTEL = 5696, SubgroupAvcMotionEstimationIntraINTEL = 5697, SubgroupAvcMotionEstimationChromaINTEL = 5698, + VariableLengthArrayINTEL = 5817, + FunctionFloatControlINTEL = 5821, FPGAMemoryAttributesINTEL = 5824, + FPFastMathModeINTEL = 5837, + ArbitraryPrecisionIntegersINTEL = 5844, UnstructuredLoopControlsINTEL = 5886, FPGALoopControlsINTEL = 5888, KernelAttributesINTEL = 5892, FPGAKernelAttributesINTEL = 5897, + FPGAMemoryAccessesINTEL = 5898, + FPGAClusterAttributesINTEL = 5904, + LoopFuseINTEL = 5906, + FPGABufferLocationINTEL = 5920, + USMStorageClassesINTEL = 5935, + IOPipesINTEL = 5943, BlockingPipesINTEL = 5945, FPGARegINTEL = 5948, AtomicFloat32AddEXT = 6033, AtomicFloat64AddEXT = 6034, + LongConstantCompositeINTEL = 6089, }; enum class SpirvRayQueryIntersection diff --git a/src/Nazara/Shader/SpirvData.cpp b/src/Nazara/Shader/SpirvData.cpp index dae33b777..5bb2f2794 100644 --- a/src/Nazara/Shader/SpirvData.cpp +++ b/src/Nazara/Shader/SpirvData.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020 Jérôme Leclercq +// Copyright (C) 2021 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" @@ -11,7 +11,7 @@ namespace Nz { - static constexpr std::array s_operands = { + static constexpr std::array s_operands = { { { SpirvOperandKind::IdResultType, @@ -5429,6 +5429,70 @@ namespace Nz SpirvOperandKind::IdRef, R"('Index')" }, + { + SpirvOperandKind::IdRef, + R"('Accel')" + }, + { + SpirvOperandKind::IdRef, + R"('Ray Flags')" + }, + { + SpirvOperandKind::IdRef, + R"('Cull Mask')" + }, + { + SpirvOperandKind::IdRef, + R"('SBT Offset')" + }, + { + SpirvOperandKind::IdRef, + R"('SBT Stride')" + }, + { + SpirvOperandKind::IdRef, + R"('Miss Index')" + }, + { + SpirvOperandKind::IdRef, + R"('Ray Origin')" + }, + { + SpirvOperandKind::IdRef, + R"('Ray Tmin')" + }, + { + SpirvOperandKind::IdRef, + R"('Ray Direction')" + }, + { + SpirvOperandKind::IdRef, + R"('Ray Tmax')" + }, + { + SpirvOperandKind::IdRef, + R"('Payload')" + }, + { + SpirvOperandKind::IdRef, + R"('SBT Index')" + }, + { + SpirvOperandKind::IdRef, + R"('Callable Data')" + }, + { + SpirvOperandKind::IdResultType, + R"(IdResultType)" + }, + { + SpirvOperandKind::IdResult, + R"(IdResult)" + }, + { + SpirvOperandKind::IdRef, + R"('Accel')" + }, { SpirvOperandKind::IdResult, R"(IdResult)" @@ -6345,6 +6409,106 @@ namespace Nz SpirvOperandKind::IdRef, R"('Operand 1')" }, + { + SpirvOperandKind::IdResultType, + R"(IdResultType)" + }, + { + SpirvOperandKind::IdResult, + R"(IdResult)" + }, + { + SpirvOperandKind::LiteralString, + R"('Asm target')" + }, + { + SpirvOperandKind::IdResultType, + R"(IdResultType)" + }, + { + SpirvOperandKind::IdResult, + R"(IdResult)" + }, + { + SpirvOperandKind::IdRef, + R"('Asm type')" + }, + { + SpirvOperandKind::IdRef, + R"('Target')" + }, + { + SpirvOperandKind::LiteralString, + R"('Asm instructions')" + }, + { + SpirvOperandKind::LiteralString, + R"('Constraints')" + }, + { + SpirvOperandKind::IdResultType, + R"(IdResultType)" + }, + { + SpirvOperandKind::IdResult, + R"(IdResult)" + }, + { + SpirvOperandKind::IdRef, + R"('Asm')" + }, + { + SpirvOperandKind::IdRef, + R"('Argument 0')" + }, + { + SpirvOperandKind::IdResultType, + R"(IdResultType)" + }, + { + SpirvOperandKind::IdResult, + R"(IdResult)" + }, + { + SpirvOperandKind::IdRef, + R"('Pointer')" + }, + { + SpirvOperandKind::IdScope, + R"('Memory')" + }, + { + SpirvOperandKind::IdMemorySemantics, + R"('Semantics')" + }, + { + SpirvOperandKind::IdRef, + R"('Value')" + }, + { + SpirvOperandKind::IdResultType, + R"(IdResultType)" + }, + { + SpirvOperandKind::IdResult, + R"(IdResult)" + }, + { + SpirvOperandKind::IdRef, + R"('Pointer')" + }, + { + SpirvOperandKind::IdScope, + R"('Memory')" + }, + { + SpirvOperandKind::IdMemorySemantics, + R"('Semantics')" + }, + { + SpirvOperandKind::IdRef, + R"('Value')" + }, { SpirvOperandKind::IdRef, R"('Target')" @@ -8185,6 +8349,30 @@ namespace Nz SpirvOperandKind::IdRef, R"('Payload')" }, + { + SpirvOperandKind::IdResultType, + R"(IdResultType)" + }, + { + SpirvOperandKind::IdResult, + R"(IdResult)" + }, + { + SpirvOperandKind::IdRef, + R"('Lenght')" + }, + { + SpirvOperandKind::IdResultType, + R"(IdResultType)" + }, + { + SpirvOperandKind::IdResult, + R"(IdResult)" + }, + { + SpirvOperandKind::IdRef, + R"('Ptr')" + }, { SpirvOperandKind::LiteralInteger, R"('Loop Control Parameters')" @@ -8197,6 +8385,30 @@ namespace Nz SpirvOperandKind::IdResult, R"(IdResult)" }, + { + SpirvOperandKind::IdRef, + R"('Pointer')" + }, + { + SpirvOperandKind::IdResultType, + R"(IdResultType)" + }, + { + SpirvOperandKind::IdResult, + R"(IdResult)" + }, + { + SpirvOperandKind::IdRef, + R"('Pointer')" + }, + { + SpirvOperandKind::IdResultType, + R"(IdResultType)" + }, + { + SpirvOperandKind::IdResult, + R"(IdResult)" + }, { SpirvOperandKind::IdRef, R"('Packet Size')" @@ -8513,10 +8725,28 @@ namespace Nz SpirvOperandKind::IdRef, R"('Value')" }, + { + SpirvOperandKind::IdResult, + R"(IdResult)" + }, + { + SpirvOperandKind::IdRef, + R"('Member 0 type', + +'member 1 type', + +...)" + }, + { + SpirvOperandKind::IdRef, + R"('Constituents')" + }, + { + SpirvOperandKind::IdRef, + R"('Constituents')" + }, } }; - static std::array s_instructions = { + static std::array s_instructions = { { { SpirvOp::OpNop, @@ -10625,137 +10855,23 @@ namespace Nz 4, }, { - SpirvOp::OpTypeRayQueryProvisionalKHR, - R"(OpTypeRayQueryProvisionalKHR)", + SpirvOp::OpTraceRayKHR, + R"(OpTraceRayKHR)", &s_operands[1352], - 1, + 11, }, { - SpirvOp::OpRayQueryInitializeKHR, - R"(OpRayQueryInitializeKHR)", - &s_operands[1353], - 8, - }, - { - SpirvOp::OpRayQueryTerminateKHR, - R"(OpRayQueryTerminateKHR)", - &s_operands[1361], - 1, - }, - { - SpirvOp::OpRayQueryGenerateIntersectionKHR, - R"(OpRayQueryGenerateIntersectionKHR)", - &s_operands[1362], + SpirvOp::OpExecuteCallableKHR, + R"(OpExecuteCallableKHR)", + &s_operands[1363], 2, }, { - SpirvOp::OpRayQueryConfirmIntersectionKHR, - R"(OpRayQueryConfirmIntersectionKHR)", - &s_operands[1364], - 1, - }, - { - SpirvOp::OpRayQueryProceedKHR, - R"(OpRayQueryProceedKHR)", + SpirvOp::OpConvertUToAccelerationStructureKHR, + R"(OpConvertUToAccelerationStructureKHR)", &s_operands[1365], 3, }, - { - SpirvOp::OpRayQueryGetIntersectionTypeKHR, - R"(OpRayQueryGetIntersectionTypeKHR)", - &s_operands[1368], - 4, - }, - { - SpirvOp::OpGroupIAddNonUniformAMD, - R"(OpGroupIAddNonUniformAMD)", - &s_operands[1372], - 5, - }, - { - SpirvOp::OpGroupFAddNonUniformAMD, - R"(OpGroupFAddNonUniformAMD)", - &s_operands[1377], - 5, - }, - { - SpirvOp::OpGroupFMinNonUniformAMD, - R"(OpGroupFMinNonUniformAMD)", - &s_operands[1382], - 5, - }, - { - SpirvOp::OpGroupUMinNonUniformAMD, - R"(OpGroupUMinNonUniformAMD)", - &s_operands[1387], - 5, - }, - { - SpirvOp::OpGroupSMinNonUniformAMD, - R"(OpGroupSMinNonUniformAMD)", - &s_operands[1392], - 5, - }, - { - SpirvOp::OpGroupFMaxNonUniformAMD, - R"(OpGroupFMaxNonUniformAMD)", - &s_operands[1397], - 5, - }, - { - SpirvOp::OpGroupUMaxNonUniformAMD, - R"(OpGroupUMaxNonUniformAMD)", - &s_operands[1402], - 5, - }, - { - SpirvOp::OpGroupSMaxNonUniformAMD, - R"(OpGroupSMaxNonUniformAMD)", - &s_operands[1407], - 5, - }, - { - SpirvOp::OpFragmentMaskFetchAMD, - R"(OpFragmentMaskFetchAMD)", - &s_operands[1412], - 4, - }, - { - SpirvOp::OpFragmentFetchAMD, - R"(OpFragmentFetchAMD)", - &s_operands[1416], - 5, - }, - { - SpirvOp::OpReadClockKHR, - R"(OpReadClockKHR)", - &s_operands[1421], - 3, - }, - { - SpirvOp::OpImageSampleFootprintNV, - R"(OpImageSampleFootprintNV)", - &s_operands[1424], - 7, - }, - { - SpirvOp::OpGroupNonUniformPartitionNV, - R"(OpGroupNonUniformPartitionNV)", - &s_operands[1431], - 3, - }, - { - SpirvOp::OpWritePackedPrimitiveIndices4x8NV, - R"(OpWritePackedPrimitiveIndices4x8NV)", - &s_operands[1434], - 2, - }, - { - SpirvOp::OpReportIntersectionKHR, - R"(OpReportIntersectionKHR)", - &s_operands[1436], - 4, - }, { SpirvOp::OpIgnoreIntersectionKHR, R"(OpIgnoreIntersectionKHR)", @@ -10769,51 +10885,195 @@ namespace Nz 0, }, { - SpirvOp::OpTraceRayKHR, - R"(OpTraceRayKHR)", + SpirvOp::OpTypeRayQueryKHR, + R"(OpTypeRayQueryKHR)", + &s_operands[1368], + 1, + }, + { + SpirvOp::OpRayQueryInitializeKHR, + R"(OpRayQueryInitializeKHR)", + &s_operands[1369], + 8, + }, + { + SpirvOp::OpRayQueryTerminateKHR, + R"(OpRayQueryTerminateKHR)", + &s_operands[1377], + 1, + }, + { + SpirvOp::OpRayQueryGenerateIntersectionKHR, + R"(OpRayQueryGenerateIntersectionKHR)", + &s_operands[1378], + 2, + }, + { + SpirvOp::OpRayQueryConfirmIntersectionKHR, + R"(OpRayQueryConfirmIntersectionKHR)", + &s_operands[1380], + 1, + }, + { + SpirvOp::OpRayQueryProceedKHR, + R"(OpRayQueryProceedKHR)", + &s_operands[1381], + 3, + }, + { + SpirvOp::OpRayQueryGetIntersectionTypeKHR, + R"(OpRayQueryGetIntersectionTypeKHR)", + &s_operands[1384], + 4, + }, + { + SpirvOp::OpGroupIAddNonUniformAMD, + R"(OpGroupIAddNonUniformAMD)", + &s_operands[1388], + 5, + }, + { + SpirvOp::OpGroupFAddNonUniformAMD, + R"(OpGroupFAddNonUniformAMD)", + &s_operands[1393], + 5, + }, + { + SpirvOp::OpGroupFMinNonUniformAMD, + R"(OpGroupFMinNonUniformAMD)", + &s_operands[1398], + 5, + }, + { + SpirvOp::OpGroupUMinNonUniformAMD, + R"(OpGroupUMinNonUniformAMD)", + &s_operands[1403], + 5, + }, + { + SpirvOp::OpGroupSMinNonUniformAMD, + R"(OpGroupSMinNonUniformAMD)", + &s_operands[1408], + 5, + }, + { + SpirvOp::OpGroupFMaxNonUniformAMD, + R"(OpGroupFMaxNonUniformAMD)", + &s_operands[1413], + 5, + }, + { + SpirvOp::OpGroupUMaxNonUniformAMD, + R"(OpGroupUMaxNonUniformAMD)", + &s_operands[1418], + 5, + }, + { + SpirvOp::OpGroupSMaxNonUniformAMD, + R"(OpGroupSMaxNonUniformAMD)", + &s_operands[1423], + 5, + }, + { + SpirvOp::OpFragmentMaskFetchAMD, + R"(OpFragmentMaskFetchAMD)", + &s_operands[1428], + 4, + }, + { + SpirvOp::OpFragmentFetchAMD, + R"(OpFragmentFetchAMD)", + &s_operands[1432], + 5, + }, + { + SpirvOp::OpReadClockKHR, + R"(OpReadClockKHR)", + &s_operands[1437], + 3, + }, + { + SpirvOp::OpImageSampleFootprintNV, + R"(OpImageSampleFootprintNV)", &s_operands[1440], + 7, + }, + { + SpirvOp::OpGroupNonUniformPartitionNV, + R"(OpGroupNonUniformPartitionNV)", + &s_operands[1447], + 3, + }, + { + SpirvOp::OpWritePackedPrimitiveIndices4x8NV, + R"(OpWritePackedPrimitiveIndices4x8NV)", + &s_operands[1450], + 2, + }, + { + SpirvOp::OpReportIntersectionKHR, + R"(OpReportIntersectionKHR)", + &s_operands[1452], + 4, + }, + { + SpirvOp::OpIgnoreIntersectionNV, + R"(OpIgnoreIntersectionNV)", + nullptr, + 0, + }, + { + SpirvOp::OpTerminateRayNV, + R"(OpTerminateRayNV)", + nullptr, + 0, + }, + { + SpirvOp::OpTraceNV, + R"(OpTraceNV)", + &s_operands[1456], 11, }, { SpirvOp::OpTypeAccelerationStructureKHR, R"(OpTypeAccelerationStructureKHR)", - &s_operands[1451], + &s_operands[1467], 1, }, { - SpirvOp::OpExecuteCallableKHR, - R"(OpExecuteCallableKHR)", - &s_operands[1452], + SpirvOp::OpExecuteCallableNV, + R"(OpExecuteCallableNV)", + &s_operands[1468], 2, }, { SpirvOp::OpTypeCooperativeMatrixNV, R"(OpTypeCooperativeMatrixNV)", - &s_operands[1454], + &s_operands[1470], 5, }, { SpirvOp::OpCooperativeMatrixLoadNV, R"(OpCooperativeMatrixLoadNV)", - &s_operands[1459], + &s_operands[1475], 6, }, { SpirvOp::OpCooperativeMatrixStoreNV, R"(OpCooperativeMatrixStoreNV)", - &s_operands[1465], + &s_operands[1481], 5, }, { SpirvOp::OpCooperativeMatrixMulAddNV, R"(OpCooperativeMatrixMulAddNV)", - &s_operands[1470], + &s_operands[1486], 5, }, { SpirvOp::OpCooperativeMatrixLengthNV, R"(OpCooperativeMatrixLengthNV)", - &s_operands[1475], + &s_operands[1491], 3, }, { @@ -10837,1017 +11097,1101 @@ namespace Nz { SpirvOp::OpIsHelperInvocationEXT, R"(OpIsHelperInvocationEXT)", - &s_operands[1478], + &s_operands[1494], 2, }, { SpirvOp::OpSubgroupShuffleINTEL, R"(OpSubgroupShuffleINTEL)", - &s_operands[1480], + &s_operands[1496], 4, }, { SpirvOp::OpSubgroupShuffleDownINTEL, R"(OpSubgroupShuffleDownINTEL)", - &s_operands[1484], + &s_operands[1500], 5, }, { SpirvOp::OpSubgroupShuffleUpINTEL, R"(OpSubgroupShuffleUpINTEL)", - &s_operands[1489], + &s_operands[1505], 5, }, { SpirvOp::OpSubgroupShuffleXorINTEL, R"(OpSubgroupShuffleXorINTEL)", - &s_operands[1494], + &s_operands[1510], 4, }, { SpirvOp::OpSubgroupBlockReadINTEL, R"(OpSubgroupBlockReadINTEL)", - &s_operands[1498], + &s_operands[1514], 3, }, { SpirvOp::OpSubgroupBlockWriteINTEL, R"(OpSubgroupBlockWriteINTEL)", - &s_operands[1501], + &s_operands[1517], 2, }, { SpirvOp::OpSubgroupImageBlockReadINTEL, R"(OpSubgroupImageBlockReadINTEL)", - &s_operands[1503], + &s_operands[1519], 4, }, { SpirvOp::OpSubgroupImageBlockWriteINTEL, R"(OpSubgroupImageBlockWriteINTEL)", - &s_operands[1507], + &s_operands[1523], 3, }, { SpirvOp::OpSubgroupImageMediaBlockReadINTEL, R"(OpSubgroupImageMediaBlockReadINTEL)", - &s_operands[1510], + &s_operands[1526], 6, }, { SpirvOp::OpSubgroupImageMediaBlockWriteINTEL, R"(OpSubgroupImageMediaBlockWriteINTEL)", - &s_operands[1516], + &s_operands[1532], 5, }, { SpirvOp::OpUCountLeadingZerosINTEL, R"(OpUCountLeadingZerosINTEL)", - &s_operands[1521], + &s_operands[1537], 3, }, { SpirvOp::OpUCountTrailingZerosINTEL, R"(OpUCountTrailingZerosINTEL)", - &s_operands[1524], + &s_operands[1540], 3, }, { SpirvOp::OpAbsISubINTEL, R"(OpAbsISubINTEL)", - &s_operands[1527], + &s_operands[1543], 4, }, { SpirvOp::OpAbsUSubINTEL, R"(OpAbsUSubINTEL)", - &s_operands[1531], + &s_operands[1547], 4, }, { SpirvOp::OpIAddSatINTEL, R"(OpIAddSatINTEL)", - &s_operands[1535], + &s_operands[1551], 4, }, { SpirvOp::OpUAddSatINTEL, R"(OpUAddSatINTEL)", - &s_operands[1539], + &s_operands[1555], 4, }, { SpirvOp::OpIAverageINTEL, R"(OpIAverageINTEL)", - &s_operands[1543], + &s_operands[1559], 4, }, { SpirvOp::OpUAverageINTEL, R"(OpUAverageINTEL)", - &s_operands[1547], + &s_operands[1563], 4, }, { SpirvOp::OpIAverageRoundedINTEL, R"(OpIAverageRoundedINTEL)", - &s_operands[1551], + &s_operands[1567], 4, }, { SpirvOp::OpUAverageRoundedINTEL, R"(OpUAverageRoundedINTEL)", - &s_operands[1555], + &s_operands[1571], 4, }, { SpirvOp::OpISubSatINTEL, R"(OpISubSatINTEL)", - &s_operands[1559], + &s_operands[1575], 4, }, { SpirvOp::OpUSubSatINTEL, R"(OpUSubSatINTEL)", - &s_operands[1563], + &s_operands[1579], 4, }, { SpirvOp::OpIMul32x16INTEL, R"(OpIMul32x16INTEL)", - &s_operands[1567], + &s_operands[1583], 4, }, { SpirvOp::OpUMul32x16INTEL, R"(OpUMul32x16INTEL)", - &s_operands[1571], + &s_operands[1587], 4, }, { - SpirvOp::OpFunctionPointerINTEL, - R"(OpFunctionPointerINTEL)", - &s_operands[1575], + SpirvOp::OpConstFunctionPointerINTEL, + R"(OpConstFunctionPointerINTEL)", + &s_operands[1591], 3, }, { SpirvOp::OpFunctionPointerCallINTEL, R"(OpFunctionPointerCallINTEL)", - &s_operands[1578], + &s_operands[1594], 3, }, + { + SpirvOp::OpAsmTargetINTEL, + R"(OpAsmTargetINTEL)", + &s_operands[1597], + 3, + }, + { + SpirvOp::OpAsmINTEL, + R"(OpAsmINTEL)", + &s_operands[1600], + 6, + }, + { + SpirvOp::OpAsmCallINTEL, + R"(OpAsmCallINTEL)", + &s_operands[1606], + 4, + }, + { + SpirvOp::OpAtomicFMinEXT, + R"(OpAtomicFMinEXT)", + &s_operands[1610], + 6, + }, + { + SpirvOp::OpAtomicFMaxEXT, + R"(OpAtomicFMaxEXT)", + &s_operands[1616], + 6, + }, { SpirvOp::OpDecorateStringGOOGLE, R"(OpDecorateStringGOOGLE)", - &s_operands[1581], + &s_operands[1622], 2, }, { SpirvOp::OpMemberDecorateStringGOOGLE, R"(OpMemberDecorateStringGOOGLE)", - &s_operands[1583], + &s_operands[1624], 3, }, { SpirvOp::OpVmeImageINTEL, R"(OpVmeImageINTEL)", - &s_operands[1586], + &s_operands[1627], 4, }, { SpirvOp::OpTypeVmeImageINTEL, R"(OpTypeVmeImageINTEL)", - &s_operands[1590], + &s_operands[1631], 2, }, { SpirvOp::OpTypeAvcImePayloadINTEL, R"(OpTypeAvcImePayloadINTEL)", - &s_operands[1592], + &s_operands[1633], 1, }, { SpirvOp::OpTypeAvcRefPayloadINTEL, R"(OpTypeAvcRefPayloadINTEL)", - &s_operands[1593], + &s_operands[1634], 1, }, { SpirvOp::OpTypeAvcSicPayloadINTEL, R"(OpTypeAvcSicPayloadINTEL)", - &s_operands[1594], + &s_operands[1635], 1, }, { SpirvOp::OpTypeAvcMcePayloadINTEL, R"(OpTypeAvcMcePayloadINTEL)", - &s_operands[1595], + &s_operands[1636], 1, }, { SpirvOp::OpTypeAvcMceResultINTEL, R"(OpTypeAvcMceResultINTEL)", - &s_operands[1596], + &s_operands[1637], 1, }, { SpirvOp::OpTypeAvcImeResultINTEL, R"(OpTypeAvcImeResultINTEL)", - &s_operands[1597], + &s_operands[1638], 1, }, { SpirvOp::OpTypeAvcImeResultSingleReferenceStreamoutINTEL, R"(OpTypeAvcImeResultSingleReferenceStreamoutINTEL)", - &s_operands[1598], + &s_operands[1639], 1, }, { SpirvOp::OpTypeAvcImeResultDualReferenceStreamoutINTEL, R"(OpTypeAvcImeResultDualReferenceStreamoutINTEL)", - &s_operands[1599], + &s_operands[1640], 1, }, { SpirvOp::OpTypeAvcImeSingleReferenceStreaminINTEL, R"(OpTypeAvcImeSingleReferenceStreaminINTEL)", - &s_operands[1600], + &s_operands[1641], 1, }, { SpirvOp::OpTypeAvcImeDualReferenceStreaminINTEL, R"(OpTypeAvcImeDualReferenceStreaminINTEL)", - &s_operands[1601], + &s_operands[1642], 1, }, { SpirvOp::OpTypeAvcRefResultINTEL, R"(OpTypeAvcRefResultINTEL)", - &s_operands[1602], + &s_operands[1643], 1, }, { SpirvOp::OpTypeAvcSicResultINTEL, R"(OpTypeAvcSicResultINTEL)", - &s_operands[1603], + &s_operands[1644], 1, }, { SpirvOp::OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL, R"(OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL)", - &s_operands[1604], + &s_operands[1645], 4, }, { SpirvOp::OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL, R"(OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL)", - &s_operands[1608], + &s_operands[1649], 4, }, { SpirvOp::OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL, R"(OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL)", - &s_operands[1612], + &s_operands[1653], 4, }, { SpirvOp::OpSubgroupAvcMceSetInterShapePenaltyINTEL, R"(OpSubgroupAvcMceSetInterShapePenaltyINTEL)", - &s_operands[1616], + &s_operands[1657], 4, }, { SpirvOp::OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL, R"(OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL)", - &s_operands[1620], + &s_operands[1661], 4, }, { SpirvOp::OpSubgroupAvcMceSetInterDirectionPenaltyINTEL, R"(OpSubgroupAvcMceSetInterDirectionPenaltyINTEL)", - &s_operands[1624], + &s_operands[1665], 4, }, { SpirvOp::OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL, R"(OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL)", - &s_operands[1628], + &s_operands[1669], 4, }, { SpirvOp::OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL, R"(OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL)", - &s_operands[1632], + &s_operands[1673], 4, }, { SpirvOp::OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL, R"(OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL)", - &s_operands[1636], + &s_operands[1677], 2, }, { SpirvOp::OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL, R"(OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL)", - &s_operands[1638], + &s_operands[1679], 2, }, { SpirvOp::OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL, R"(OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL)", - &s_operands[1640], + &s_operands[1681], 2, }, { SpirvOp::OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL, R"(OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL)", - &s_operands[1642], + &s_operands[1683], 6, }, { SpirvOp::OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL, R"(OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL)", - &s_operands[1648], + &s_operands[1689], 4, }, { SpirvOp::OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL, R"(OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL)", - &s_operands[1652], + &s_operands[1693], 2, }, { SpirvOp::OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL, R"(OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL)", - &s_operands[1654], + &s_operands[1695], 2, }, { SpirvOp::OpSubgroupAvcMceSetAcOnlyHaarINTEL, R"(OpSubgroupAvcMceSetAcOnlyHaarINTEL)", - &s_operands[1656], + &s_operands[1697], 3, }, { SpirvOp::OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL, R"(OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL)", - &s_operands[1659], + &s_operands[1700], 4, }, { SpirvOp::OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL, R"(OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL)", - &s_operands[1663], + &s_operands[1704], 4, }, { SpirvOp::OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL, R"(OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL)", - &s_operands[1667], + &s_operands[1708], 5, }, { SpirvOp::OpSubgroupAvcMceConvertToImePayloadINTEL, R"(OpSubgroupAvcMceConvertToImePayloadINTEL)", - &s_operands[1672], + &s_operands[1713], 3, }, { SpirvOp::OpSubgroupAvcMceConvertToImeResultINTEL, R"(OpSubgroupAvcMceConvertToImeResultINTEL)", - &s_operands[1675], + &s_operands[1716], 3, }, { SpirvOp::OpSubgroupAvcMceConvertToRefPayloadINTEL, R"(OpSubgroupAvcMceConvertToRefPayloadINTEL)", - &s_operands[1678], + &s_operands[1719], 3, }, { SpirvOp::OpSubgroupAvcMceConvertToRefResultINTEL, R"(OpSubgroupAvcMceConvertToRefResultINTEL)", - &s_operands[1681], + &s_operands[1722], 3, }, { SpirvOp::OpSubgroupAvcMceConvertToSicPayloadINTEL, R"(OpSubgroupAvcMceConvertToSicPayloadINTEL)", - &s_operands[1684], + &s_operands[1725], 3, }, { SpirvOp::OpSubgroupAvcMceConvertToSicResultINTEL, R"(OpSubgroupAvcMceConvertToSicResultINTEL)", - &s_operands[1687], + &s_operands[1728], 3, }, { SpirvOp::OpSubgroupAvcMceGetMotionVectorsINTEL, R"(OpSubgroupAvcMceGetMotionVectorsINTEL)", - &s_operands[1690], + &s_operands[1731], 3, }, { SpirvOp::OpSubgroupAvcMceGetInterDistortionsINTEL, R"(OpSubgroupAvcMceGetInterDistortionsINTEL)", - &s_operands[1693], + &s_operands[1734], 3, }, { SpirvOp::OpSubgroupAvcMceGetBestInterDistortionsINTEL, R"(OpSubgroupAvcMceGetBestInterDistortionsINTEL)", - &s_operands[1696], + &s_operands[1737], 3, }, { SpirvOp::OpSubgroupAvcMceGetInterMajorShapeINTEL, R"(OpSubgroupAvcMceGetInterMajorShapeINTEL)", - &s_operands[1699], + &s_operands[1740], 3, }, { SpirvOp::OpSubgroupAvcMceGetInterMinorShapeINTEL, R"(OpSubgroupAvcMceGetInterMinorShapeINTEL)", - &s_operands[1702], + &s_operands[1743], 3, }, { SpirvOp::OpSubgroupAvcMceGetInterDirectionsINTEL, R"(OpSubgroupAvcMceGetInterDirectionsINTEL)", - &s_operands[1705], + &s_operands[1746], 3, }, { SpirvOp::OpSubgroupAvcMceGetInterMotionVectorCountINTEL, R"(OpSubgroupAvcMceGetInterMotionVectorCountINTEL)", - &s_operands[1708], + &s_operands[1749], 3, }, { SpirvOp::OpSubgroupAvcMceGetInterReferenceIdsINTEL, R"(OpSubgroupAvcMceGetInterReferenceIdsINTEL)", - &s_operands[1711], + &s_operands[1752], 3, }, { SpirvOp::OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL, R"(OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL)", - &s_operands[1714], + &s_operands[1755], 5, }, { SpirvOp::OpSubgroupAvcImeInitializeINTEL, R"(OpSubgroupAvcImeInitializeINTEL)", - &s_operands[1719], + &s_operands[1760], 5, }, { SpirvOp::OpSubgroupAvcImeSetSingleReferenceINTEL, R"(OpSubgroupAvcImeSetSingleReferenceINTEL)", - &s_operands[1724], + &s_operands[1765], 5, }, { SpirvOp::OpSubgroupAvcImeSetDualReferenceINTEL, R"(OpSubgroupAvcImeSetDualReferenceINTEL)", - &s_operands[1729], + &s_operands[1770], 6, }, { SpirvOp::OpSubgroupAvcImeRefWindowSizeINTEL, R"(OpSubgroupAvcImeRefWindowSizeINTEL)", - &s_operands[1735], + &s_operands[1776], 4, }, { SpirvOp::OpSubgroupAvcImeAdjustRefOffsetINTEL, R"(OpSubgroupAvcImeAdjustRefOffsetINTEL)", - &s_operands[1739], + &s_operands[1780], 6, }, { SpirvOp::OpSubgroupAvcImeConvertToMcePayloadINTEL, R"(OpSubgroupAvcImeConvertToMcePayloadINTEL)", - &s_operands[1745], + &s_operands[1786], 3, }, { SpirvOp::OpSubgroupAvcImeSetMaxMotionVectorCountINTEL, R"(OpSubgroupAvcImeSetMaxMotionVectorCountINTEL)", - &s_operands[1748], + &s_operands[1789], 4, }, { SpirvOp::OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL, R"(OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL)", - &s_operands[1752], + &s_operands[1793], 3, }, { SpirvOp::OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL, R"(OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL)", - &s_operands[1755], + &s_operands[1796], 4, }, { SpirvOp::OpSubgroupAvcImeSetWeightedSadINTEL, R"(OpSubgroupAvcImeSetWeightedSadINTEL)", - &s_operands[1759], + &s_operands[1800], 4, }, { SpirvOp::OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL, R"(OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL)", - &s_operands[1763], + &s_operands[1804], 5, }, { SpirvOp::OpSubgroupAvcImeEvaluateWithDualReferenceINTEL, R"(OpSubgroupAvcImeEvaluateWithDualReferenceINTEL)", - &s_operands[1768], + &s_operands[1809], 6, }, { SpirvOp::OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL, R"(OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL)", - &s_operands[1774], + &s_operands[1815], 6, }, { SpirvOp::OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL, R"(OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL)", - &s_operands[1780], + &s_operands[1821], 7, }, { SpirvOp::OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL, R"(OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL)", - &s_operands[1787], + &s_operands[1828], 5, }, { SpirvOp::OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL, R"(OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL)", - &s_operands[1792], + &s_operands[1833], 6, }, { SpirvOp::OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL, R"(OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL)", - &s_operands[1798], + &s_operands[1839], 6, }, { SpirvOp::OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL, R"(OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL)", - &s_operands[1804], + &s_operands[1845], 7, }, { SpirvOp::OpSubgroupAvcImeConvertToMceResultINTEL, R"(OpSubgroupAvcImeConvertToMceResultINTEL)", - &s_operands[1811], + &s_operands[1852], 3, }, { SpirvOp::OpSubgroupAvcImeGetSingleReferenceStreaminINTEL, R"(OpSubgroupAvcImeGetSingleReferenceStreaminINTEL)", - &s_operands[1814], + &s_operands[1855], 3, }, { SpirvOp::OpSubgroupAvcImeGetDualReferenceStreaminINTEL, R"(OpSubgroupAvcImeGetDualReferenceStreaminINTEL)", - &s_operands[1817], + &s_operands[1858], 3, }, { SpirvOp::OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL, R"(OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL)", - &s_operands[1820], + &s_operands[1861], 3, }, { SpirvOp::OpSubgroupAvcImeStripDualReferenceStreamoutINTEL, R"(OpSubgroupAvcImeStripDualReferenceStreamoutINTEL)", - &s_operands[1823], + &s_operands[1864], 3, }, { SpirvOp::OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL, R"(OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL)", - &s_operands[1826], + &s_operands[1867], 4, }, { SpirvOp::OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL, R"(OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL)", - &s_operands[1830], + &s_operands[1871], 4, }, { SpirvOp::OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL, R"(OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL)", - &s_operands[1834], + &s_operands[1875], 4, }, { SpirvOp::OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL, R"(OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL)", - &s_operands[1838], + &s_operands[1879], 5, }, { SpirvOp::OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL, R"(OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL)", - &s_operands[1843], + &s_operands[1884], 5, }, { SpirvOp::OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL, R"(OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL)", - &s_operands[1848], + &s_operands[1889], 5, }, { SpirvOp::OpSubgroupAvcImeGetBorderReachedINTEL, R"(OpSubgroupAvcImeGetBorderReachedINTEL)", - &s_operands[1853], + &s_operands[1894], 4, }, { SpirvOp::OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL, R"(OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL)", - &s_operands[1857], + &s_operands[1898], 3, }, { SpirvOp::OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL, R"(OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL)", - &s_operands[1860], + &s_operands[1901], 3, }, { SpirvOp::OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL, R"(OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL)", - &s_operands[1863], + &s_operands[1904], 3, }, { SpirvOp::OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL, R"(OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL)", - &s_operands[1866], + &s_operands[1907], 3, }, { SpirvOp::OpSubgroupAvcFmeInitializeINTEL, R"(OpSubgroupAvcFmeInitializeINTEL)", - &s_operands[1869], + &s_operands[1910], 9, }, { SpirvOp::OpSubgroupAvcBmeInitializeINTEL, R"(OpSubgroupAvcBmeInitializeINTEL)", - &s_operands[1878], + &s_operands[1919], 10, }, { SpirvOp::OpSubgroupAvcRefConvertToMcePayloadINTEL, R"(OpSubgroupAvcRefConvertToMcePayloadINTEL)", - &s_operands[1888], + &s_operands[1929], 3, }, { SpirvOp::OpSubgroupAvcRefSetBidirectionalMixDisableINTEL, R"(OpSubgroupAvcRefSetBidirectionalMixDisableINTEL)", - &s_operands[1891], + &s_operands[1932], 3, }, { SpirvOp::OpSubgroupAvcRefSetBilinearFilterEnableINTEL, R"(OpSubgroupAvcRefSetBilinearFilterEnableINTEL)", - &s_operands[1894], + &s_operands[1935], 3, }, { SpirvOp::OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL, R"(OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL)", - &s_operands[1897], + &s_operands[1938], 5, }, { SpirvOp::OpSubgroupAvcRefEvaluateWithDualReferenceINTEL, R"(OpSubgroupAvcRefEvaluateWithDualReferenceINTEL)", - &s_operands[1902], + &s_operands[1943], 6, }, { SpirvOp::OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL, R"(OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL)", - &s_operands[1908], + &s_operands[1949], 5, }, { SpirvOp::OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL, R"(OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL)", - &s_operands[1913], + &s_operands[1954], 6, }, { SpirvOp::OpSubgroupAvcRefConvertToMceResultINTEL, R"(OpSubgroupAvcRefConvertToMceResultINTEL)", - &s_operands[1919], + &s_operands[1960], 3, }, { SpirvOp::OpSubgroupAvcSicInitializeINTEL, R"(OpSubgroupAvcSicInitializeINTEL)", - &s_operands[1922], + &s_operands[1963], 3, }, { SpirvOp::OpSubgroupAvcSicConfigureSkcINTEL, R"(OpSubgroupAvcSicConfigureSkcINTEL)", - &s_operands[1925], + &s_operands[1966], 8, }, { SpirvOp::OpSubgroupAvcSicConfigureIpeLumaINTEL, R"(OpSubgroupAvcSicConfigureIpeLumaINTEL)", - &s_operands[1933], + &s_operands[1974], 10, }, { SpirvOp::OpSubgroupAvcSicConfigureIpeLumaChromaINTEL, R"(OpSubgroupAvcSicConfigureIpeLumaChromaINTEL)", - &s_operands[1943], + &s_operands[1984], 13, }, { SpirvOp::OpSubgroupAvcSicGetMotionVectorMaskINTEL, R"(OpSubgroupAvcSicGetMotionVectorMaskINTEL)", - &s_operands[1956], + &s_operands[1997], 4, }, { SpirvOp::OpSubgroupAvcSicConvertToMcePayloadINTEL, R"(OpSubgroupAvcSicConvertToMcePayloadINTEL)", - &s_operands[1960], + &s_operands[2001], 3, }, { SpirvOp::OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL, R"(OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL)", - &s_operands[1963], + &s_operands[2004], 4, }, { SpirvOp::OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL, R"(OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL)", - &s_operands[1967], + &s_operands[2008], 6, }, { SpirvOp::OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL, R"(OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL)", - &s_operands[1973], + &s_operands[2014], 4, }, { SpirvOp::OpSubgroupAvcSicSetBilinearFilterEnableINTEL, R"(OpSubgroupAvcSicSetBilinearFilterEnableINTEL)", - &s_operands[1977], + &s_operands[2018], 3, }, { SpirvOp::OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL, R"(OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL)", - &s_operands[1980], + &s_operands[2021], 4, }, { SpirvOp::OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL, R"(OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL)", - &s_operands[1984], + &s_operands[2025], 4, }, { SpirvOp::OpSubgroupAvcSicEvaluateIpeINTEL, R"(OpSubgroupAvcSicEvaluateIpeINTEL)", - &s_operands[1988], + &s_operands[2029], 4, }, { SpirvOp::OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL, R"(OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL)", - &s_operands[1992], + &s_operands[2033], 5, }, { SpirvOp::OpSubgroupAvcSicEvaluateWithDualReferenceINTEL, R"(OpSubgroupAvcSicEvaluateWithDualReferenceINTEL)", - &s_operands[1997], + &s_operands[2038], 6, }, { SpirvOp::OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL, R"(OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL)", - &s_operands[2003], + &s_operands[2044], 5, }, { SpirvOp::OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL, R"(OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL)", - &s_operands[2008], + &s_operands[2049], 6, }, { SpirvOp::OpSubgroupAvcSicConvertToMceResultINTEL, R"(OpSubgroupAvcSicConvertToMceResultINTEL)", - &s_operands[2014], + &s_operands[2055], 3, }, { SpirvOp::OpSubgroupAvcSicGetIpeLumaShapeINTEL, R"(OpSubgroupAvcSicGetIpeLumaShapeINTEL)", - &s_operands[2017], + &s_operands[2058], 3, }, { SpirvOp::OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL, R"(OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL)", - &s_operands[2020], + &s_operands[2061], 3, }, { SpirvOp::OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL, R"(OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL)", - &s_operands[2023], + &s_operands[2064], 3, }, { SpirvOp::OpSubgroupAvcSicGetPackedIpeLumaModesINTEL, R"(OpSubgroupAvcSicGetPackedIpeLumaModesINTEL)", - &s_operands[2026], + &s_operands[2067], 3, }, { SpirvOp::OpSubgroupAvcSicGetIpeChromaModeINTEL, R"(OpSubgroupAvcSicGetIpeChromaModeINTEL)", - &s_operands[2029], + &s_operands[2070], 3, }, { SpirvOp::OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL, R"(OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL)", - &s_operands[2032], + &s_operands[2073], 3, }, { SpirvOp::OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL, R"(OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL)", - &s_operands[2035], + &s_operands[2076], 3, }, { SpirvOp::OpSubgroupAvcSicGetInterRawSadsINTEL, R"(OpSubgroupAvcSicGetInterRawSadsINTEL)", - &s_operands[2038], + &s_operands[2079], 3, }, + { + SpirvOp::OpVariableLengthArrayINTEL, + R"(OpVariableLengthArrayINTEL)", + &s_operands[2082], + 3, + }, + { + SpirvOp::OpSaveMemoryINTEL, + R"(OpSaveMemoryINTEL)", + &s_operands[2085], + 2, + }, + { + SpirvOp::OpRestoreMemoryINTEL, + R"(OpRestoreMemoryINTEL)", + &s_operands[2087], + 1, + }, { SpirvOp::OpLoopControlINTEL, R"(OpLoopControlINTEL)", - &s_operands[2041], + &s_operands[2088], 1, }, + { + SpirvOp::OpPtrCastToCrossWorkgroupINTEL, + R"(OpPtrCastToCrossWorkgroupINTEL)", + &s_operands[2089], + 3, + }, + { + SpirvOp::OpCrossWorkgroupCastToPtrINTEL, + R"(OpCrossWorkgroupCastToPtrINTEL)", + &s_operands[2092], + 3, + }, { SpirvOp::OpReadPipeBlockingINTEL, R"(OpReadPipeBlockingINTEL)", - &s_operands[2042], + &s_operands[2095], 4, }, { SpirvOp::OpWritePipeBlockingINTEL, R"(OpWritePipeBlockingINTEL)", - &s_operands[2046], + &s_operands[2099], 4, }, { SpirvOp::OpFPGARegINTEL, R"(OpFPGARegINTEL)", - &s_operands[2050], + &s_operands[2103], 4, }, { SpirvOp::OpRayQueryGetRayTMinKHR, R"(OpRayQueryGetRayTMinKHR)", - &s_operands[2054], + &s_operands[2107], 3, }, { SpirvOp::OpRayQueryGetRayFlagsKHR, R"(OpRayQueryGetRayFlagsKHR)", - &s_operands[2057], + &s_operands[2110], 3, }, { SpirvOp::OpRayQueryGetIntersectionTKHR, R"(OpRayQueryGetIntersectionTKHR)", - &s_operands[2060], + &s_operands[2113], 4, }, { SpirvOp::OpRayQueryGetIntersectionInstanceCustomIndexKHR, R"(OpRayQueryGetIntersectionInstanceCustomIndexKHR)", - &s_operands[2064], + &s_operands[2117], 4, }, { SpirvOp::OpRayQueryGetIntersectionInstanceIdKHR, R"(OpRayQueryGetIntersectionInstanceIdKHR)", - &s_operands[2068], + &s_operands[2121], 4, }, { SpirvOp::OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR, R"(OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR)", - &s_operands[2072], + &s_operands[2125], 4, }, { SpirvOp::OpRayQueryGetIntersectionGeometryIndexKHR, R"(OpRayQueryGetIntersectionGeometryIndexKHR)", - &s_operands[2076], + &s_operands[2129], 4, }, { SpirvOp::OpRayQueryGetIntersectionPrimitiveIndexKHR, R"(OpRayQueryGetIntersectionPrimitiveIndexKHR)", - &s_operands[2080], + &s_operands[2133], 4, }, { SpirvOp::OpRayQueryGetIntersectionBarycentricsKHR, R"(OpRayQueryGetIntersectionBarycentricsKHR)", - &s_operands[2084], + &s_operands[2137], 4, }, { SpirvOp::OpRayQueryGetIntersectionFrontFaceKHR, R"(OpRayQueryGetIntersectionFrontFaceKHR)", - &s_operands[2088], + &s_operands[2141], 4, }, { SpirvOp::OpRayQueryGetIntersectionCandidateAABBOpaqueKHR, R"(OpRayQueryGetIntersectionCandidateAABBOpaqueKHR)", - &s_operands[2092], + &s_operands[2145], 3, }, { SpirvOp::OpRayQueryGetIntersectionObjectRayDirectionKHR, R"(OpRayQueryGetIntersectionObjectRayDirectionKHR)", - &s_operands[2095], + &s_operands[2148], 4, }, { SpirvOp::OpRayQueryGetIntersectionObjectRayOriginKHR, R"(OpRayQueryGetIntersectionObjectRayOriginKHR)", - &s_operands[2099], + &s_operands[2152], 4, }, { SpirvOp::OpRayQueryGetWorldRayDirectionKHR, R"(OpRayQueryGetWorldRayDirectionKHR)", - &s_operands[2103], + &s_operands[2156], 3, }, { SpirvOp::OpRayQueryGetWorldRayOriginKHR, R"(OpRayQueryGetWorldRayOriginKHR)", - &s_operands[2106], + &s_operands[2159], 3, }, { SpirvOp::OpRayQueryGetIntersectionObjectToWorldKHR, R"(OpRayQueryGetIntersectionObjectToWorldKHR)", - &s_operands[2109], + &s_operands[2162], 4, }, { SpirvOp::OpRayQueryGetIntersectionWorldToObjectKHR, R"(OpRayQueryGetIntersectionWorldToObjectKHR)", - &s_operands[2113], + &s_operands[2166], 4, }, { SpirvOp::OpAtomicFAddEXT, R"(OpAtomicFAddEXT)", - &s_operands[2117], + &s_operands[2170], 6, }, + { + SpirvOp::OpTypeBufferSurfaceINTEL, + R"(OpTypeBufferSurfaceINTEL)", + &s_operands[2176], + 1, + }, + { + SpirvOp::OpTypeStructContinuedINTEL, + R"(OpTypeStructContinuedINTEL)", + &s_operands[2177], + 1, + }, + { + SpirvOp::OpConstantCompositeContinuedINTEL, + R"(OpConstantCompositeContinuedINTEL)", + &s_operands[2178], + 1, + }, + { + SpirvOp::OpSpecConstantCompositeContinuedINTEL, + R"(OpSpecConstantCompositeContinuedINTEL)", + &s_operands[2179], + 1, + }, } }; From 36be581d9a5dcf087b2bc96041caaeba01ac436b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 19 Feb 2021 14:51:06 +0100 Subject: [PATCH 060/278] Shader/SpirV: Fix missing OpSelectionMerge before branching --- src/Nazara/Shader/SpirvAstVisitor.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Nazara/Shader/SpirvAstVisitor.cpp b/src/Nazara/Shader/SpirvAstVisitor.cpp index 9c6797ff9..fee8b7d2e 100644 --- a/src/Nazara/Shader/SpirvAstVisitor.cpp +++ b/src/Nazara/Shader/SpirvAstVisitor.cpp @@ -452,6 +452,9 @@ namespace Nz m_currentBlock = &previousContentBlock; Visit(firstCond.statement); + SpirvBlock mergeBlock(m_writer); + m_blocks.back().Append(SpirvOp::OpSelectionMerge, mergeBlock.GetLabelId(), SpirvSelectionControl::None); + std::optional nextBlock; for (std::size_t statementIndex = 1; statementIndex < node.condStatements.size(); ++statementIndex) { @@ -469,8 +472,6 @@ namespace Nz Visit(statement.statement); } - SpirvBlock mergeBlock(m_writer); - if (node.elseStatement) { SpirvBlock elseBlock(m_writer); From 7c5b1844d343de80313cab52cdf80eb9a0c8c705 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 19 Feb 2021 14:51:21 +0100 Subject: [PATCH 061/278] Core/Flag: Improve code --- include/Nazara/Core/Flags.hpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/include/Nazara/Core/Flags.hpp b/include/Nazara/Core/Flags.hpp index e87d21158..2211a9d9f 100644 --- a/include/Nazara/Core/Flags.hpp +++ b/include/Nazara/Core/Flags.hpp @@ -18,33 +18,29 @@ namespace Nz { }; + template struct IsEnumFlag : std::false_type {}; template struct IsEnumFlag::max)>> : std::true_type {}; + template - struct GetEnumAutoFlag : std::false_type - { - static constexpr bool value = true; - }; + struct GetEnumAutoFlag : std::integral_constant {}; template - struct GetEnumAutoFlag> : std::true_type - { - static constexpr bool value = T::AutoFlag; - }; + struct GetEnumAutoFlag> : std::integral_constant {}; template class Flags { - static_assert(std::is_enum::value, "Type must be an enumeration"); - static_assert(IsEnumFlag::value, "Enum has not been enabled as flags by an EnumAsFlags specialization"); + static_assert(std::is_enum_v, "Type must be an enumeration"); + static_assert(IsEnumFlag(), "Enum has not been enabled as flags by an EnumAsFlags specialization"); static_assert(std::is_same_v::max)>, E>, "EnumAsFlags field max should be of the same type as the enum"); static constexpr std::size_t MaxValue = static_cast(EnumAsFlags::max); - static constexpr bool AutoFlag = GetEnumAutoFlag::value; + static constexpr bool AutoFlag = GetEnumAutoFlag(); using BitField16 = std::conditional_t<(MaxValue >= 8), UInt16, UInt8>; using BitField32 = std::conditional_t<(MaxValue >= 16), UInt32, BitField16>; From ac3db8a8bfc11cb734f8046988c22eeb81f91882 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sat, 20 Feb 2021 18:01:03 +0100 Subject: [PATCH 062/278] Utility/PixelFormat: Add preliminary support for SRGB formats (WIP) --- include/Nazara/OpenGLRenderer/Utils.inl | 15 ++++-- include/Nazara/Utility/Enums.hpp | 4 ++ include/Nazara/Utility/PixelFormat.inl | 17 +------ include/Nazara/VulkanRenderer/Utils.inl | 2 + src/Nazara/Utility/PixelFormat.cpp | 55 +++++++++++++++++++-- src/Nazara/VulkanRenderer/VulkanTexture.cpp | 28 ++++------- 6 files changed, 78 insertions(+), 43 deletions(-) diff --git a/include/Nazara/OpenGLRenderer/Utils.inl b/include/Nazara/OpenGLRenderer/Utils.inl index fcae4116a..0887b2e83 100644 --- a/include/Nazara/OpenGLRenderer/Utils.inl +++ b/include/Nazara/OpenGLRenderer/Utils.inl @@ -15,11 +15,16 @@ namespace Nz // TODO: Fill this switch switch (pixelFormat) { - case PixelFormat_A8: return GLTextureFormat { GL_R8, GL_RED, GL_UNSIGNED_BYTE, GL_ZERO, GL_ZERO, GL_ZERO, GL_RED }; - case PixelFormat_BGR8: return GLTextureFormat { GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE, GL_BLUE, GL_GREEN, GL_RED, GL_ONE }; - case PixelFormat_BGRA8: return GLTextureFormat { GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA }; - case PixelFormat_RGB8: return GLTextureFormat { GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE, GL_RED, GL_GREEN, GL_BLUE, GL_ONE }; - case PixelFormat_RGBA8: return GLTextureFormat { GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; + case PixelFormat_A8: return GLTextureFormat{ GL_R8, GL_RED, GL_UNSIGNED_BYTE, GL_ZERO, GL_ZERO, GL_ZERO, GL_RED }; + case PixelFormat_BGR8: return GLTextureFormat{ GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, GL_BLUE, GL_GREEN, GL_RED, GL_ONE }; + case PixelFormat_BGR8_SRGB: return GLTextureFormat{ GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE, GL_BLUE, GL_GREEN, GL_RED, GL_ONE }; + case PixelFormat_BGRA8: return GLTextureFormat{ GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA }; + case PixelFormat_BGRA8_SRGB: return GLTextureFormat{ GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA }; + case PixelFormat_Depth24Stencil8: return GLTextureFormat{ GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_RED, GL_GREEN, GL_ZERO, GL_ZERO }; + case PixelFormat_RGB8: return GLTextureFormat{ GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, GL_RED, GL_GREEN, GL_BLUE, GL_ONE }; + case PixelFormat_RGB8_SRGB: return GLTextureFormat{ GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE, GL_RED, GL_GREEN, GL_BLUE, GL_ONE }; + case PixelFormat_RGBA8: return GLTextureFormat{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; + case PixelFormat_RGBA8_SRGB: return GLTextureFormat{ GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; default: break; } diff --git a/include/Nazara/Utility/Enums.hpp b/include/Nazara/Utility/Enums.hpp index 6f556da16..4112ce48b 100644 --- a/include/Nazara/Utility/Enums.hpp +++ b/include/Nazara/Utility/Enums.hpp @@ -174,7 +174,9 @@ namespace Nz PixelFormat_A8, // 1*uint8 PixelFormat_BGR8, // 3*uint8 + PixelFormat_BGR8_SRGB, // 3*uint8 PixelFormat_BGRA8, // 4*uint8 + PixelFormat_BGRA8_SRGB, // 4*uint8 PixelFormat_DXT1, PixelFormat_DXT3, PixelFormat_DXT5, @@ -202,6 +204,7 @@ namespace Nz PixelFormat_RG32UI, // 2*uint32 PixelFormat_RGB5A1, // 3*uint5 + alpha bit PixelFormat_RGB8, // 3*uint8 + PixelFormat_RGB8_SRGB, // 3*uint8 PixelFormat_RGB16F, // 3*half PixelFormat_RGB16I, // 4*int16 PixelFormat_RGB16UI, // 4*uint16 @@ -210,6 +213,7 @@ namespace Nz PixelFormat_RGB32UI, // 4*uint32 PixelFormat_RGBA4, // 4*uint4 PixelFormat_RGBA8, // 4*uint8 + PixelFormat_RGBA8_SRGB, // 4*uint8 PixelFormat_RGBA16F, // 4*half PixelFormat_RGBA16I, // 4*int16 PixelFormat_RGBA16UI, // 4*uint16 diff --git a/include/Nazara/Utility/PixelFormat.inl b/include/Nazara/Utility/PixelFormat.inl index 6f0170607..e9b30f0ec 100644 --- a/include/Nazara/Utility/PixelFormat.inl +++ b/include/Nazara/Utility/PixelFormat.inl @@ -185,27 +185,14 @@ namespace Nz } #endif - ConvertFunction func = s_convertFunctions[srcFormat][dstFormat]; - if (!func) - { - NazaraError("Pixel format conversion from " + GetName(srcFormat) + " to " + GetName(dstFormat) + " is not supported"); - return false; - } - - if (!func(reinterpret_cast(src), reinterpret_cast(src) + GetBytesPerPixel(srcFormat), reinterpret_cast(dst))) - { - NazaraError("Pixel format conversion from " + GetName(srcFormat) + " to " + GetName(dstFormat) + " failed"); - return false; - } - - return true; + return Convert(srcFormat, dstFormat, src, static_cast(src) + GetBytesPerPixel(srcFormat), dst); } inline bool PixelFormatInfo::Convert(PixelFormat srcFormat, PixelFormat dstFormat, const void* start, const void* end, void* dst) { if (srcFormat == dstFormat) { - std::memcpy(dst, start, reinterpret_cast(end)-reinterpret_cast(start)); + std::memcpy(dst, start, reinterpret_cast(end) - reinterpret_cast(start)); return true; } diff --git a/include/Nazara/VulkanRenderer/Utils.inl b/include/Nazara/VulkanRenderer/Utils.inl index 90eba6933..a9a872601 100644 --- a/include/Nazara/VulkanRenderer/Utils.inl +++ b/include/Nazara/VulkanRenderer/Utils.inl @@ -15,9 +15,11 @@ namespace Nz switch (format) { case VK_FORMAT_B8G8R8A8_UNORM: return PixelFormat::PixelFormat_BGRA8; + case VK_FORMAT_B8G8R8A8_SRGB: return PixelFormat::PixelFormat_BGRA8_SRGB; case VK_FORMAT_D24_UNORM_S8_UINT: return PixelFormat::PixelFormat_Depth24Stencil8; case VK_FORMAT_D32_SFLOAT: return PixelFormat::PixelFormat_Depth32; case VK_FORMAT_R8G8B8A8_UNORM: return PixelFormat::PixelFormat_RGBA8; + case VK_FORMAT_R8G8B8A8_SRGB: return PixelFormat::PixelFormat_RGBA8_SRGB; default: break; } diff --git a/src/Nazara/Utility/PixelFormat.cpp b/src/Nazara/Utility/PixelFormat.cpp index b169afd4f..d5ecff45e 100644 --- a/src/Nazara/Utility/PixelFormat.cpp +++ b/src/Nazara/Utility/PixelFormat.cpp @@ -157,6 +157,15 @@ namespace Nz return dst; } + template<> + UInt8* ConvertPixels(const UInt8* start, const UInt8* end, UInt8* dst) + { + //FIXME: Not correct + std::size_t count = end - start; + std::memcpy(dst, start, count); + return dst + count; + } + template<> UInt8* ConvertPixels(const UInt8* start, const UInt8* end, UInt8* dst) { @@ -288,6 +297,15 @@ namespace Nz return dst; } + template<> + UInt8* ConvertPixels(const UInt8* start, const UInt8* end, UInt8* dst) + { + //FIXME: Not correct + std::size_t count = end - start; + std::memcpy(dst, start, count); + return dst + count; + } + template<> UInt8* ConvertPixels(const UInt8* start, const UInt8* end, UInt8* dst) { @@ -1114,6 +1132,15 @@ namespace Nz return dst; } + template<> + UInt8* ConvertPixels(const UInt8* start, const UInt8* end, UInt8* dst) + { + //FIXME: Not correct + std::size_t count = end - start; + std::memcpy(dst, start, count); + return dst + count; + } + template<> UInt8* ConvertPixels(const UInt8* start, const UInt8* end, UInt8* dst) { @@ -1261,10 +1288,20 @@ namespace Nz return dst; } - template + template<> + UInt8* ConvertPixels(const UInt8* start, const UInt8* end, UInt8* dst) + { + //FIXME: Not correct + std::size_t count = end - start; + std::memcpy(dst, start, count); + return dst + count; + } + + + template void RegisterConverter() { - PixelFormatInfo::SetConvertFunction(format1, format2, &ConvertPixels); + PixelFormatInfo::SetConvertFunction(Format1, Format2, &ConvertPixels); } } @@ -1386,7 +1423,9 @@ namespace Nz // Setup informations about every pixel format s_pixelFormatInfos[PixelFormat_A8] = PixelFormatDescription("A8", PixelFormatContent_ColorRGBA, 0, 0, 0, 0xFF, PixelFormatSubType_Unsigned); s_pixelFormatInfos[PixelFormat_BGR8] = PixelFormatDescription("BGR8", PixelFormatContent_ColorRGBA, 0x0000FF, 0x00FF00, 0xFF0000, 0, PixelFormatSubType_Unsigned); + s_pixelFormatInfos[PixelFormat_BGR8_SRGB] = PixelFormatDescription("BGR8_SRGB", PixelFormatContent_ColorRGBA, 0x0000FF, 0x00FF00, 0xFF0000, 0, PixelFormatSubType_Unsigned); s_pixelFormatInfos[PixelFormat_BGRA8] = PixelFormatDescription("BGRA8", PixelFormatContent_ColorRGBA, 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF, PixelFormatSubType_Unsigned); + s_pixelFormatInfos[PixelFormat_BGRA8_SRGB] = PixelFormatDescription("BGRA8_SRGB", PixelFormatContent_ColorRGBA, 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF, PixelFormatSubType_Unsigned); s_pixelFormatInfos[PixelFormat_DXT1] = PixelFormatDescription("DXT1", PixelFormatContent_ColorRGBA, 8, PixelFormatSubType_Compressed); s_pixelFormatInfos[PixelFormat_DXT3] = PixelFormatDescription("DXT3", PixelFormatContent_ColorRGBA, 16, PixelFormatSubType_Compressed); s_pixelFormatInfos[PixelFormat_DXT5] = PixelFormatDescription("DXT5", PixelFormatContent_ColorRGBA, 16, PixelFormatSubType_Compressed); @@ -1413,6 +1452,7 @@ namespace Nz s_pixelFormatInfos[PixelFormat_RG32I] = PixelFormatDescription("RG32I", PixelFormatContent_ColorRGBA, 0xFFFFFFFF00000000, 0x00000000FFFFFFFF, 0, 0, PixelFormatSubType_Int); s_pixelFormatInfos[PixelFormat_RG32UI] = PixelFormatDescription("RG32UI", PixelFormatContent_ColorRGBA, 0xFFFFFFFF00000000, 0x00000000FFFFFFFF, 0, 0, PixelFormatSubType_Unsigned); s_pixelFormatInfos[PixelFormat_RGB8] = PixelFormatDescription("RGB8", PixelFormatContent_ColorRGBA, 0xFF000000, 0x00FF0000, 0x0000FF00, 0, PixelFormatSubType_Unsigned); + s_pixelFormatInfos[PixelFormat_RGB8_SRGB] = PixelFormatDescription("RGB8_SRGB", PixelFormatContent_ColorRGBA, 0xFF000000, 0x00FF0000, 0x0000FF00, 0, PixelFormatSubType_Unsigned); s_pixelFormatInfos[PixelFormat_RGB16F] = PixelFormatDescription("RGB16F", PixelFormatContent_ColorRGBA, 0xFFFF00000000, 0x0000FFFF0000, 0x00000000FFFF, 0, PixelFormatSubType_Half); s_pixelFormatInfos[PixelFormat_RGB16I] = PixelFormatDescription("RGB16I", PixelFormatContent_ColorRGBA, 0xFFFF00000000, 0x0000FFFF0000, 0x00000000FFFF, 0, PixelFormatSubType_Int); s_pixelFormatInfos[PixelFormat_RGB16UI] = PixelFormatDescription("RGB16UI", PixelFormatContent_ColorRGBA, 0xFFFF000000000000, 0x0000FFFF00000000, 0x00000000FFFF0000, 0, PixelFormatSubType_Unsigned); @@ -1422,16 +1462,17 @@ namespace Nz s_pixelFormatInfos[PixelFormat_RGBA4] = PixelFormatDescription("RGBA4", PixelFormatContent_ColorRGBA, 0xF000, 0x0F00, 0x00F0, 0x000F, PixelFormatSubType_Unsigned); s_pixelFormatInfos[PixelFormat_RGB5A1] = PixelFormatDescription("RGB5A1", PixelFormatContent_ColorRGBA, 0xF800, 0x07C0, 0x003E, 0x0001, PixelFormatSubType_Unsigned); s_pixelFormatInfos[PixelFormat_RGBA8] = PixelFormatDescription("RGBA8", PixelFormatContent_ColorRGBA, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF, PixelFormatSubType_Unsigned); + s_pixelFormatInfos[PixelFormat_RGBA8_SRGB] = PixelFormatDescription("RGBA8_SRGB", PixelFormatContent_ColorRGBA, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF, PixelFormatSubType_Unsigned); s_pixelFormatInfos[PixelFormat_RGBA16F] = PixelFormatDescription("RGBA16F", PixelFormatContent_ColorRGBA, 0xFFFF000000000000, 0x0000FFFF00000000, 0x00000000FFFF0000, 0x000000000000FFFF, PixelFormatSubType_Half); s_pixelFormatInfos[PixelFormat_RGBA16I] = PixelFormatDescription("RGBA16I", PixelFormatContent_ColorRGBA, 0xFFFF000000000000, 0x0000FFFF00000000, 0x00000000FFFF0000, 0x000000000000FFFF, PixelFormatSubType_Int); s_pixelFormatInfos[PixelFormat_RGBA16UI] = PixelFormatDescription("RGBA16UI", PixelFormatContent_ColorRGBA, 0xFFFF000000000000, 0x0000FFFF00000000, 0x00000000FFFF0000, 0x000000000000FFFF, PixelFormatSubType_Unsigned); s_pixelFormatInfos[PixelFormat_RGBA32F] = PixelFormatDescription("RGBA32F", PixelFormatContent_ColorRGBA, b32, b32 >> 32, b32 >> 64, b32 >> 96, PixelFormatSubType_Float); s_pixelFormatInfos[PixelFormat_RGBA32I] = PixelFormatDescription("RGBA32I", PixelFormatContent_ColorRGBA, b32, b32 >> 32, b32 >> 64, b32 >> 96, PixelFormatSubType_Int); s_pixelFormatInfos[PixelFormat_RGBA32UI] = PixelFormatDescription("RGBA32UI", PixelFormatContent_ColorRGBA, b32, b32 >> 32, b32 >> 64, b32 >> 96, PixelFormatSubType_Unsigned); - s_pixelFormatInfos[PixelFormat_Depth16] = PixelFormatDescription("Depth16", PixelFormatContent_DepthStencil, 0xFFFF, 0, 0, 0, PixelFormatSubType_Unsigned); - s_pixelFormatInfos[PixelFormat_Depth24] = PixelFormatDescription("Depth24", PixelFormatContent_DepthStencil, 0xFFFFFF, 0, 0, 0, PixelFormatSubType_Unsigned); + s_pixelFormatInfos[PixelFormat_Depth16] = PixelFormatDescription("Depth16", PixelFormatContent_Depth, 0xFFFF, 0, 0, 0, PixelFormatSubType_Unsigned); + s_pixelFormatInfos[PixelFormat_Depth24] = PixelFormatDescription("Depth24", PixelFormatContent_Depth, 0xFFFFFF, 0, 0, 0, PixelFormatSubType_Unsigned); s_pixelFormatInfos[PixelFormat_Depth24Stencil8] = PixelFormatDescription("Depth24Stencil8", PixelFormatContent_DepthStencil, 0xFFFFFF00, 0x000000FF, 0, 0, PixelFormatSubType_Unsigned); - s_pixelFormatInfos[PixelFormat_Depth32] = PixelFormatDescription("Depth32", PixelFormatContent_DepthStencil, 0xFFFFFFFF, 0, 0, 0, PixelFormatSubType_Unsigned); + s_pixelFormatInfos[PixelFormat_Depth32] = PixelFormatDescription("Depth32", PixelFormatContent_Depth, 0xFFFFFFFF, 0, 0, 0, PixelFormatSubType_Unsigned); s_pixelFormatInfos[PixelFormat_Stencil1] = PixelFormatDescription("Stencil1", PixelFormatContent_Stencil, 0x1, 0, 0, 0, PixelFormatSubType_Unsigned); s_pixelFormatInfos[PixelFormat_Stencil4] = PixelFormatDescription("Stencil4", PixelFormatContent_Stencil, 0xF, 0, 0, 0, PixelFormatSubType_Unsigned); s_pixelFormatInfos[PixelFormat_Stencil8] = PixelFormatDescription("Stencil8", PixelFormatContent_Stencil, 0xFF, 0, 0, 0, PixelFormatSubType_Unsigned); @@ -1454,6 +1495,7 @@ namespace Nz RegisterConverter(); /**********************************BGR8***********************************/ + RegisterConverter(); RegisterConverter(); RegisterConverter(); RegisterConverter();/* @@ -1473,6 +1515,7 @@ namespace Nz /**********************************BGRA8**********************************/ RegisterConverter(); RegisterConverter(); + RegisterConverter(); RegisterConverter(); RegisterConverter();/* RegisterConverter(); @@ -1642,6 +1685,7 @@ namespace Nz RegisterConverter(); RegisterConverter();*/ RegisterConverter(); + RegisterConverter(); RegisterConverter(); RegisterConverter(); @@ -1662,6 +1706,7 @@ namespace Nz RegisterConverter(); RegisterConverter(); RegisterConverter(); + RegisterConverter(); return true; } diff --git a/src/Nazara/VulkanRenderer/VulkanTexture.cpp b/src/Nazara/VulkanRenderer/VulkanTexture.cpp index 5574bb755..377370946 100644 --- a/src/Nazara/VulkanRenderer/VulkanTexture.cpp +++ b/src/Nazara/VulkanRenderer/VulkanTexture.cpp @@ -231,13 +231,19 @@ namespace Nz switch (pixelFormat) { case PixelFormat_BGR8: + case PixelFormat_BGR8_SRGB: + case PixelFormat_BGRA8: + case PixelFormat_BGRA8_SRGB: + case PixelFormat_RGB8: + case PixelFormat_RGB8_SRGB: + case PixelFormat_RGBA8: + case PixelFormat_RGBA8_SRGB: { - createImage.format = VK_FORMAT_B8G8R8_SRGB; + createImage.format = ToVulkan(pixelFormat); createImageView.format = createImage.format; break; } - case PixelFormat_BGRA8: { createImage.format = VK_FORMAT_B8G8R8A8_SRGB; createImageView.format = createImage.format; @@ -246,7 +252,7 @@ namespace Nz case PixelFormat_L8: { - createImage.format = VK_FORMAT_R8_SRGB; + createImage.format = VK_FORMAT_R8_UNORM; createImageView.format = createImage.format; createImageView.components = { VK_COMPONENT_SWIZZLE_R, @@ -259,7 +265,7 @@ namespace Nz case PixelFormat_LA8: { - createImage.format = VK_FORMAT_R8G8_SRGB; + createImage.format = VK_FORMAT_R8G8_UNORM; createImageView.format = createImage.format; createImageView.components = { VK_COMPONENT_SWIZZLE_R, @@ -270,20 +276,6 @@ namespace Nz break; } - case PixelFormat_RGB8: - { - createImage.format = VK_FORMAT_R8G8B8_SRGB; - createImageView.format = createImage.format; - break; - } - - case PixelFormat_RGBA8: - { - createImage.format = VK_FORMAT_R8G8B8A8_SRGB; - createImageView.format = createImage.format; - break; - } - default: throw std::runtime_error("Unsupported pixel format " + PixelFormatInfo::GetName(pixelFormat)); } From 8f9f943e2c9aebe83db3195e6152cd0bf5426060 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sat, 20 Feb 2021 18:56:54 +0100 Subject: [PATCH 063/278] OpenGLRenderer: Implement primitive mode --- include/Nazara/OpenGLRenderer/Utils.hpp | 1 + include/Nazara/OpenGLRenderer/Utils.inl | 16 ++++++++++++++++ .../OpenGLRenderer/OpenGLCommandBuffer.cpp | 4 ++-- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/include/Nazara/OpenGLRenderer/Utils.hpp b/include/Nazara/OpenGLRenderer/Utils.hpp index 8c28d2419..46c5e2ed2 100644 --- a/include/Nazara/OpenGLRenderer/Utils.hpp +++ b/include/Nazara/OpenGLRenderer/Utils.hpp @@ -31,6 +31,7 @@ namespace Nz inline GLenum ToOpenGL(BlendFunc blendFunc); inline GLenum ToOpenGL(FaceSide filter); + inline GLenum ToOpenGL(PrimitiveMode primitiveMode); inline GLenum ToOpenGL(SamplerFilter filter); inline GLenum ToOpenGL(SamplerFilter minFilter, SamplerMipmapMode mipmapFilter); inline GLenum ToOpenGL(SamplerWrap wrapMode); diff --git a/include/Nazara/OpenGLRenderer/Utils.inl b/include/Nazara/OpenGLRenderer/Utils.inl index 0887b2e83..3ddffacf8 100644 --- a/include/Nazara/OpenGLRenderer/Utils.inl +++ b/include/Nazara/OpenGLRenderer/Utils.inl @@ -68,6 +68,22 @@ namespace Nz return {}; } + GLenum ToOpenGL(PrimitiveMode primitiveMode) + { + switch (primitiveMode) + { + case PrimitiveMode_LineList: return GL_LINES; + case PrimitiveMode_LineStrip: return GL_LINE_STRIP; + case PrimitiveMode_PointList: return GL_POINTS; + case PrimitiveMode_TriangleList: return GL_TRIANGLES; + case PrimitiveMode_TriangleStrip: return GL_TRIANGLE_STRIP; + case PrimitiveMode_TriangleFan: return GL_TRIANGLE_FAN; + } + + NazaraError("Unhandled PrimitiveMode 0x" + NumberToString(UnderlyingCast(primitiveMode), 16)); + return {}; + } + inline GLenum ToOpenGL(RendererComparison comparison) { switch (comparison) diff --git a/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp b/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp index 4c47d6a54..86f205cde 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp @@ -81,12 +81,12 @@ namespace Nz else if constexpr (std::is_same_v) { ApplyStates(*context, command.states); - context->glDrawArraysInstanced(GL_TRIANGLES, command.firstVertex, command.vertexCount, command.instanceCount); + context->glDrawArraysInstanced(ToOpenGL(command.states.pipeline->GetPipelineInfo().primitiveMode), command.firstVertex, command.vertexCount, command.instanceCount); } else if constexpr (std::is_same_v) { ApplyStates(*context, command.states); - context->glDrawElementsInstanced(GL_TRIANGLES, command.indexCount, GL_UNSIGNED_SHORT, nullptr, command.instanceCount); + context->glDrawElementsInstanced(ToOpenGL(command.states.pipeline->GetPipelineInfo().primitiveMode), command.indexCount, GL_UNSIGNED_SHORT, nullptr, command.instanceCount); } else if constexpr (std::is_same_v) { From f7442982a4a60290bedea3a3e1ad7020c10f37ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sat, 20 Feb 2021 19:10:32 +0100 Subject: [PATCH 064/278] OpenGLRenderer: Implement debug region data --- .../Nazara/OpenGLRenderer/Wrapper/CoreFunctions.hpp | 6 ++++-- src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp | 10 ++++++++-- src/Nazara/OpenGLRenderer/Wrapper/Context.cpp | 5 ++++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/include/Nazara/OpenGLRenderer/Wrapper/CoreFunctions.hpp b/include/Nazara/OpenGLRenderer/Wrapper/CoreFunctions.hpp index ab3a25631..c684b52ce 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/CoreFunctions.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper/CoreFunctions.hpp @@ -154,10 +154,12 @@ typedef void (GL_APIENTRYP PFNGLSPECIALIZESHADERARBPROC) (GLuint shader, const G cb(glVertexAttribIPointer, PFNGLVERTEXATTRIBIPOINTERPROC) \ cb(glViewport, PFNGLVIEWPORTPROC) \ \ - extCb(glObjectLabel, PFNGLOBJECTLABELPROC) \ - \ extCb(glDebugMessageCallback, PFNGLDEBUGMESSAGECALLBACKPROC) \ \ + extCb(glObjectLabel, PFNGLOBJECTLABELPROC) \ + extCb(glPopDebugGroup, PFNGLPOPDEBUGGROUPPROC) \ + extCb(glPushDebugGroup, PFNGLPUSHDEBUGGROUPPROC) \ + \ extCb(glSpecializeShaderARB, PFNGLSPECIALIZESHADERARBPROC) \ #endif diff --git a/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp b/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp index 86f205cde..b2bdb985b 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp @@ -63,9 +63,10 @@ namespace Nz { using T = std::decay_t; - if constexpr (std::is_same_v || std::is_same_v) + if constexpr (std::is_same_v) { - // TODO + if (context->glPushDebugGroup) + context->glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, command.regionName.size(), command.regionName.data()); } else if constexpr (std::is_same_v) { @@ -88,6 +89,11 @@ namespace Nz ApplyStates(*context, command.states); context->glDrawElementsInstanced(ToOpenGL(command.states.pipeline->GetPipelineInfo().primitiveMode), command.indexCount, GL_UNSIGNED_SHORT, nullptr, command.instanceCount); } + else if constexpr (std::is_same_v) + { + if (context->glPopDebugGroup) + context->glPopDebugGroup(); + } else if constexpr (std::is_same_v) { command.framebuffer->Activate(); diff --git a/src/Nazara/OpenGLRenderer/Wrapper/Context.cpp b/src/Nazara/OpenGLRenderer/Wrapper/Context.cpp index 4b50659da..90192071f 100644 --- a/src/Nazara/OpenGLRenderer/Wrapper/Context.cpp +++ b/src/Nazara/OpenGLRenderer/Wrapper/Context.cpp @@ -644,8 +644,11 @@ namespace Nz::GL void Context::HandleDebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message) const { + if (id == 0) + return; + std::stringstream ss; - ss << "OpenGL debug message (ID: 0x" << std::to_string(id) << "):\n"; + ss << "OpenGL debug message (ID: 0x" << id << "):\n"; ss << "Sent by context: " << this; ss << "\n-Source: "; switch (source) From 3ef74d6e1d7278b0fecfaaee0019b4f92d0e6734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sat, 20 Feb 2021 19:14:13 +0100 Subject: [PATCH 065/278] OpenGLRenderer: Use glTexStorage2D instead of glTexImage2D --- include/Nazara/OpenGLRenderer/Wrapper/Texture.hpp | 1 + include/Nazara/OpenGLRenderer/Wrapper/Texture.inl | 9 +++++++++ src/Nazara/OpenGLRenderer/OpenGLTexture.cpp | 3 +-- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include/Nazara/OpenGLRenderer/Wrapper/Texture.hpp b/include/Nazara/OpenGLRenderer/Wrapper/Texture.hpp index 0b04a5e4a..a8288d62e 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/Texture.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper/Texture.hpp @@ -31,6 +31,7 @@ namespace Nz::GL inline void TexImage2D(GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type); inline void TexImage2D(GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* data); + inline void TexStorage2D(GLint levels, GLint internalFormat, GLsizei width, GLsizei height); inline void TexSubImage2D(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* data); Texture& operator=(const Texture&) = delete; diff --git a/include/Nazara/OpenGLRenderer/Wrapper/Texture.inl b/include/Nazara/OpenGLRenderer/Wrapper/Texture.inl index a345ac6f4..ecf5288b2 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/Texture.inl +++ b/include/Nazara/OpenGLRenderer/Wrapper/Texture.inl @@ -58,6 +58,15 @@ namespace Nz::GL context.glTexImage2D(ToOpenGL(m_target), level, internalFormat, width, height, border, format, type, data); } + inline void Texture::TexStorage2D(GLint levels, GLint internalFormat, GLsizei width, GLsizei height) + { + m_target = TextureTarget::Target2D; + + const Context& context = EnsureDeviceContext(); + context.BindTexture(m_target, m_objectId); + context.glTexStorage2D(ToOpenGL(m_target), levels, internalFormat, width, height); + } + inline void Texture::TexSubImage2D(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* data) { const Context& context = EnsureDeviceContext(); diff --git a/src/Nazara/OpenGLRenderer/OpenGLTexture.cpp b/src/Nazara/OpenGLRenderer/OpenGLTexture.cpp index 53cb0bfbb..abd49e4a8 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLTexture.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLTexture.cpp @@ -29,8 +29,7 @@ namespace Nz break; case ImageType_2D: - for (unsigned int level = 0; level < m_params.mipmapLevel; ++level) - m_texture.TexImage2D(0, format->internalFormat, GetLevelSize(params.width, level), GetLevelSize(params.height, level), 0, format->format, format->type); + m_texture.TexStorage2D(params.mipmapLevel, format->internalFormat, params.width, params.height); break; case ImageType_2D_Array: From fb3468854f696e658c99405c6f4d03506f1db9a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sat, 20 Feb 2021 19:22:08 +0100 Subject: [PATCH 066/278] Renderer: Implement Framebuffers --- .../Nazara/OpenGLRenderer/OpenGLDevice.hpp | 3 + .../Nazara/OpenGLRenderer/OpenGLDevice.inl | 6 ++ .../OpenGLRenderer/OpenGLFboFramebuffer.hpp | 45 +++++++++ .../OpenGLRenderer/OpenGLFboFramebuffer.inl | 12 +++ .../Nazara/OpenGLRenderer/OpenGLTexture.hpp | 2 + .../Nazara/OpenGLRenderer/OpenGLTexture.inl | 17 ++++ .../OpenGLWindowFramebuffer.hpp | 2 +- .../OpenGLWindowFramebuffer.inl | 2 +- .../Nazara/OpenGLRenderer/Wrapper/Context.hpp | 1 + .../Nazara/OpenGLRenderer/Wrapper/Context.inl | 9 ++ .../OpenGLRenderer/Wrapper/CoreFunctions.hpp | 4 + .../OpenGLRenderer/Wrapper/DeviceObject.hpp | 5 +- .../OpenGLRenderer/Wrapper/DeviceObject.inl | 36 ++++---- .../OpenGLRenderer/Wrapper/Framebuffer.hpp | 42 +++++---- .../OpenGLRenderer/Wrapper/Framebuffer.inl | 50 ++++++++-- include/Nazara/Renderer/RenderDevice.hpp | 4 + include/Nazara/Renderer/RenderPass.inl | 2 +- include/Nazara/Utility/Enums.hpp | 1 + include/Nazara/VulkanRenderer/Utils.hpp | 2 + include/Nazara/VulkanRenderer/Utils.inl | 41 ++++++++- .../Nazara/VulkanRenderer/VulkanDevice.hpp | 2 + .../VulkanSingleFramebuffer.hpp | 6 +- .../VulkanSingleFramebuffer.inl | 6 -- .../OpenGLRenderer/OpenGLCommandBuffer.cpp | 13 ++- .../OpenGLCommandBufferBuilder.cpp | 2 +- src/Nazara/OpenGLRenderer/OpenGLDevice.cpp | 12 +++ .../OpenGLRenderer/OpenGLFboFramebuffer.cpp | 92 +++++++++++++++++++ .../OpenGLRenderer/OpenGLShaderBinding.cpp | 26 +----- src/Nazara/VulkanRenderer/VkRenderWindow.cpp | 6 +- src/Nazara/VulkanRenderer/VulkanDevice.cpp | 12 +++ .../VulkanRenderer/VulkanRenderPass.cpp | 4 +- .../VulkanSingleFramebuffer.cpp | 34 +++++++ 32 files changed, 401 insertions(+), 100 deletions(-) create mode 100644 include/Nazara/OpenGLRenderer/OpenGLFboFramebuffer.hpp create mode 100644 include/Nazara/OpenGLRenderer/OpenGLFboFramebuffer.inl create mode 100644 src/Nazara/OpenGLRenderer/OpenGLFboFramebuffer.cpp diff --git a/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp b/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp index 610438e10..1161e5667 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp @@ -34,6 +34,8 @@ namespace Nz std::shared_ptr InstantiateBuffer(BufferType type) override; std::shared_ptr InstantiateCommandPool(QueueType queueType) override; + std::shared_ptr InstantiateFramebuffer(unsigned int width, unsigned int height, const std::shared_ptr& renderPass, const std::vector>& attachments) override; + std::shared_ptr InstantiateRenderPass(std::vector attachments, std::vector subpassDescriptions, std::vector subpassDependencies) override; std::shared_ptr InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override; std::shared_ptr InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) override; std::shared_ptr InstantiateShaderStage(const ShaderAst& shaderAst, const ShaderWriter::States& states) override; @@ -42,6 +44,7 @@ namespace Nz std::shared_ptr InstantiateTextureSampler(const TextureSamplerInfo& params) override; inline void NotifyBufferDestruction(GLuint buffer) const; + inline void NotifyFramebufferDestruction(GLuint fbo) const; inline void NotifyProgramDestruction(GLuint program) const; inline void NotifySamplerDestruction(GLuint sampler) const; inline void NotifyTextureDestruction(GLuint texture) const; diff --git a/include/Nazara/OpenGLRenderer/OpenGLDevice.inl b/include/Nazara/OpenGLRenderer/OpenGLDevice.inl index a9c823a7e..e995edbb9 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLDevice.inl +++ b/include/Nazara/OpenGLRenderer/OpenGLDevice.inl @@ -18,6 +18,12 @@ namespace Nz context->NotifyBufferDestruction(buffer); } + inline void OpenGLDevice::NotifyFramebufferDestruction(GLuint fbo) const + { + for (const GL::Context* context : m_contexts) + context->NotifyFramebufferDestruction(fbo); + } + inline void OpenGLDevice::NotifyProgramDestruction(GLuint program) const { for (const GL::Context* context : m_contexts) diff --git a/include/Nazara/OpenGLRenderer/OpenGLFboFramebuffer.hpp b/include/Nazara/OpenGLRenderer/OpenGLFboFramebuffer.hpp new file mode 100644 index 000000000..f4c5f960c --- /dev/null +++ b/include/Nazara/OpenGLRenderer/OpenGLFboFramebuffer.hpp @@ -0,0 +1,45 @@ +// Copyright (C) 2020 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_OPENGLRENDERER_OPENGLWINDOWFRAMEBUFFER_HPP +#define NAZARA_OPENGLRENDERER_OPENGLWINDOWFRAMEBUFFER_HPP + +#include +#include +#include +#include +#include + +namespace Nz +{ + class OpenGLDevice; + class RenderPass; + class Texture; + + class NAZARA_OPENGLRENDERER_API OpenGLFboFramebuffer : public OpenGLFramebuffer + { + public: + OpenGLFboFramebuffer(OpenGLDevice& device, const std::vector>& attachments); + OpenGLFboFramebuffer(const OpenGLFboFramebuffer&) = delete; + OpenGLFboFramebuffer(OpenGLFboFramebuffer&&) noexcept = default; + ~OpenGLFboFramebuffer() = default; + + void Activate() const override; + + std::size_t GetColorBufferCount() const override; + + OpenGLFboFramebuffer& operator=(const OpenGLFboFramebuffer&) = delete; + OpenGLFboFramebuffer& operator=(OpenGLFboFramebuffer&&) = delete; + + private: + GL::Framebuffer m_framebuffer; + std::size_t m_colorAttachmentCount; + }; +} + +#include + +#endif // NAZARA_OPENGLRENDERER_OpenGLWindowFramebuffer_HPP diff --git a/include/Nazara/OpenGLRenderer/OpenGLFboFramebuffer.inl b/include/Nazara/OpenGLRenderer/OpenGLFboFramebuffer.inl new file mode 100644 index 000000000..c629eb72a --- /dev/null +++ b/include/Nazara/OpenGLRenderer/OpenGLFboFramebuffer.inl @@ -0,0 +1,12 @@ +// Copyright (C) 2020 Jérôme Leclercq +// This file is part of the "Nazara Engine - OpenGL Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ +} + +#include diff --git a/include/Nazara/OpenGLRenderer/OpenGLTexture.hpp b/include/Nazara/OpenGLRenderer/OpenGLTexture.hpp index d3d66cb12..0b97585a8 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLTexture.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLTexture.hpp @@ -34,6 +34,8 @@ namespace Nz OpenGLTexture& operator=(const OpenGLTexture&) = delete; OpenGLTexture& operator=(OpenGLTexture&&) = delete; + static inline GL::TextureTarget ToTextureTarget(ImageType imageType); + private: GL::Texture m_texture; TextureInfo m_params; diff --git a/include/Nazara/OpenGLRenderer/OpenGLTexture.inl b/include/Nazara/OpenGLRenderer/OpenGLTexture.inl index a9c2cfec4..e7d789788 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLTexture.inl +++ b/include/Nazara/OpenGLRenderer/OpenGLTexture.inl @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include namespace Nz @@ -11,6 +12,22 @@ namespace Nz { return m_texture; } + + inline GL::TextureTarget OpenGLTexture::ToTextureTarget(ImageType imageType) + { + switch (imageType) + { + case ImageType_2D: return GL::TextureTarget::Target2D; + case ImageType_2D_Array: return GL::TextureTarget::Target2D_Array; + case ImageType_3D: return GL::TextureTarget::Target3D; + case ImageType_Cubemap: return GL::TextureTarget::Cubemap; + + case ImageType_1D: + case ImageType_1D_Array: + default: + throw std::runtime_error("unsupported texture type"); + } + } } #include diff --git a/include/Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.hpp b/include/Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.hpp index e1a7cb998..e97c66ff4 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.hpp @@ -36,4 +36,4 @@ namespace Nz #include -#endif // NAZARA_OPENGLRENDERER_OpenGLWindowFramebuffer_HPP +#endif diff --git a/include/Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.inl b/include/Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.inl index 9549a0467..033d596da 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.inl +++ b/include/Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.inl @@ -2,7 +2,7 @@ // This file is part of the "Nazara Engine - OpenGL Renderer" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include namespace Nz diff --git a/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp b/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp index 4f95b5c21..db1932d1f 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp @@ -126,6 +126,7 @@ namespace Nz::GL bool Initialize(const ContextParams& params); inline void NotifyBufferDestruction(GLuint buffer) const; + inline void NotifyFramebufferDestruction(GLuint fbo) const; inline void NotifyProgramDestruction(GLuint program) const; inline void NotifySamplerDestruction(GLuint sampler) const; inline void NotifyTextureDestruction(GLuint texture) const; diff --git a/include/Nazara/OpenGLRenderer/Wrapper/Context.inl b/include/Nazara/OpenGLRenderer/Wrapper/Context.inl index 8c675cea7..f194afe99 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/Context.inl +++ b/include/Nazara/OpenGLRenderer/Wrapper/Context.inl @@ -58,6 +58,15 @@ namespace Nz::GL } } + inline void Context::NotifyFramebufferDestruction(GLuint fbo) const + { + if (m_state.boundDrawFBO == fbo) + m_state.boundDrawFBO = 0; + + if (m_state.boundReadFBO == fbo) + m_state.boundReadFBO = 0; + } + inline void Context::NotifyProgramDestruction(GLuint program) const { if (m_state.boundProgram == program) diff --git a/include/Nazara/OpenGLRenderer/Wrapper/CoreFunctions.hpp b/include/Nazara/OpenGLRenderer/Wrapper/CoreFunctions.hpp index c684b52ce..de1d45a08 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/CoreFunctions.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper/CoreFunctions.hpp @@ -36,6 +36,7 @@ typedef void (GL_APIENTRYP PFNGLSPECIALIZESHADERARBPROC) (GLuint shader, const G cb(glBufferSubData, PFNGLBUFFERSUBDATAPROC) \ cb(glClear, PFNGLCLEARPROC) \ cb(glClearBufferfi, PFNGLCLEARBUFFERFIPROC) \ + cb(glClearBufferfv, PFNGLCLEARBUFFERFVPROC) \ cb(glClearBufferuiv, PFNGLCLEARBUFFERUIVPROC) \ cb(glClearColor, PFNGLCLEARCOLORPROC) \ cb(glClearDepthf, PFNGLCLEARDEPTHFPROC) \ @@ -156,6 +157,9 @@ typedef void (GL_APIENTRYP PFNGLSPECIALIZESHADERARBPROC) (GLuint shader, const G \ extCb(glDebugMessageCallback, PFNGLDEBUGMESSAGECALLBACKPROC) \ \ + extCb(glMemoryBarrier, PFNGLMEMORYBARRIERPROC) \ + extCb(glMemoryBarrierByRegion, PFNGLMEMORYBARRIERBYREGIONPROC) \ + \ extCb(glObjectLabel, PFNGLOBJECTLABELPROC) \ extCb(glPopDebugGroup, PFNGLPOPDEBUGGROUPPROC) \ extCb(glPushDebugGroup, PFNGLPUSHDEBUGGROUPPROC) \ diff --git a/include/Nazara/OpenGLRenderer/Wrapper/DeviceObject.hpp b/include/Nazara/OpenGLRenderer/Wrapper/DeviceObject.hpp index e9a241ad4..9f7063875 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/DeviceObject.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper/DeviceObject.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -26,6 +27,8 @@ namespace Nz::GL bool Create(OpenGLDevice& device, CreateArgs... args); void Destroy(); + const Context& EnsureDeviceContext() const; + bool IsValid() const; OpenGLDevice* GetDevice() const; @@ -39,8 +42,6 @@ namespace Nz::GL static constexpr GLuint InvalidObject = 0; protected: - const Context& EnsureDeviceContext(); - MovablePtr m_device; MovableValue m_objectId; }; diff --git a/include/Nazara/OpenGLRenderer/Wrapper/DeviceObject.inl b/include/Nazara/OpenGLRenderer/Wrapper/DeviceObject.inl index 08d029c79..c92a83c61 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/DeviceObject.inl +++ b/include/Nazara/OpenGLRenderer/Wrapper/DeviceObject.inl @@ -46,6 +46,24 @@ namespace Nz::GL } } + template + const Context& DeviceObject::EnsureDeviceContext() const + { + assert(m_device); + + const Context* activeContext = Context::GetCurrentContext(); + if (!activeContext || activeContext->GetDevice() != m_device) + { + const Context& referenceContext = m_device->GetReferenceContext(); + if (!Context::SetCurrentContext(&referenceContext)) + throw std::runtime_error("failed to activate context"); + + return referenceContext; + } + + return *activeContext; + } + template bool DeviceObject::IsValid() const { @@ -72,24 +90,6 @@ namespace Nz::GL if (context.glObjectLabel) context.glObjectLabel(ObjectType, m_objectId, name.size(), name.data()); } - - template - const Context& DeviceObject::EnsureDeviceContext() - { - assert(m_device); - - const Context* activeContext = Context::GetCurrentContext(); - if (!activeContext || activeContext->GetDevice() != m_device) - { - const Context& referenceContext = m_device->GetReferenceContext(); - if (!Context::SetCurrentContext(&referenceContext)) - throw std::runtime_error("failed to activate context"); - - return referenceContext; - } - - return *activeContext; - } } #include diff --git a/include/Nazara/OpenGLRenderer/Wrapper/Framebuffer.hpp b/include/Nazara/OpenGLRenderer/Wrapper/Framebuffer.hpp index dcfe84546..4d9c27ad1 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/Framebuffer.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper/Framebuffer.hpp @@ -4,36 +4,38 @@ #pragma once -#ifndef NAZARA_OPENGLRENDERER_VKFRAMEBUFFER_HPP -#define NAZARA_OPENGLRENDERER_VKFRAMEBUFFER_HPP +#ifndef NAZARA_OPENGLRENDERER_GLFRAMEBUFFER_HPP +#define NAZARA_OPENGLRENDERER_GLFRAMEBUFFER_HPP #include #include -namespace Nz +namespace Nz::GL { - namespace Vk + class Framebuffer : public DeviceObject { - class Framebuffer : public DeviceObject - { - friend DeviceObject; + friend DeviceObject; - public: - Framebuffer() = default; - Framebuffer(const Framebuffer&) = delete; - Framebuffer(Framebuffer&&) = default; - ~Framebuffer() = default; + public: + Framebuffer() = default; + Framebuffer(const Framebuffer&) = delete; + Framebuffer(Framebuffer&&) noexcept = default; + ~Framebuffer() = default; - Framebuffer& operator=(const Framebuffer&) = delete; - Framebuffer& operator=(Framebuffer&&) = delete; + inline GLenum Check() const; - private: - static inline VkResult CreateHelper(Device& device, const VkFramebufferCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkFramebuffer* handle); - static inline void DestroyHelper(Device& device, VkFramebuffer handle, const VkAllocationCallbacks* allocator); - }; - } + inline void Renderbuffer(GLenum attachment, GLenum renderbuffer); + inline void Texture2D(GLenum attachment, GLenum textarget, GLuint texture, GLint level = 0); + + Framebuffer& operator=(const Framebuffer&) = delete; + Framebuffer& operator=(Framebuffer&&) noexcept = default; + + private: + static inline GLuint CreateHelper(OpenGLDevice& device, const Context& context); + static inline void DestroyHelper(OpenGLDevice& device, const Context& context, GLuint objectId); + }; } #include -#endif // NAZARA_OPENGLRENDERER_VKFRAMEBUFFER_HPP +#endif diff --git a/include/Nazara/OpenGLRenderer/Wrapper/Framebuffer.inl b/include/Nazara/OpenGLRenderer/Wrapper/Framebuffer.inl index 3656d27f8..54017a96a 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/Framebuffer.inl +++ b/include/Nazara/OpenGLRenderer/Wrapper/Framebuffer.inl @@ -3,21 +3,51 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include -namespace Nz +namespace Nz::GL { - namespace Vk + inline GLenum Framebuffer::Check() const { - inline VkResult Framebuffer::CreateHelper(Device& device, const VkFramebufferCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkFramebuffer* handle) - { - return device.vkCreateFramebuffer(device, createInfo, allocator, handle); - } + assert(m_objectId); - inline void Framebuffer::DestroyHelper(Device& device, VkFramebuffer handle, const VkAllocationCallbacks* allocator) - { - return device.vkDestroyFramebuffer(device, handle, allocator); - } + const Context& context = EnsureDeviceContext(); + context.BindFramebuffer(m_objectId); + return context.glCheckFramebufferStatus(GL_FRAMEBUFFER); + } + + inline void Framebuffer::Renderbuffer(GLenum attachment, GLenum renderbuffer) + { + assert(m_objectId); + + const Context& context = EnsureDeviceContext(); + context.BindFramebuffer(m_objectId); + context.glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, renderbuffer); + } + + inline void Framebuffer::Texture2D(GLenum attachment, GLenum textarget, GLuint texture, GLint level) + { + assert(m_objectId); + + const Context& context = EnsureDeviceContext(); + context.BindFramebuffer(m_objectId); + context.glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, textarget, texture, level); + } + + inline GLuint Framebuffer::CreateHelper(OpenGLDevice& /*device*/, const Context& context) + { + GLuint fbo = 0; + context.glGenFramebuffers(1U, &fbo); + + return fbo; + } + + inline void Framebuffer::DestroyHelper(OpenGLDevice& device, const Context& context, GLuint objectId) + { + context.glDeleteFramebuffers(1U, &objectId); + + device.NotifyFramebufferDestruction(objectId); } } diff --git a/include/Nazara/Renderer/RenderDevice.hpp b/include/Nazara/Renderer/RenderDevice.hpp index 5f658ef69..8030c0f55 100644 --- a/include/Nazara/Renderer/RenderDevice.hpp +++ b/include/Nazara/Renderer/RenderDevice.hpp @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include #include @@ -33,6 +35,8 @@ namespace Nz virtual std::shared_ptr InstantiateBuffer(BufferType type) = 0; virtual std::shared_ptr InstantiateCommandPool(QueueType queueType) = 0; + virtual std::shared_ptr InstantiateFramebuffer(unsigned int width, unsigned int height, const std::shared_ptr& renderPass, const std::vector>& attachments) = 0; + virtual std::shared_ptr InstantiateRenderPass(std::vector attachments, std::vector subpassDescriptions, std::vector subpassDependencies) = 0; virtual std::shared_ptr InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) = 0; virtual std::shared_ptr InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) = 0; virtual std::shared_ptr InstantiateShaderStage(const ShaderAst& shaderAst, const ShaderWriter::States& states) = 0; diff --git a/include/Nazara/Renderer/RenderPass.inl b/include/Nazara/Renderer/RenderPass.inl index a7360cd30..37345cbea 100644 --- a/include/Nazara/Renderer/RenderPass.inl +++ b/include/Nazara/Renderer/RenderPass.inl @@ -15,7 +15,7 @@ namespace Nz { } - inline auto Nz::RenderPass::GetAttachment(std::size_t attachmentIndex) const -> const Attachment& + inline auto RenderPass::GetAttachment(std::size_t attachmentIndex) const -> const Attachment& { assert(attachmentIndex < m_attachments.size()); return m_attachments[attachmentIndex]; diff --git a/include/Nazara/Utility/Enums.hpp b/include/Nazara/Utility/Enums.hpp index 4112ce48b..d2eae1681 100644 --- a/include/Nazara/Utility/Enums.hpp +++ b/include/Nazara/Utility/Enums.hpp @@ -162,6 +162,7 @@ namespace Nz PixelFormatContent_Undefined = -1, PixelFormatContent_ColorRGBA, + PixelFormatContent_Depth, PixelFormatContent_DepthStencil, PixelFormatContent_Stencil, diff --git a/include/Nazara/VulkanRenderer/Utils.hpp b/include/Nazara/VulkanRenderer/Utils.hpp index b337d3d10..88ec90b05 100644 --- a/include/Nazara/VulkanRenderer/Utils.hpp +++ b/include/Nazara/VulkanRenderer/Utils.hpp @@ -39,6 +39,8 @@ namespace Nz inline VkShaderStageFlags ToVulkan(ShaderStageTypeFlags stageType); inline VkStencilOp ToVulkan(StencilOperation stencilOp); inline VkImageLayout ToVulkan(TextureLayout textureLayout); + inline VkImageUsageFlagBits ToVulkan(TextureUsage textureLayout); + inline VkImageUsageFlags ToVulkan(TextureUsageFlags textureLayout); inline VkVertexInputRate ToVulkan(VertexInputRate inputRate); NAZARA_VULKANRENDERER_API std::string TranslateVulkanError(VkResult code); diff --git a/include/Nazara/VulkanRenderer/Utils.inl b/include/Nazara/VulkanRenderer/Utils.inl index a9a872601..336335802 100644 --- a/include/Nazara/VulkanRenderer/Utils.inl +++ b/include/Nazara/VulkanRenderer/Utils.inl @@ -196,9 +196,11 @@ namespace Nz switch (pixelFormat) { case PixelFormat::PixelFormat_BGRA8: return VK_FORMAT_B8G8R8A8_UNORM; + case PixelFormat::PixelFormat_BGRA8_SRGB: return VK_FORMAT_B8G8R8A8_SRGB; case PixelFormat::PixelFormat_Depth24Stencil8: return VK_FORMAT_D24_UNORM_S8_UINT; case PixelFormat::PixelFormat_Depth32: return VK_FORMAT_D32_SFLOAT; case PixelFormat::PixelFormat_RGBA8: return VK_FORMAT_R8G8B8A8_UNORM; + case PixelFormat::PixelFormat_RGBA8_SRGB: return VK_FORMAT_R8G8B8A8_SRGB; default: break; } @@ -336,10 +338,10 @@ namespace Nz { switch (textureLayout) { - case TextureLayout::ColorInput: return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - case TextureLayout::ColorOutput: return VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR; - case TextureLayout::DepthStencilInput: return VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL; - case TextureLayout::DepthStencilOutput: return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL; + case TextureLayout::ColorInput: return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + case TextureLayout::ColorOutput: return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + case TextureLayout::DepthStencilInput: return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; + case TextureLayout::DepthStencilOutput: return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; case TextureLayout::Present: return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; case TextureLayout::TransferSource: return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; case TextureLayout::TransferDestination: return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; @@ -350,6 +352,35 @@ namespace Nz return {}; } + VkImageUsageFlagBits ToVulkan(TextureUsage textureLayout) + { + switch (textureLayout) + { + case TextureUsage::ColorOutput: return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + case TextureUsage::DepthStencilOutput: return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + case TextureUsage::InputAttachment: return VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; + case TextureUsage::ShaderSampling: return VK_IMAGE_USAGE_SAMPLED_BIT; + case TextureUsage::TransferSource: return VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + case TextureUsage::TransferDestination: return VK_IMAGE_USAGE_TRANSFER_DST_BIT; + } + + NazaraError("Unhandled TextureUsage 0x" + NumberToString(UnderlyingCast(textureLayout), 16)); + return {}; + } + + VkImageUsageFlags ToVulkan(TextureUsageFlags textureLayout) + { + VkImageUsageFlags imageUsageBits = 0; + for (int i = 0; i <= UnderlyingCast(TextureUsage::Max); ++i) + { + TextureUsage textureUsage = static_cast(i); + if (textureLayout.Test(textureUsage)) + imageUsageBits |= ToVulkan(textureUsage); + } + + return imageUsageBits; + } + inline VkVertexInputRate ToVulkan(VertexInputRate inputRate) { switch (inputRate) @@ -359,7 +390,7 @@ namespace Nz } NazaraError("Unhandled VertexInputRate 0x" + NumberToString(UnderlyingCast(inputRate), 16)); - return VK_VERTEX_INPUT_RATE_VERTEX; + return {}; } } diff --git a/include/Nazara/VulkanRenderer/VulkanDevice.hpp b/include/Nazara/VulkanRenderer/VulkanDevice.hpp index 4d47de3bf..ae3439685 100644 --- a/include/Nazara/VulkanRenderer/VulkanDevice.hpp +++ b/include/Nazara/VulkanRenderer/VulkanDevice.hpp @@ -25,6 +25,8 @@ namespace Nz std::shared_ptr InstantiateBuffer(BufferType type) override; std::shared_ptr InstantiateCommandPool(QueueType queueType) override; + std::shared_ptr InstantiateFramebuffer(unsigned int width, unsigned int height, const std::shared_ptr& renderPass, const std::vector>& attachments) override; + std::shared_ptr InstantiateRenderPass(std::vector attachments, std::vector subpassDescriptions, std::vector subpassDependencies) override; std::shared_ptr InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override; std::shared_ptr InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) override; std::shared_ptr InstantiateShaderStage(const ShaderAst& shaderAst, const ShaderWriter::States& states) override; diff --git a/include/Nazara/VulkanRenderer/VulkanSingleFramebuffer.hpp b/include/Nazara/VulkanRenderer/VulkanSingleFramebuffer.hpp index 688bf99ba..0edc5d1e3 100644 --- a/include/Nazara/VulkanRenderer/VulkanSingleFramebuffer.hpp +++ b/include/Nazara/VulkanRenderer/VulkanSingleFramebuffer.hpp @@ -8,13 +8,17 @@ #define NAZARA_VULKANRENDERER_VULKANSINGLEFRAMEBUFFER_HPP #include +#include namespace Nz { + class RenderPass; + class Texture; + class NAZARA_VULKANRENDERER_API VulkanSingleFramebuffer final : public VulkanFramebuffer { public: - inline VulkanSingleFramebuffer(Vk::Framebuffer renderPass); + VulkanSingleFramebuffer(Vk::Device& device, unsigned int width, unsigned int height, const std::shared_ptr& renderPass, const std::vector>& attachments); VulkanSingleFramebuffer(const VulkanSingleFramebuffer&) = delete; VulkanSingleFramebuffer(VulkanSingleFramebuffer&&) = delete; ~VulkanSingleFramebuffer() = default; diff --git a/include/Nazara/VulkanRenderer/VulkanSingleFramebuffer.inl b/include/Nazara/VulkanRenderer/VulkanSingleFramebuffer.inl index 19f5e35c1..b9553b998 100644 --- a/include/Nazara/VulkanRenderer/VulkanSingleFramebuffer.inl +++ b/include/Nazara/VulkanRenderer/VulkanSingleFramebuffer.inl @@ -7,12 +7,6 @@ namespace Nz { - inline VulkanSingleFramebuffer::VulkanSingleFramebuffer(Vk::Framebuffer framebuffer) : - VulkanFramebuffer(Type::Single), - m_framebuffer(std::move(framebuffer)) - { - } - inline Vk::Framebuffer& VulkanSingleFramebuffer::GetFramebuffer() { return m_framebuffer; diff --git a/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp b/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp index b2bdb985b..6ed855aa4 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp @@ -106,18 +106,19 @@ namespace Nz for (std::size_t i = 0; i < colorBufferCount; ++i) { Nz::Color color = command.clearValues[i].color; - std::array clearColor = { color.r, color.g, color.b, color.a }; + std::array clearColor = { color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f }; - context->glClearBufferuiv(GL_COLOR, GLint(i), clearColor.data()); + context->glClearBufferfv(GL_COLOR, GLint(i), clearColor.data()); } + + context->glClear(GL_DEPTH_BUFFER_BIT); } else { Nz::Color color = command.clearValues[0].color; - context->glClearColor(color.r, color.g, color.b, color.a); + context->glClearColor(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f); + context->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } - - context->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } else static_assert(AlwaysFalse::value, "non-exhaustive visitor"); @@ -131,6 +132,8 @@ namespace Nz states.shaderBindings->Apply(context); states.pipeline->Apply(context); + states.pipeline->FlipY(states.shouldFlipY); + if (states.scissorRegion) context.SetScissorBox(states.scissorRegion->x, states.scissorRegion->y, states.scissorRegion->width, states.scissorRegion->height); diff --git a/src/Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.cpp b/src/Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.cpp index e10d0de22..1571ef677 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.cpp @@ -19,7 +19,7 @@ namespace Nz m_commandBuffer.BeginDebugRegion(regionName, color); } - void OpenGLCommandBufferBuilder::BeginRenderPass(const Framebuffer& framebuffer, const RenderPass& renderPass, Nz::Recti renderRect, std::initializer_list clearValues) + void OpenGLCommandBufferBuilder::BeginRenderPass(const Framebuffer& framebuffer, const RenderPass& renderPass, Nz::Recti /*renderRect*/, std::initializer_list clearValues) { m_commandBuffer.SetFramebuffer(static_cast(framebuffer), renderPass, clearValues); } diff --git a/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp b/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp index 5d2ffa399..205099232 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include #include #include @@ -58,6 +60,16 @@ namespace Nz return std::make_shared(); } + std::shared_ptr OpenGLDevice::InstantiateFramebuffer(unsigned int /*width*/, unsigned int /*height*/, const std::shared_ptr& /*renderPass*/, const std::vector>& attachments) + { + return std::make_shared(*this, attachments); + } + + std::shared_ptr OpenGLDevice::InstantiateRenderPass(std::vector attachments, std::vector subpassDescriptions, std::vector subpassDependencies) + { + return std::make_shared(std::move(attachments), std::move(subpassDescriptions), std::move(subpassDependencies)); + } + std::shared_ptr OpenGLDevice::InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) { return std::make_shared(*this, std::move(pipelineInfo)); diff --git a/src/Nazara/OpenGLRenderer/OpenGLFboFramebuffer.cpp b/src/Nazara/OpenGLRenderer/OpenGLFboFramebuffer.cpp new file mode 100644 index 000000000..f7923472c --- /dev/null +++ b/src/Nazara/OpenGLRenderer/OpenGLFboFramebuffer.cpp @@ -0,0 +1,92 @@ +// Copyright (C) 2020 Jérôme Leclercq +// This file is part of the "Nazara Engine - OpenGL Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include + +namespace Nz +{ + OpenGLFboFramebuffer::OpenGLFboFramebuffer(OpenGLDevice& device, const std::vector>& attachments) : + OpenGLFramebuffer(OpenGLFramebuffer::Type::FBO) + { + if (!m_framebuffer.Create(device)) + throw std::runtime_error("failed to create framebuffer object"); + + std::size_t colorAttachmentCount = 0; + bool hasDepth = false; + bool hasStencil = false; + + for (std::size_t i = 0; i < attachments.size(); ++i) + { + assert(attachments[i]); + const OpenGLTexture& glTexture = static_cast(*attachments[i]); + + PixelFormat textureFormat = glTexture.GetFormat(); + + GLenum attachment; + switch (PixelFormatInfo::GetContent(textureFormat)) + { + case PixelFormatContent_ColorRGBA: + attachment = GL_COLOR_ATTACHMENT0 + colorAttachmentCount; + colorAttachmentCount++; + break; + + case PixelFormatContent_Depth: + if (hasDepth) + throw std::runtime_error("a framebuffer can only have one depth attachment"); + + attachment = GL_DEPTH_ATTACHMENT; + hasDepth = true; + break; + + case PixelFormatContent_DepthStencil: + if (hasDepth) + throw std::runtime_error("a framebuffer can only have one depth attachment"); + + if (hasStencil) + throw std::runtime_error("a framebuffer can only have one stencil attachment"); + + attachment = GL_DEPTH_STENCIL_ATTACHMENT; + hasDepth = true; + hasStencil = true; + break; + + case PixelFormatContent_Stencil: + if (hasStencil) + throw std::runtime_error("a framebuffer can only have one stencil attachment"); + + attachment = GL_STENCIL_ATTACHMENT; + hasStencil = true; + break; + + case PixelFormatContent_Undefined: + default: + throw std::runtime_error("unhandled pixel format " + PixelFormatInfo::GetName(textureFormat)); + } + + m_framebuffer.Texture2D(attachment, ToOpenGL(OpenGLTexture::ToTextureTarget(glTexture.GetType())), glTexture.GetTexture().GetObjectId()); + } + + GLenum status = m_framebuffer.Check(); + if (status != GL_FRAMEBUFFER_COMPLETE) + throw std::runtime_error("invalid framebuffer: 0x" + NumberToString(status, 16)); + + m_colorAttachmentCount = colorAttachmentCount; + } + + void OpenGLFboFramebuffer::Activate() const + { + const GL::Context& context = m_framebuffer.EnsureDeviceContext(); + + context.BindFramebuffer(GL::FramebufferTarget::Draw, m_framebuffer.GetObjectId()); + } + + std::size_t OpenGLFboFramebuffer::GetColorBufferCount() const + { + return m_colorAttachmentCount; + } +} diff --git a/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp b/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp index d8fd7fa44..5bef6dcc7 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp @@ -68,7 +68,7 @@ namespace Nz const TextureBinding& texBinding = std::get(binding.content); auto& textureDescriptor = m_owner.GetTextureDescriptor(m_poolIndex, m_bindingIndex, resourceIndex); - textureDescriptor.bindingIndex = binding.bindingIndex; + textureDescriptor.bindingIndex = UInt32(binding.bindingIndex); if (OpenGLTexture* glTexture = static_cast(texBinding.texture)) { @@ -79,29 +79,7 @@ namespace Nz else textureDescriptor.sampler = 0; - switch (glTexture->GetType()) - { - case ImageType_2D: - textureDescriptor.textureTarget = GL::TextureTarget::Target2D; - break; - - case ImageType_2D_Array: - textureDescriptor.textureTarget = GL::TextureTarget::Target2D_Array; - break; - - case ImageType_3D: - textureDescriptor.textureTarget = GL::TextureTarget::Target3D; - break; - - case ImageType_Cubemap: - textureDescriptor.textureTarget = GL::TextureTarget::Cubemap; - break; - - case ImageType_1D: - case ImageType_1D_Array: - default: - throw std::runtime_error("unsupported texture type"); - } + textureDescriptor.textureTarget = OpenGLTexture::ToTextureTarget(glTexture->GetType()); } else { diff --git a/src/Nazara/VulkanRenderer/VkRenderWindow.cpp b/src/Nazara/VulkanRenderer/VkRenderWindow.cpp index 9091e04c2..4dd7e927d 100644 --- a/src/Nazara/VulkanRenderer/VkRenderWindow.cpp +++ b/src/Nazara/VulkanRenderer/VkRenderWindow.cpp @@ -419,7 +419,7 @@ namespace Nz RenderPass::AttachmentReference colorReference = { 0, - TextureLayout::ColorInput + TextureLayout::ColorOutput }; std::vector subpasses = { @@ -475,12 +475,12 @@ namespace Nz AttachmentStoreOp::Discard, AttachmentStoreOp::Discard, TextureLayout::Undefined, - TextureLayout::DepthStencilInput + TextureLayout::DepthStencilOutput }); subpasses.front().depthStencilAttachment = RenderPass::AttachmentReference{ 1, - TextureLayout::DepthStencilInput + TextureLayout::DepthStencilOutput }; } diff --git a/src/Nazara/VulkanRenderer/VulkanDevice.cpp b/src/Nazara/VulkanRenderer/VulkanDevice.cpp index 5f6ed9e3d..0de3132a5 100644 --- a/src/Nazara/VulkanRenderer/VulkanDevice.cpp +++ b/src/Nazara/VulkanRenderer/VulkanDevice.cpp @@ -4,9 +4,11 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -25,6 +27,16 @@ namespace Nz return std::make_shared(*this, queueType); } + std::shared_ptr VulkanDevice::InstantiateFramebuffer(unsigned int width, unsigned int height, const std::shared_ptr& renderPass, const std::vector>& attachments) + { + return std::make_shared(*this, width, height, renderPass, attachments); + } + + std::shared_ptr VulkanDevice::InstantiateRenderPass(std::vector attachments, std::vector subpassDescriptions, std::vector subpassDependencies) + { + return std::make_shared(*this, std::move(attachments), std::move(subpassDescriptions), std::move(subpassDependencies)); + } + std::shared_ptr VulkanDevice::InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) { return std::make_shared(*this, std::move(pipelineInfo)); diff --git a/src/Nazara/VulkanRenderer/VulkanRenderPass.cpp b/src/Nazara/VulkanRenderer/VulkanRenderPass.cpp index 2d497d6ab..e44b38edd 100644 --- a/src/Nazara/VulkanRenderer/VulkanRenderPass.cpp +++ b/src/Nazara/VulkanRenderer/VulkanRenderPass.cpp @@ -76,9 +76,9 @@ namespace Nz VkSubpassDescriptionFlags(0), VK_PIPELINE_BIND_POINT_GRAPHICS, UInt32(subpassInfo.inputAttachments.size()), - &vkAttachmentReferences[inputAttachmentIndex], + (!subpassInfo.inputAttachments.empty()) ? &vkAttachmentReferences[inputAttachmentIndex] : nullptr, UInt32(subpassInfo.colorAttachment.size()), - &vkAttachmentReferences[colorAttachmentIndex], + (!subpassInfo.colorAttachment.empty()) ? &vkAttachmentReferences[colorAttachmentIndex] : nullptr, nullptr, (subpassInfo.depthStencilAttachment) ? &vkAttachmentReferences[depthStencilAttachmentIndex] : nullptr, 0, diff --git a/src/Nazara/VulkanRenderer/VulkanSingleFramebuffer.cpp b/src/Nazara/VulkanRenderer/VulkanSingleFramebuffer.cpp index a8ecb74ad..e445e2a5f 100644 --- a/src/Nazara/VulkanRenderer/VulkanSingleFramebuffer.cpp +++ b/src/Nazara/VulkanRenderer/VulkanSingleFramebuffer.cpp @@ -3,8 +3,42 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include +#include +#include +#include #include namespace Nz { + VulkanSingleFramebuffer::VulkanSingleFramebuffer(Vk::Device& device, unsigned int width, unsigned int height, const std::shared_ptr& renderPass, const std::vector>& attachments) : + VulkanFramebuffer(Type::Single) + { + assert(renderPass); + const VulkanRenderPass& vkRenderPass = static_cast(*renderPass); + + StackArray imageViews = NazaraStackArrayNoInit(VkImageView, attachments.size()); + for (std::size_t i = 0; i < attachments.size(); ++i) + { + assert(attachments[i]); + + const VulkanTexture& vkTexture = static_cast(*attachments[i]); + imageViews[i] = vkTexture.GetImageView(); + } + + VkFramebufferCreateInfo createInfo = { + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, + nullptr, + 0, + vkRenderPass.GetRenderPass(), + UInt32(imageViews.size()), + imageViews.data(), + UInt32(width), + UInt32(height), + 1 + }; + + if (!m_framebuffer.Create(device, createInfo)) + throw std::runtime_error("failed to instantiate Vulkan framebuffer: " + TranslateVulkanError(m_framebuffer.GetLastErrorCode())); + } } From 311cfeaf3cdcce98d34ddcd05b1e50a776f1a3b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sat, 20 Feb 2021 19:23:29 +0100 Subject: [PATCH 067/278] OpenGLRenderer: Fix Y flipping for FBOs --- .../OpenGLRenderer/OpenGLCommandBuffer.hpp | 1 + .../OpenGLRenderer/OpenGLCommandBuffer.inl | 2 ++ .../OpenGLRenderer/OpenGLRenderPipeline.hpp | 4 +++ .../Nazara/OpenGLRenderer/Wrapper/Program.hpp | 6 +++- .../Nazara/OpenGLRenderer/Wrapper/Program.inl | 24 ++++++++++++- include/Nazara/Shader/GlslWriter.hpp | 2 ++ .../OpenGLRenderer/OpenGLRenderPipeline.cpp | 17 ++++++++- src/Nazara/Shader/GlslWriter.cpp | 36 +++++++++++++++---- 8 files changed, 83 insertions(+), 9 deletions(-) diff --git a/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp b/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp index 40a6f645e..82148f580 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp @@ -106,6 +106,7 @@ namespace Nz std::optional scissorRegion; std::optional viewportRegion; std::vector vertexBuffers; + bool shouldFlipY = false; }; struct DrawData diff --git a/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.inl b/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.inl index 1dd4b4d30..0b281eaa4 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.inl +++ b/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.inl @@ -142,6 +142,8 @@ namespace Nz std::copy(clearValues.begin(), clearValues.end(), setFramebuffer.clearValues.begin()); m_commands.emplace_back(std::move(setFramebuffer)); + + m_currentStates.shouldFlipY = (framebuffer.GetType() == OpenGLFramebuffer::Type::Window); } inline void OpenGLCommandBuffer::SetScissor(Nz::Recti scissorRegion) diff --git a/include/Nazara/OpenGLRenderer/OpenGLRenderPipeline.hpp b/include/Nazara/OpenGLRenderer/OpenGLRenderPipeline.hpp index 3c40eca7a..6745b8c5f 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLRenderPipeline.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLRenderPipeline.hpp @@ -24,11 +24,15 @@ namespace Nz void Apply(const GL::Context& context) const; + void FlipY(bool shouldFlipY) const; + inline const RenderPipelineInfo& GetPipelineInfo() const override; private: RenderPipelineInfo m_pipelineInfo; GL::Program m_program; + GLint m_flipYUniformLocation; + mutable bool m_isYFlipped; }; } diff --git a/include/Nazara/OpenGLRenderer/Wrapper/Program.hpp b/include/Nazara/OpenGLRenderer/Wrapper/Program.hpp index 6acc1eb7b..a4c4181ac 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/Program.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper/Program.hpp @@ -26,10 +26,14 @@ namespace Nz::GL inline void AttachShader(GLuint shader); - inline bool GetLinkStatus(std::string* error = nullptr); + inline bool GetLinkStatus(std::string* error = nullptr) const; + inline GLint GetUniformLocation(const char* uniformName) const; + inline GLint GetUniformLocation(const std::string& uniformName) const; inline void Link(); + inline void Uniform(GLint uniformLocation, float value) const; + Program& operator=(const Program&) = delete; Program& operator=(Program&&) noexcept = default; diff --git a/include/Nazara/OpenGLRenderer/Wrapper/Program.inl b/include/Nazara/OpenGLRenderer/Wrapper/Program.inl index ca8795d70..fd5e6030b 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/Program.inl +++ b/include/Nazara/OpenGLRenderer/Wrapper/Program.inl @@ -16,7 +16,7 @@ namespace Nz::GL context.glAttachShader(m_objectId, shader); } - inline bool Program::GetLinkStatus(std::string* error) + inline bool Program::GetLinkStatus(std::string* error) const { assert(m_objectId); const Context& context = EnsureDeviceContext(); @@ -45,6 +45,19 @@ namespace Nz::GL return true; } + inline GLint Program::GetUniformLocation(const char* uniformName) const + { + assert(m_objectId); + const Context& context = EnsureDeviceContext(); + + return context.glGetUniformLocation(m_objectId, uniformName); + } + + inline GLint Program::GetUniformLocation(const std::string& uniformName) const + { + return GetUniformLocation(uniformName.c_str()); + } + inline void Program::Link() { assert(m_objectId); @@ -53,6 +66,15 @@ namespace Nz::GL context.glLinkProgram(m_objectId); } + inline void Program::Uniform(GLint uniformLocation, float value) const + { + assert(m_objectId); + + const Context& context = EnsureDeviceContext(); + context.BindProgram(m_objectId); + context.glUniform1f(uniformLocation, value); + } + inline GLuint Program::CreateHelper(OpenGLDevice& /*device*/, const Context& context) { return context.glCreateProgram(); diff --git a/include/Nazara/Shader/GlslWriter.hpp b/include/Nazara/Shader/GlslWriter.hpp index 2584389a2..a74871da4 100644 --- a/include/Nazara/Shader/GlslWriter.hpp +++ b/include/Nazara/Shader/GlslWriter.hpp @@ -43,6 +43,8 @@ namespace Nz bool flipYPosition = false; }; + static const char* GetFlipYUniformName(); + private: void Append(ShaderExpressionType type); void Append(ShaderNodes::BuiltinEntry builtin); diff --git a/src/Nazara/OpenGLRenderer/OpenGLRenderPipeline.cpp b/src/Nazara/OpenGLRenderer/OpenGLRenderPipeline.cpp index d3378c941..e1511a847 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLRenderPipeline.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLRenderPipeline.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -14,7 +15,8 @@ namespace Nz { OpenGLRenderPipeline::OpenGLRenderPipeline(OpenGLDevice& device, RenderPipelineInfo pipelineInfo) : - m_pipelineInfo(std::move(pipelineInfo)) + m_pipelineInfo(std::move(pipelineInfo)), + m_isYFlipped(false) { if (!m_program.Create(device)) throw std::runtime_error("failed to create program"); @@ -30,6 +32,10 @@ namespace Nz std::string errLog; if (!m_program.GetLinkStatus(&errLog)) throw std::runtime_error("failed to link program: " + errLog); + + m_flipYUniformLocation = m_program.GetUniformLocation(GlslWriter::GetFlipYUniformName()); + if (m_flipYUniformLocation != -1) + m_program.Uniform(m_flipYUniformLocation, 1.f); } void OpenGLRenderPipeline::Apply(const GL::Context& context) const @@ -37,4 +43,13 @@ namespace Nz context.UpdateStates(m_pipelineInfo); context.BindProgram(m_program.GetObjectId()); //< Bind program after states } + + void OpenGLRenderPipeline::FlipY(bool shouldFlipY) const + { + if (m_isYFlipped != shouldFlipY) + { + m_program.Uniform(m_flipYUniformLocation, (shouldFlipY) ? -1.f : 1.f); + m_isYFlipped = shouldFlipY; + } + } } diff --git a/src/Nazara/Shader/GlslWriter.cpp b/src/Nazara/Shader/GlslWriter.cpp index e1f32d414..f78896a3c 100644 --- a/src/Nazara/Shader/GlslWriter.cpp +++ b/src/Nazara/Shader/GlslWriter.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -17,6 +18,8 @@ namespace Nz { namespace { + static const char* flipYUniformName = "_NzFlipValue"; + struct AstAdapter : ShaderAstCloner { void Visit(ShaderNodes::AssignOp& node) override @@ -35,8 +38,11 @@ namespace Nz if (builtinVar.entry != ShaderNodes::BuiltinEntry::VertexPosition) return ShaderAstCloner::Visit(node); - auto fixYConstant = ShaderBuilder::Constant(Nz::Vector4f(1.f, -1.f, 1.f, 1.f)); - auto mulFix = ShaderBuilder::Multiply(CloneExpression(node.right), fixYConstant); + auto flipVar = ShaderBuilder::Uniform(flipYUniformName, ShaderNodes::BasicType::Float1); + + auto oneConstant = ShaderBuilder::Constant(1.f); + auto fixYValue = ShaderBuilder::Cast(oneConstant, ShaderBuilder::Identifier(flipVar), oneConstant, oneConstant); + auto mulFix = ShaderBuilder::Multiply(CloneExpression(node.right), fixYValue); PushExpression(ShaderNodes::AssignOp::Build(node.op, CloneExpression(node.left), mulFix)); } @@ -50,8 +56,21 @@ namespace Nz { } - std::string GlslWriter::Generate(const ShaderAst& shader, const States& conditions) + std::string GlslWriter::Generate(const ShaderAst& inputShader, const States& conditions) { + const ShaderAst* selectedShader = &inputShader; + std::optional modifiedShader; + if (inputShader.GetStage() == ShaderStageType::Vertex && m_environment.flipYPosition) + { + modifiedShader.emplace(inputShader); + + modifiedShader->AddUniform(flipYUniformName, ShaderNodes::BasicType::Float1); + + selectedShader = &modifiedShader.value(); + } + + const ShaderAst& shader = *selectedShader; + std::string error; if (!ValidateShader(shader, &error)) throw std::runtime_error("Invalid shader AST: " + error); @@ -172,9 +191,9 @@ namespace Nz const char* inKeyword = (glslVersion >= 130) ? "in" : "varying"; const char* outKeyword = (glslVersion >= 130) ? "out" : "varying"; - DeclareVariables(shader, shader.GetUniforms(), "uniform", "Uniforms"); - DeclareVariables(shader, shader.GetInputs(), inKeyword, "Inputs"); - DeclareVariables(shader, shader.GetOutputs(), outKeyword, "Outputs"); + DeclareVariables(shader, shader.GetUniforms(), "uniform", "Uniforms"); + DeclareVariables(shader, shader.GetInputs(), inKeyword, "Inputs"); + DeclareVariables(shader, shader.GetOutputs(), outKeyword, "Outputs"); std::size_t functionCount = shader.GetFunctionCount(); if (functionCount > 1) @@ -201,6 +220,11 @@ namespace Nz m_environment = std::move(environment); } + const char* GlslWriter::GetFlipYUniformName() + { + return flipYUniformName; + } + void GlslWriter::Append(ShaderExpressionType type) { std::visit([&](auto&& arg) From b291f8a21c728b3c7dd6b03ad87829f41052a4fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sat, 20 Feb 2021 19:25:25 +0100 Subject: [PATCH 068/278] Renderer: Implement TextureUsage --- include/Nazara/Renderer/Enums.hpp | 20 ++++++++++++++++++++ include/Nazara/Renderer/Texture.hpp | 2 ++ src/Nazara/VulkanRenderer/VulkanTexture.cpp | 2 +- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/include/Nazara/Renderer/Enums.hpp b/include/Nazara/Renderer/Enums.hpp index 2e3f95286..7204ff60d 100644 --- a/include/Nazara/Renderer/Enums.hpp +++ b/include/Nazara/Renderer/Enums.hpp @@ -154,6 +154,26 @@ namespace Nz TransferDestination, Undefined }; + + enum class TextureUsage + { + ColorOutput, + DepthStencilOutput, + InputAttachment, + ShaderSampling, + TransferSource, + TransferDestination, + + Max = TransferDestination + }; + + template<> + struct EnumAsFlags + { + static constexpr TextureUsage max = TextureUsage::Max; + }; + + using TextureUsageFlags = Flags; } #endif // NAZARA_ENUMS_RENDERER_HPP diff --git a/include/Nazara/Renderer/Texture.hpp b/include/Nazara/Renderer/Texture.hpp index 8f185fe21..450144d7b 100644 --- a/include/Nazara/Renderer/Texture.hpp +++ b/include/Nazara/Renderer/Texture.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include namespace Nz @@ -19,6 +20,7 @@ namespace Nz { PixelFormat pixelFormat; ImageType type; + TextureUsageFlags usageFlags = TextureUsage::ShaderSampling | TextureUsage::TransferDestination; UInt8 mipmapLevel = 1; unsigned int depth = 1; unsigned int height; diff --git a/src/Nazara/VulkanRenderer/VulkanTexture.cpp b/src/Nazara/VulkanRenderer/VulkanTexture.cpp index 377370946..275f78e92 100644 --- a/src/Nazara/VulkanRenderer/VulkanTexture.cpp +++ b/src/Nazara/VulkanRenderer/VulkanTexture.cpp @@ -24,7 +24,7 @@ namespace Nz createInfo.mipLevels = params.mipmapLevel; createInfo.samples = VK_SAMPLE_COUNT_1_BIT; createInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - createInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + createInfo.usage = ToVulkan(params.usageFlags); VkImageViewCreateInfo createInfoView = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; createInfoView.subresourceRange = { From 57adfa09de6402b352de8dd0845bacd3cc310203 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sat, 20 Feb 2021 19:25:38 +0100 Subject: [PATCH 069/278] VulkanRenderer: Fix Depth24Stencil8 format --- src/Nazara/VulkanRenderer/VulkanTexture.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Nazara/VulkanRenderer/VulkanTexture.cpp b/src/Nazara/VulkanRenderer/VulkanTexture.cpp index 275f78e92..13a2fc0bc 100644 --- a/src/Nazara/VulkanRenderer/VulkanTexture.cpp +++ b/src/Nazara/VulkanRenderer/VulkanTexture.cpp @@ -244,9 +244,11 @@ namespace Nz break; } + case PixelFormat_Depth24Stencil8: { - createImage.format = VK_FORMAT_B8G8R8A8_SRGB; + createImage.format = VK_FORMAT_D24_UNORM_S8_UINT; createImageView.format = createImage.format; + createImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; break; } From d59423afcaaf925b0887629f8d766791eeb3898e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 24 Feb 2021 23:50:12 +0100 Subject: [PATCH 070/278] Renderer: Rename some TextureUsage --- include/Nazara/Renderer/Enums.hpp | 4 ++-- include/Nazara/VulkanRenderer/Utils.inl | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/Nazara/Renderer/Enums.hpp b/include/Nazara/Renderer/Enums.hpp index 7204ff60d..3f9de6791 100644 --- a/include/Nazara/Renderer/Enums.hpp +++ b/include/Nazara/Renderer/Enums.hpp @@ -157,8 +157,8 @@ namespace Nz enum class TextureUsage { - ColorOutput, - DepthStencilOutput, + ColorAttachment, + DepthStencilAttachment, InputAttachment, ShaderSampling, TransferSource, diff --git a/include/Nazara/VulkanRenderer/Utils.inl b/include/Nazara/VulkanRenderer/Utils.inl index 336335802..d017ab1a3 100644 --- a/include/Nazara/VulkanRenderer/Utils.inl +++ b/include/Nazara/VulkanRenderer/Utils.inl @@ -356,12 +356,12 @@ namespace Nz { switch (textureLayout) { - case TextureUsage::ColorOutput: return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - case TextureUsage::DepthStencilOutput: return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - case TextureUsage::InputAttachment: return VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; - case TextureUsage::ShaderSampling: return VK_IMAGE_USAGE_SAMPLED_BIT; - case TextureUsage::TransferSource: return VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - case TextureUsage::TransferDestination: return VK_IMAGE_USAGE_TRANSFER_DST_BIT; + case TextureUsage::ColorAttachment: return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + case TextureUsage::DepthStencilAttachment: return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + case TextureUsage::InputAttachment: return VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; + case TextureUsage::ShaderSampling: return VK_IMAGE_USAGE_SAMPLED_BIT; + case TextureUsage::TransferSource: return VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + case TextureUsage::TransferDestination: return VK_IMAGE_USAGE_TRANSFER_DST_BIT; } NazaraError("Unhandled TextureUsage 0x" + NumberToString(UnderlyingCast(textureLayout), 16)); From 48ab2a4b04d1a46841e4c268974ba6357727ba3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 19 Mar 2021 09:55:36 +0100 Subject: [PATCH 071/278] ObjectHandle: Fix handling of --- include/Nazara/Core/HandledObject.hpp | 6 ++- include/Nazara/Core/HandledObject.inl | 24 +++++---- include/Nazara/Core/ObjectHandle.hpp | 7 +++ include/Nazara/Core/ObjectHandle.inl | 77 ++++++++++++++++++++++++++- 4 files changed, 99 insertions(+), 15 deletions(-) diff --git a/include/Nazara/Core/HandledObject.hpp b/include/Nazara/Core/HandledObject.hpp index 390a4e612..c2bd59d0c 100644 --- a/include/Nazara/Core/HandledObject.hpp +++ b/include/Nazara/Core/HandledObject.hpp @@ -37,7 +37,10 @@ namespace Nz HandledObject(HandledObject&& object) noexcept; ~HandledObject(); - ObjectHandle CreateHandle(); + template + ObjectHandle CreateHandle(); + + std::shared_ptr GetHandleData(); HandledObject& operator=(const HandledObject& object); HandledObject& operator=(HandledObject&& object) noexcept; @@ -48,7 +51,6 @@ namespace Nz void UnregisterAllHandles() noexcept; private: - std::shared_ptr GetHandleData(); void InitHandleData(); std::shared_ptr m_handleData; diff --git a/include/Nazara/Core/HandledObject.inl b/include/Nazara/Core/HandledObject.inl index ed0115f5b..8f1e497a0 100644 --- a/include/Nazara/Core/HandledObject.inl +++ b/include/Nazara/Core/HandledObject.inl @@ -58,9 +58,20 @@ namespace Nz * \return ObjectHandle to this */ template - ObjectHandle HandledObject::CreateHandle() + template + ObjectHandle HandledObject::CreateHandle() { - return ObjectHandle(static_cast(this)); + static_assert(std::is_base_of_v, "Cannot retrieve a handle for a non-related class"); + return ObjectHandle(static_cast(this)); + } + + template + std::shared_ptr HandledObject::GetHandleData() + { + if (!m_handleData) + InitHandleData(); + + return std::shared_ptr(m_handleData); } /*! @@ -112,15 +123,6 @@ namespace Nz } } - template - std::shared_ptr HandledObject::GetHandleData() - { - if (!m_handleData) - InitHandleData(); - - return std::shared_ptr(m_handleData); - } - template void HandledObject::InitHandleData() { diff --git a/include/Nazara/Core/ObjectHandle.hpp b/include/Nazara/Core/ObjectHandle.hpp index e2e72f185..6d62dc582 100644 --- a/include/Nazara/Core/ObjectHandle.hpp +++ b/include/Nazara/Core/ObjectHandle.hpp @@ -22,6 +22,8 @@ namespace Nz public: ObjectHandle(); explicit ObjectHandle(T* object); + template ObjectHandle(const ObjectHandle& ref); + template ObjectHandle(ObjectHandle&& ref); ObjectHandle(const ObjectHandle& handle) = default; ObjectHandle(ObjectHandle&& handle) noexcept; ~ObjectHandle(); @@ -78,6 +80,11 @@ namespace Nz template bool operator>=(const T& lhs, const ObjectHandle& rhs); template bool operator>=(const ObjectHandle& lhs, const T& rhs); + template ObjectHandle ConstRefCast(const ObjectHandle& ref); + template ObjectHandle DynamicRefCast(const ObjectHandle& ref); + template ObjectHandle ReinterpretRefCast(const ObjectHandle& ref); + template ObjectHandle StaticRefCast(const ObjectHandle& ref); + template struct PointedType> { using type = T; }; template struct PointedType> { using type = T; }; } diff --git a/include/Nazara/Core/ObjectHandle.inl b/include/Nazara/Core/ObjectHandle.inl index fc43fdffe..1a3d09b9b 100644 --- a/include/Nazara/Core/ObjectHandle.inl +++ b/include/Nazara/Core/ObjectHandle.inl @@ -26,15 +26,34 @@ namespace Nz { } + template + template + ObjectHandle::ObjectHandle(const ObjectHandle& ref) : + m_handleData(ref.m_handleData) + { + static_assert(std::is_base_of_v, "Can only implicitly convert from a derived to a base"); + } + + template + template + ObjectHandle::ObjectHandle(ObjectHandle&& ref) : + m_handleData(std::move(ref.m_handleData)) + { + ref.m_handleData = Detail::HandleData::GetEmptyObject(); + + static_assert(std::is_base_of_v, "Can only implicitly convert from a derived to a base"); + } + /*! * \brief Constructs a ObjectHandle object by move semantic * * \param handle ObjectHandle to move into this */ template - ObjectHandle::ObjectHandle(ObjectHandle&& handle) noexcept + ObjectHandle::ObjectHandle(ObjectHandle&& handle) noexcept : + m_handleData(std::move(handle.m_handleData)) { - Reset(std::move(handle)); + handle.m_handleData = Detail::HandleData::GetEmptyObject(); } /*! @@ -457,6 +476,60 @@ namespace Nz return !(lhs < rhs); } + /*! + * \brief Casts an ObjectHandle from one type to another using static_cast + * \return Reference to the casted object + * + * \param ref The reference to convert + * + * \remark It is an undefined behavior to cast between incompatible types + */ + template + ObjectHandle ConstRefCast(const ObjectHandle& ref) + { + return ObjectHandle(const_cast(ref.GetObject())); + } + + /*! + * \brief Casts an ObjectHandle from one type to another using static_cast + * \return Reference to the casted object + * + * \param ref The reference to convert + */ + template + ObjectHandle DynamicRefCast(const ObjectHandle& ref) + { + return ObjectHandle(dynamic_cast(ref.GetObject())); + } + + /*! + * \brief Casts an ObjectHandle from one type to another using static_cast + * \return Reference to the casted object + * + * \param ref The reference to convert + * + * \remark It is an undefined behavior to cast between incompatible types + */ + template + ObjectHandle ReinterpretRefCast(const ObjectHandle& ref) + { + return ObjectHandle(static_cast(ref.GetObject())); + } + + /*! + * \brief Casts an ObjectHandle from one type to another using static_cast + * \return Reference to the casted object + * + * \param ref The reference to convert + * + * \remark It is an undefined behavior to cast between incompatible types + */ + template + ObjectHandle StaticRefCast(const ObjectHandle& ref) + { + return ObjectHandle(static_cast(ref.GetObject())); + } + template const ObjectHandle ObjectHandle::InvalidHandle; } From 02805aade3e03b1e7216423a993811a3288ee192 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Tue, 30 Mar 2021 10:12:55 +0200 Subject: [PATCH 072/278] Update BaseWidget.cpp --- SDK/src/NDK/BaseWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SDK/src/NDK/BaseWidget.cpp b/SDK/src/NDK/BaseWidget.cpp index ecfddf33c..6cee67002 100644 --- a/SDK/src/NDK/BaseWidget.cpp +++ b/SDK/src/NDK/BaseWidget.cpp @@ -183,7 +183,7 @@ namespace Ndk { if (entity.isEnabled) { - entity.handle->Enable(show); //< This will override isEnabled + entity.handle->Enable(show); //< This will override isEnabled, so reset it next line entity.isEnabled = true; } } From 560061b4a506e4f8c98f6a1de230caad049a5df4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Tue, 30 Mar 2021 10:24:36 +0200 Subject: [PATCH 073/278] Sdk/EntityList: Fix crash when world was moved --- SDK/include/NDK/EntityList.hpp | 12 +-- SDK/include/NDK/EntityList.inl | 109 ++----------------------- SDK/include/NDK/World.hpp | 4 + SDK/include/NDK/World.inl | 25 +++++- SDK/src/NDK/EntityList.cpp | 143 +++++++++++++++++++++++++++++++++ SDK/src/NDK/World.cpp | 5 ++ 6 files changed, 188 insertions(+), 110 deletions(-) diff --git a/SDK/include/NDK/EntityList.hpp b/SDK/include/NDK/EntityList.hpp index 3b4f1580a..7602b6b21 100644 --- a/SDK/include/NDK/EntityList.hpp +++ b/SDK/include/NDK/EntityList.hpp @@ -16,6 +16,7 @@ namespace Ndk class NDK_API EntityList { friend Entity; + friend World; public: class iterator; @@ -23,16 +24,16 @@ namespace Ndk using size_type = std::size_t; inline EntityList(); - inline EntityList(const EntityList& entityList); - inline EntityList(EntityList&& entityList) noexcept; - inline ~EntityList(); + EntityList(const EntityList& entityList); + EntityList(EntityList&& entityList) noexcept; + ~EntityList(); - inline void Clear(); + void Clear(); inline bool Has(const Entity* entity) const; inline bool Has(EntityId entity) const; - inline void Insert(Entity* entity); + void Insert(Entity* entity); inline void Remove(Entity* entity); inline void Reserve(std::size_t entityCount); @@ -50,6 +51,7 @@ namespace Ndk inline std::size_t FindNext(std::size_t currentId) const; inline World* GetWorld() const; inline void NotifyEntityDestruction(const Entity* entity); + inline void SetWorld(World* world); Nz::Bitset m_entityBits; World* m_world; diff --git a/SDK/include/NDK/EntityList.inl b/SDK/include/NDK/EntityList.inl index a34165a68..27dfbb48d 100644 --- a/SDK/include/NDK/EntityList.inl +++ b/SDK/include/NDK/EntityList.inl @@ -2,6 +2,7 @@ // This file is part of the "Nazara Development Kit" // For conditions of distribution and use, see copyright notice in Prerequisites.hpp +#include #include #include @@ -21,52 +22,6 @@ namespace Ndk { } - /*! - * \brief Construct a new entity list by copying another one - */ - inline EntityList::EntityList(const EntityList& entityList) : - m_entityBits(entityList.m_entityBits), - m_world(entityList.m_world) - { - for (const Ndk::EntityHandle& entity : *this) - entity->RegisterEntityList(this); - } - - /*! - * \brief Construct a new entity list by moving a list into this one - */ - inline EntityList::EntityList(EntityList&& entityList) noexcept : - m_entityBits(std::move(entityList.m_entityBits)), - m_world(entityList.m_world) - { - for (const Ndk::EntityHandle& entity : *this) - { - entity->UnregisterEntityList(&entityList); - entity->RegisterEntityList(this); - } - } - - inline EntityList::~EntityList() - { - for (const Ndk::EntityHandle& entity : *this) - entity->UnregisterEntityList(this); - } - - - /*! - * \brief Clears the set from every entities - * - * \remark This resets the implicit world member, allowing you to insert entities from a different world than previously - */ - inline void EntityList::Clear() - { - for (const Ndk::EntityHandle& entity : *this) - entity->UnregisterEntityList(this); - - m_entityBits.Clear(); - m_world = nullptr; - } - /*! * \brief Checks whether or not the EntityList contains the entity * \return true If it is the case @@ -93,29 +48,6 @@ namespace Ndk return m_entityBits.UnboundedTest(entity); } - /*! - * \brief Inserts the entity into the set - * - * Marks an entity as present in this entity list, it must belongs to the same world as others entities contained in this list. - * - * \param entity Valid pointer to an entity - * - * \remark If entity is already contained, no action is performed - * \remark If any entity has been inserted since construction (or last Clear call), the entity must belong to the same world as the previously inserted entities - */ - inline void EntityList::Insert(Entity* entity) - { - NazaraAssert(entity, "Invalid entity"); - - if (!Has(entity)) - { - entity->RegisterEntityList(this); - - m_entityBits.UnboundedSet(entity->GetId(), true); - m_world = entity->GetWorld(); - } - } - /*! * \brief Removes the entity from the set * @@ -167,40 +99,6 @@ namespace Ndk return m_entityBits.Count(); } - inline EntityList& EntityList::operator=(const EntityList& entityList) - { - for (const Ndk::EntityHandle& entity : *this) - entity->UnregisterEntityList(this); - - m_entityBits = entityList.m_entityBits; - m_world = entityList.m_world; - - for (const Ndk::EntityHandle& entity : *this) - entity->RegisterEntityList(this); - - return *this; - } - - inline EntityList& EntityList::operator=(EntityList&& entityList) noexcept - { - if (this == &entityList) - return *this; - - for (const Ndk::EntityHandle& entity : *this) - entity->UnregisterEntityList(this); - - m_entityBits = std::move(entityList.m_entityBits); - m_world = entityList.m_world; - - for (const Ndk::EntityHandle& entity : *this) - { - entity->UnregisterEntityList(&entityList); - entity->RegisterEntityList(this); - } - - return *this; - } - inline std::size_t EntityList::FindNext(std::size_t currentId) const { return m_entityBits.FindNext(currentId); @@ -218,6 +116,11 @@ namespace Ndk m_entityBits.Reset(entity->GetId()); } + inline void EntityList::SetWorld(World* world) + { + m_world = world; + } + inline EntityList::iterator::iterator(const EntityList* list, std::size_t nextId) : m_nextEntityId(nextId), diff --git a/SDK/include/NDK/World.hpp b/SDK/include/NDK/World.hpp index ca6e917b7..072ce0637 100644 --- a/SDK/include/NDK/World.hpp +++ b/SDK/include/NDK/World.hpp @@ -26,6 +26,7 @@ namespace Ndk { friend BaseSystem; friend Entity; + friend EntityList; public: using EntityVector = std::vector; @@ -97,7 +98,9 @@ namespace Ndk inline void Invalidate(); inline void Invalidate(EntityId id); inline void InvalidateSystemOrder(); + inline void RegisterEntityList(EntityList* list); void ReorderSystems(); + inline void UnregisterEntityList(EntityList* list); struct DoubleBitset { @@ -123,6 +126,7 @@ namespace Ndk std::vector m_orderedSystems; std::vector m_entities; std::vector m_entityBlocks; + std::vector m_referencedByLists; std::vector> m_waitingEntities; EntityList m_aliveEntities; ProfilerData m_profilerData; diff --git a/SDK/include/NDK/World.inl b/SDK/include/NDK/World.inl index 1c3e446e1..85a34c9cc 100644 --- a/SDK/include/NDK/World.inl +++ b/SDK/include/NDK/World.inl @@ -443,25 +443,31 @@ namespace Ndk m_dirtyEntities = std::move(world.m_dirtyEntities); m_entityBlocks = std::move(world.m_entityBlocks); m_freeEntityIds = std::move(world.m_freeEntityIds); + m_isProfilerEnabled = world.m_isProfilerEnabled; m_killedEntities = std::move(world.m_killedEntities); m_orderedSystems = std::move(world.m_orderedSystems); m_orderedSystemsUpdated = world.m_orderedSystemsUpdated; m_profilerData = std::move(world.m_profilerData); - m_isProfilerEnabled = world.m_isProfilerEnabled; + m_referencedByLists = std::move(world.m_referencedByLists); m_entities = std::move(world.m_entities); for (EntityBlock& block : m_entities) block.entity.SetWorld(this); + for (EntityList* list : m_referencedByLists) + list->SetWorld(this); + m_waitingEntities = std::move(world.m_waitingEntities); for (auto& blockPtr : m_waitingEntities) blockPtr->entity.SetWorld(this); m_systems = std::move(world.m_systems); for (const auto& systemPtr : m_systems) + { if (systemPtr) systemPtr->SetWorld(this); - + } + return *this; } @@ -480,4 +486,19 @@ namespace Ndk { m_orderedSystemsUpdated = false; } + + inline void World::RegisterEntityList(EntityList* list) + { + m_referencedByLists.push_back(list); + } + + inline void World::UnregisterEntityList(EntityList* list) + { + auto it = std::find(m_referencedByLists.begin(), m_referencedByLists.end(), list); + assert(it != m_referencedByLists.end()); + + // Swap and pop idiom + *it = m_referencedByLists.back(); + m_referencedByLists.pop_back(); + } } diff --git a/SDK/src/NDK/EntityList.cpp b/SDK/src/NDK/EntityList.cpp index 49841843d..fdae20097 100644 --- a/SDK/src/NDK/EntityList.cpp +++ b/SDK/src/NDK/EntityList.cpp @@ -7,6 +7,149 @@ namespace Ndk { + /*! + * \brief Construct a new entity list by copying another one + */ + EntityList::EntityList(const EntityList& entityList) : + m_entityBits(entityList.m_entityBits), + m_world(entityList.m_world) + { + for (const Ndk::EntityHandle& entity : *this) + entity->RegisterEntityList(this); + + if (m_world) + m_world->RegisterEntityList(this); + } + + /*! + * \brief Construct a new entity list by moving a list into this one + */ + EntityList::EntityList(EntityList&& entityList) noexcept : + m_entityBits(std::move(entityList.m_entityBits)), + m_world(entityList.m_world) + { + for (const Ndk::EntityHandle& entity : *this) + { + entity->UnregisterEntityList(&entityList); + entity->RegisterEntityList(this); + } + + if (m_world) + { + m_world->UnregisterEntityList(&entityList); + m_world->RegisterEntityList(this); + + entityList.m_world = nullptr; + } + } + + EntityList::~EntityList() + { + for (const Ndk::EntityHandle& entity : *this) + entity->UnregisterEntityList(this); + + if (m_world) + m_world->UnregisterEntityList(this); + } + + + /*! + * \brief Clears the set from every entities + * + * \remark This resets the implicit world member, allowing you to insert entities from a different world than previously + */ + void EntityList::Clear() + { + for (const Ndk::EntityHandle& entity : *this) + entity->UnregisterEntityList(this); + + m_entityBits.Clear(); + + if (m_world) + { + m_world->UnregisterEntityList(this); + m_world = nullptr; + } + } + + /*! + * \brief Inserts the entity into the set + * + * Marks an entity as present in this entity list, it must belongs to the same world as others entities contained in this list. + * + * \param entity Valid pointer to an entity + * + * \remark If entity is already contained, no action is performed + * \remark If any entity has been inserted since construction (or last Clear call), the entity must belong to the same world as the previously inserted entities + */ + void EntityList::Insert(Entity* entity) + { + NazaraAssert(entity, "Invalid entity"); + + if (!Has(entity)) + { + entity->RegisterEntityList(this); + + m_entityBits.UnboundedSet(entity->GetId(), true); + if (!m_world) + { + m_world = entity->GetWorld(); + m_world->RegisterEntityList(this); + } + } + } + + EntityList& EntityList::operator=(const EntityList& entityList) + { + if (m_world) + m_world->UnregisterEntityList(this); + + for (const Ndk::EntityHandle& entity : *this) + entity->UnregisterEntityList(this); + + m_entityBits = entityList.m_entityBits; + m_world = entityList.m_world; + + for (const Ndk::EntityHandle& entity : *this) + entity->RegisterEntityList(this); + + if (m_world) + m_world->RegisterEntityList(this); + + return *this; + } + + EntityList& EntityList::operator=(EntityList&& entityList) noexcept + { + if (this == &entityList) + return *this; + + if (m_world) + m_world->UnregisterEntityList(this); + + for (const Ndk::EntityHandle& entity : *this) + entity->UnregisterEntityList(this); + + m_entityBits = std::move(entityList.m_entityBits); + m_world = entityList.m_world; + + if (m_world) + { + m_world->UnregisterEntityList(&entityList); + m_world->RegisterEntityList(this); + + entityList.m_world = nullptr; + } + + for (const Ndk::EntityHandle& entity : *this) + { + entity->UnregisterEntityList(&entityList); + entity->RegisterEntityList(this); + } + + return *this; + } + const EntityHandle& EntityList::iterator::operator*() const { return m_list->GetWorld()->GetEntity(static_cast(m_nextEntityId)); diff --git a/SDK/src/NDK/World.cpp b/SDK/src/NDK/World.cpp index ef59463bc..9b255c71e 100644 --- a/SDK/src/NDK/World.cpp +++ b/SDK/src/NDK/World.cpp @@ -131,6 +131,11 @@ namespace Ndk } m_entityBlocks.clear(); + // Reset world for entity lists + for (EntityList* list : m_referencedByLists) + list->SetWorld(nullptr); + m_referencedByLists.clear(); + m_entities.clear(); m_waitingEntities.clear(); From 6d6391ca46eae4412d911cc9589cfa2eaeb86502 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Tue, 30 Mar 2021 17:48:32 +0200 Subject: [PATCH 074/278] Fix compilation I forgot master was still in C++14 --- include/Nazara/Core/HandledObject.inl | 2 +- include/Nazara/Core/ObjectHandle.inl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/Nazara/Core/HandledObject.inl b/include/Nazara/Core/HandledObject.inl index 8f1e497a0..6addf9c77 100644 --- a/include/Nazara/Core/HandledObject.inl +++ b/include/Nazara/Core/HandledObject.inl @@ -61,7 +61,7 @@ namespace Nz template ObjectHandle HandledObject::CreateHandle() { - static_assert(std::is_base_of_v, "Cannot retrieve a handle for a non-related class"); + static_assert(std::is_base_of::value, "Cannot retrieve a handle for a non-related class"); return ObjectHandle(static_cast(this)); } diff --git a/include/Nazara/Core/ObjectHandle.inl b/include/Nazara/Core/ObjectHandle.inl index 1a3d09b9b..be3ec5c0c 100644 --- a/include/Nazara/Core/ObjectHandle.inl +++ b/include/Nazara/Core/ObjectHandle.inl @@ -31,7 +31,7 @@ namespace Nz ObjectHandle::ObjectHandle(const ObjectHandle& ref) : m_handleData(ref.m_handleData) { - static_assert(std::is_base_of_v, "Can only implicitly convert from a derived to a base"); + static_assert(std::is_base_of::value, "Can only implicitly convert from a derived to a base"); } template @@ -41,7 +41,7 @@ namespace Nz { ref.m_handleData = Detail::HandleData::GetEmptyObject(); - static_assert(std::is_base_of_v, "Can only implicitly convert from a derived to a base"); + static_assert(std::is_base_of::value, "Can only implicitly convert from a derived to a base"); } /*! From 9a0f2014336665e4cf7fb9b683350ae67b245348 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 24 Feb 2021 23:51:24 +0100 Subject: [PATCH 075/278] Initial shaderlang commit --- include/Nazara/Shader/ShaderLangLexer.hpp | 56 +++ include/Nazara/Shader/ShaderLangLexer.inl | 12 + include/Nazara/Shader/ShaderLangParser.hpp | 58 ++++ include/Nazara/Shader/ShaderLangParser.inl | 16 + include/Nazara/Shader/ShaderLangTokenList.hpp | 36 ++ src/Nazara/Shader/ShaderLangLexer.cpp | 327 ++++++++++++++++++ src/Nazara/Shader/ShaderLangParser.cpp | 118 +++++++ 7 files changed, 623 insertions(+) create mode 100644 include/Nazara/Shader/ShaderLangLexer.hpp create mode 100644 include/Nazara/Shader/ShaderLangLexer.inl create mode 100644 include/Nazara/Shader/ShaderLangParser.hpp create mode 100644 include/Nazara/Shader/ShaderLangParser.inl create mode 100644 include/Nazara/Shader/ShaderLangTokenList.hpp create mode 100644 src/Nazara/Shader/ShaderLangLexer.cpp create mode 100644 src/Nazara/Shader/ShaderLangParser.cpp diff --git a/include/Nazara/Shader/ShaderLangLexer.hpp b/include/Nazara/Shader/ShaderLangLexer.hpp new file mode 100644 index 000000000..10c63d31a --- /dev/null +++ b/include/Nazara/Shader/ShaderLangLexer.hpp @@ -0,0 +1,56 @@ +// Copyright (C) 2020 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_SHADER_LANGLEXER_HPP +#define NAZARA_SHADER_LANGLEXER_HPP + +#include +#include +#include +#include +#include +#include + +namespace Nz::ShaderLang +{ + enum class TokenType + { +#define NAZARA_SHADERLANG_TOKEN(X) X, + +#include + }; + + struct Token + { + unsigned int column; + unsigned int line; + TokenType type; + std::variant data; + }; + + class BadNumber : public std::exception + { + using exception::exception; + }; + + class NumberOutOfRange : public std::exception + { + using exception::exception; + }; + + class UnrecognizedToken : public std::exception + { + using exception::exception; + }; + + NAZARA_SHADER_API std::vector Tokenize(const std::string_view& str); + NAZARA_SHADER_API const char* ToString(TokenType tokenType); + NAZARA_SHADER_API std::string ToString(const std::vector& tokens, bool pretty = true); +} + +#include + +#endif diff --git a/include/Nazara/Shader/ShaderLangLexer.inl b/include/Nazara/Shader/ShaderLangLexer.inl new file mode 100644 index 000000000..6767d0351 --- /dev/null +++ b/include/Nazara/Shader/ShaderLangLexer.inl @@ -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 +#include + +namespace Nz +{ +} + +#include diff --git a/include/Nazara/Shader/ShaderLangParser.hpp b/include/Nazara/Shader/ShaderLangParser.hpp new file mode 100644 index 000000000..be6da0a35 --- /dev/null +++ b/include/Nazara/Shader/ShaderLangParser.hpp @@ -0,0 +1,58 @@ +// Copyright (C) 2020 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_SHADER_LANGPARSER_HPP +#define NAZARA_SHADER_LANGPARSER_HPP + +#include +#include +#include + +namespace Nz::ShaderLang +{ + class ExpectedToken : public std::exception + { + public: + using exception::exception; + }; + + class UnexpectedToken : public std::exception + { + public: + using exception::exception; + }; + + class NAZARA_SHADER_API Parser + { + public: + inline Parser(); + ~Parser() = default; + + void Parse(const std::vector& tokens); + + private: + const Token& Advance(); + void Expect(const Token& token, TokenType type); + void ExpectNext(TokenType type); + void ParseFunctionBody(); + void ParseFunctionDeclaration(); + void ParseFunctionParameter(); + const Token& PeekNext(); + + struct Context + { + std::size_t tokenCount; + std::size_t tokenIndex = 0; + const Token* tokens; + }; + + Context* m_context; + }; +} + +#include + +#endif diff --git a/include/Nazara/Shader/ShaderLangParser.inl b/include/Nazara/Shader/ShaderLangParser.inl new file mode 100644 index 000000000..12db8d17d --- /dev/null +++ b/include/Nazara/Shader/ShaderLangParser.inl @@ -0,0 +1,16 @@ +// 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 +#include + +namespace Nz::ShaderLang +{ + inline Parser::Parser() : + m_context(nullptr) + { + } +} + +#include diff --git a/include/Nazara/Shader/ShaderLangTokenList.hpp b/include/Nazara/Shader/ShaderLangTokenList.hpp new file mode 100644 index 000000000..b968c590e --- /dev/null +++ b/include/Nazara/Shader/ShaderLangTokenList.hpp @@ -0,0 +1,36 @@ +// Copyright (C) 2020 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#if !defined(NAZARA_SHADERLANG_TOKEN) +#error You must define NAZARA_SHADERLANG_TOKEN before including this file +#endif + +#ifndef NAZARA_SHADERLANG_TOKENT_LAST +#define NAZARA_SHADERLANG_TOKEN_LAST(X) NAZARA_SHADERLANG_TOKEN(X) +#endif + +NAZARA_SHADERLANG_TOKEN(Add) +NAZARA_SHADERLANG_TOKEN(BoolFalse) +NAZARA_SHADERLANG_TOKEN(BoolTrue) +NAZARA_SHADERLANG_TOKEN(ClosingParenthesis) +NAZARA_SHADERLANG_TOKEN(ClosingCurlyBracket) +NAZARA_SHADERLANG_TOKEN(Colon) +NAZARA_SHADERLANG_TOKEN(Comma) +NAZARA_SHADERLANG_TOKEN(Divide) +NAZARA_SHADERLANG_TOKEN(Dot) +NAZARA_SHADERLANG_TOKEN(FloatingPointValue) +NAZARA_SHADERLANG_TOKEN(EndOfStream) +NAZARA_SHADERLANG_TOKEN(FunctionDeclaration) +NAZARA_SHADERLANG_TOKEN(FunctionReturn) +NAZARA_SHADERLANG_TOKEN(IntegerValue) +NAZARA_SHADERLANG_TOKEN(Identifier) +NAZARA_SHADERLANG_TOKEN(Multiply) +NAZARA_SHADERLANG_TOKEN(OpenCurlyBracket) +NAZARA_SHADERLANG_TOKEN(OpenParenthesis) +NAZARA_SHADERLANG_TOKEN(Semicolon) +NAZARA_SHADERLANG_TOKEN(Return) +NAZARA_SHADERLANG_TOKEN(Subtract) + +#undef NAZARA_SHADERLANG_TOKEN +#undef NAZARA_SHADERLANG_TOKEN_LAST diff --git a/src/Nazara/Shader/ShaderLangLexer.cpp b/src/Nazara/Shader/ShaderLangLexer.cpp new file mode 100644 index 000000000..a93cefa85 --- /dev/null +++ b/src/Nazara/Shader/ShaderLangLexer.cpp @@ -0,0 +1,327 @@ +// 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 +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Nz::ShaderLang +{ + namespace + { + class ForceCLocale + { + public: + ForceCLocale() + { + m_previousLocale = std::locale::global(std::locale::classic()); + } + + ~ForceCLocale() + { + std::locale::global(m_previousLocale); + } + + private: + std::locale m_previousLocale; + }; + } + + std::vector Tokenize(const std::string_view& str) + { + // Can't use std::from_chars for double thanks to libc++ and libstdc++ developers being lazy + ForceCLocale forceCLocale; + + std::unordered_map reservedKeywords = { + { "false", TokenType::BoolFalse }, + { "fn", TokenType::FunctionDeclaration }, + { "return", TokenType::Return }, + { "true", TokenType::BoolTrue } + }; + + std::size_t currentPos = 0; + + auto Peek = [&](std::size_t advance = 1) -> char + { + if (currentPos + advance < str.size()) + return str[currentPos + advance]; + else + return char(-1); + }; + + auto IsAlphaNum = [&](const char c) + { + return std::isalnum(c) || c == '_'; + }; + + unsigned int lineNumber = 0; + std::size_t lastLineFeed = 0; + std::vector tokens; + + for (;;) + { + char c = Peek(0); + + Token token; + token.column = currentPos - lastLineFeed; + token.line = lineNumber; + + if (c == -1) + { + token.type = TokenType::EndOfStream; + tokens.push_back(std::move(token)); + break; + } + + std::optional tokenType; + switch (c) + { + case ' ': + case '\t': + case '\r': + break; //< Ignore blank spaces + + case '\n': + { + lineNumber++; + lastLineFeed = currentPos; + break; + } + + case '-': + { + if (Peek() == '>') + { + tokenType = TokenType::FunctionReturn; + break; + } + + tokenType = TokenType::Subtract; + break; + } + + case '/': + { + char next = Peek(); + if (next == '/') + { + // Line comment + do + { + currentPos++; + next = Peek(); + } + while (next != -1 && next != '\n'); + } + else if (next == '*') + { + // Block comment + do + { + currentPos++; + next = Peek(); + + if (next == '*') + { + currentPos++; + if (Peek() == '/') + break; + } + else if (next == '\n') + { + lineNumber++; + lastLineFeed = currentPos + 1; + } + } + while (next != -1); + } + else + tokenType == TokenType::Divide; + + break; + } + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + bool floatingPoint = false; + + std::size_t start = currentPos; + char next = Peek(); + + if (next == 'x' || next == 'X') + currentPos++; + + for (;;) + { + next = Peek(); + + if (!isdigit(next)) + { + if (next != '.') + break; + + if (floatingPoint) + break; + + floatingPoint = true; + } + + currentPos++; + } + + if (floatingPoint) + { + tokenType = TokenType::FloatingPointValue; + + std::string valueStr(str.substr(start, currentPos - start + 1)); + + char* end; + double value = std::strtod(valueStr.c_str(), &end); + if (end != &str[currentPos]) + throw BadNumber{}; + + token.data = value; + } + else + { + tokenType = TokenType::IntegerValue; + + long long value; + std::from_chars_result r = std::from_chars(&str[start], &str[currentPos + 1], value); + if (r.ptr != &str[currentPos]) + { + if (r.ec == std::errc::result_out_of_range) + throw NumberOutOfRange{}; + + throw BadNumber{}; + } + + token.data = value; + } + + break; + } + + case '+': tokenType = TokenType::Add; break; + case '*': tokenType = TokenType::Multiply; break; + case ':': tokenType = TokenType::Colon; break; + case ';': tokenType = TokenType::Semicolon; break; + case '.': tokenType = TokenType::Dot; break; + case ',': tokenType = TokenType::Comma; break; + case '{': tokenType = TokenType::OpenCurlyBracket; break; + case '}': tokenType = TokenType::ClosingCurlyBracket; break; + case '(': tokenType = TokenType::OpenParenthesis; break; + case ')': tokenType = TokenType::ClosingParenthesis; break; + + default: break; + } + + if (!tokenType) + { + if (IsAlphaNum(c)) + { + std::size_t start = currentPos; + + while (IsAlphaNum(Peek())) + currentPos++; + + std::string identifier(str.substr(start, currentPos - start + 1)); + if (auto it = reservedKeywords.find(identifier); it == reservedKeywords.end()) + { + tokenType = TokenType::Identifier; + token.data = std::move(identifier); + } + else + tokenType = it->second; + } + } + + if (tokenType) + { + token.type = *tokenType; + + tokens.push_back(std::move(token)); + } + + currentPos++; + } + + return tokens; + } + + const char* ToString(TokenType tokenType) + { + switch (tokenType) + { +#define NAZARA_SHADERLANG_TOKEN(X) case TokenType:: X: return #X; + +#include + } + + return ""; + } + + std::string ToString(const std::vector& tokens, bool pretty) + { + if (tokens.empty()) + return {}; + + unsigned int lastLineNumber = tokens.front().line; + + std::stringstream ss; + bool empty = true; + + for (const Token& token : tokens) + { + if (token.line != lastLineNumber && pretty) + { + lastLineNumber = token.line; + if (!empty) + ss << '\n'; + } + else if (!empty) + ss << ' '; + + ss << ToString(token.type); + switch (token.type) + { + case TokenType::FloatingPointValue: + ss << "(" << std::get(token.data) << ")"; + break; + + case TokenType::Identifier: + ss << "(" << std::get(token.data) << ")"; + break; + + case TokenType::IntegerValue: + ss << "(" << std::get(token.data) << ")"; + break; + + default: + break; + } + + empty = false; + } + + ss << '\n'; + + return std::move(ss).str(); + } +} diff --git a/src/Nazara/Shader/ShaderLangParser.cpp b/src/Nazara/Shader/ShaderLangParser.cpp new file mode 100644 index 000000000..482afd007 --- /dev/null +++ b/src/Nazara/Shader/ShaderLangParser.cpp @@ -0,0 +1,118 @@ +// 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 +#include +#include + +namespace Nz::ShaderLang +{ + void Parser::Parse(const std::vector& tokens) + { + Context context; + context.tokenCount = tokens.size(); + context.tokens = tokens.data(); + + m_context = &context; + + for (const Token& token : tokens) + { + switch (token.type) + { + case TokenType::FunctionDeclaration: + ParseFunctionDeclaration(); + break; + + default: + throw UnexpectedToken{}; + } + } + } + + const Token& Parser::Advance() + { + assert(m_context->tokenIndex + 1 < m_context->tokenCount); + return m_context->tokens[++m_context->tokenIndex]; + } + + void Parser::Expect(const Token& token, TokenType type) + { + if (token.type != type) + throw ExpectedToken{}; + } + + void Parser::ExpectNext(TokenType type) + { + Expect(m_context->tokens[m_context->tokenIndex + 1], type); + } + + void Parser::ParseFunctionBody() + { + + } + + void Parser::ParseFunctionDeclaration() + { + ExpectNext(TokenType::Identifier); + + std::string functionName = std::get(Advance().data); + + ExpectNext(TokenType::OpenParenthesis); + Advance(); + + bool firstParameter = true; + for (;;) + { + const Token& t = PeekNext(); + if (t.type == TokenType::ClosingParenthesis) + break; + + if (!firstParameter) + { + Expect(t, TokenType::Comma); + Advance(); + } + + ParseFunctionParameter(); + firstParameter = false; + } + + ExpectNext(TokenType::ClosingParenthesis); + Advance(); + + if (PeekNext().type == TokenType::FunctionReturn) + { + Advance(); + + std::string returnType = std::get(Advance().data); + } + + + ExpectNext(TokenType::OpenCurlyBracket); + Advance(); + + ParseFunctionBody(); + + ExpectNext(TokenType::ClosingCurlyBracket); + Advance(); + } + + void Parser::ParseFunctionParameter() + { + ExpectNext(TokenType::Identifier); + std::string parameterName = std::get(Advance().data); + + ExpectNext(TokenType::Colon); + Advance(); + + ExpectNext(TokenType::Identifier); + std::string parameterType = std::get(Advance().data); + } + + const Token& Parser::PeekNext() + { + assert(m_context->tokenIndex + 1 < m_context->tokenCount); + return m_context->tokens[m_context->tokenIndex + 1]; + } +} From b320b5b44e4942516e56cab5e4d57ef76b71bfa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sun, 28 Feb 2021 17:50:32 +0100 Subject: [PATCH 076/278] Shader: Add function parameters and return handling --- include/Nazara/Shader/GlslWriter.hpp | 1 + include/Nazara/Shader/ShaderAst.hpp | 4 +- include/Nazara/Shader/ShaderAstCloner.hpp | 1 + .../Shader/ShaderAstRecursiveVisitor.hpp | 1 + include/Nazara/Shader/ShaderAstSerializer.hpp | 1 + include/Nazara/Shader/ShaderAstValidator.hpp | 1 + include/Nazara/Shader/ShaderAstVisitor.hpp | 1 + .../Nazara/Shader/ShaderAstVisitorExcept.hpp | 1 + include/Nazara/Shader/ShaderEnums.hpp | 1 + include/Nazara/Shader/ShaderLangParser.hpp | 43 ++- include/Nazara/Shader/ShaderLangTokenList.hpp | 4 +- include/Nazara/Shader/ShaderNodes.hpp | 11 + include/Nazara/Shader/ShaderNodes.inl | 16 +- include/Nazara/Shader/SpirvAstVisitor.hpp | 1 + include/Nazara/Shader/SpirvBlock.hpp | 15 +- include/Nazara/Shader/SpirvBlock.inl | 56 +++- include/Nazara/Shader/SpirvExpressionLoad.hpp | 1 + include/Nazara/Shader/SpirvPrinter.hpp | 3 + include/Nazara/Shader/SpirvPrinter.inl | 10 + include/Nazara/Shader/SpirvSection.hpp | 51 +--- include/Nazara/Shader/SpirvSection.inl | 145 ----------- include/Nazara/Shader/SpirvSectionBase.hpp | 75 ++++++ include/Nazara/Shader/SpirvSectionBase.inl | 157 +++++++++++ include/Nazara/Shader/SpirvWriter.hpp | 6 +- src/Nazara/Shader/GlslWriter.cpp | 12 + src/Nazara/Shader/ShaderAst.cpp | 2 +- src/Nazara/Shader/ShaderAstCloner.cpp | 5 + .../Shader/ShaderAstRecursiveVisitor.cpp | 6 + src/Nazara/Shader/ShaderAstSerializer.cpp | 21 +- src/Nazara/Shader/ShaderAstValidator.cpp | 16 ++ src/Nazara/Shader/ShaderAstVisitorExcept.cpp | 5 + src/Nazara/Shader/ShaderLangLexer.cpp | 8 +- src/Nazara/Shader/ShaderLangParser.cpp | 245 ++++++++++++++++-- src/Nazara/Shader/ShaderNodes.cpp | 5 + src/Nazara/Shader/SpirvAstVisitor.cpp | 8 + src/Nazara/Shader/SpirvConstantCache.cpp | 7 + src/Nazara/Shader/SpirvExpressionLoad.cpp | 5 + ...{SpirvSection.cpp => SpirvSectionBase.cpp} | 6 +- src/Nazara/Shader/SpirvWriter.cpp | 188 ++++++++------ 39 files changed, 818 insertions(+), 327 deletions(-) create mode 100644 include/Nazara/Shader/SpirvSectionBase.hpp create mode 100644 include/Nazara/Shader/SpirvSectionBase.inl rename src/Nazara/Shader/{SpirvSection.cpp => SpirvSectionBase.cpp} (85%) diff --git a/include/Nazara/Shader/GlslWriter.hpp b/include/Nazara/Shader/GlslWriter.hpp index a74871da4..5a6f7049d 100644 --- a/include/Nazara/Shader/GlslWriter.hpp +++ b/include/Nazara/Shader/GlslWriter.hpp @@ -83,6 +83,7 @@ namespace Nz void Visit(ShaderNodes::LocalVariable& var) override; void Visit(ShaderNodes::NoOp& node) override; void Visit(ShaderNodes::ParameterVariable& var) override; + void Visit(ShaderNodes::ReturnStatement& node) override; void Visit(ShaderNodes::OutputVariable& var) override; void Visit(ShaderNodes::Sample2D& node) override; void Visit(ShaderNodes::StatementBlock& node) override; diff --git a/include/Nazara/Shader/ShaderAst.hpp b/include/Nazara/Shader/ShaderAst.hpp index 54199a179..f34b0ac9f 100644 --- a/include/Nazara/Shader/ShaderAst.hpp +++ b/include/Nazara/Shader/ShaderAst.hpp @@ -35,7 +35,7 @@ namespace Nz ~ShaderAst() = default; void AddCondition(std::string name); - void AddFunction(std::string name, ShaderNodes::StatementPtr statement, std::vector parameters = {}, ShaderNodes::BasicType returnType = ShaderNodes::BasicType::Void); + void AddFunction(std::string name, ShaderNodes::StatementPtr statement, std::vector parameters = {}, ShaderExpressionType returnType = ShaderNodes::BasicType::Void); void AddInput(std::string name, ShaderExpressionType type, std::optional locationIndex = {}); void AddOutput(std::string name, ShaderExpressionType type, std::optional locationIndex = {}); void AddStruct(std::string name, std::vector members); @@ -85,7 +85,7 @@ namespace Nz { std::string name; std::vector parameters; - ShaderNodes::BasicType returnType; + ShaderExpressionType returnType; ShaderNodes::StatementPtr statement; }; diff --git a/include/Nazara/Shader/ShaderAstCloner.hpp b/include/Nazara/Shader/ShaderAstCloner.hpp index 94b68cb0a..b777e2ba6 100644 --- a/include/Nazara/Shader/ShaderAstCloner.hpp +++ b/include/Nazara/Shader/ShaderAstCloner.hpp @@ -48,6 +48,7 @@ namespace Nz void Visit(ShaderNodes::Identifier& node) override; void Visit(ShaderNodes::IntrinsicCall& node) override; void Visit(ShaderNodes::NoOp& node) override; + void Visit(ShaderNodes::ReturnStatement& node) override; void Visit(ShaderNodes::Sample2D& node) override; void Visit(ShaderNodes::StatementBlock& node) override; void Visit(ShaderNodes::SwizzleOp& node) override; diff --git a/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp b/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp index ce8ba487c..1b7e1eebd 100644 --- a/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp +++ b/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp @@ -35,6 +35,7 @@ namespace Nz void Visit(ShaderNodes::Identifier& node) override; void Visit(ShaderNodes::IntrinsicCall& node) override; void Visit(ShaderNodes::NoOp& node) override; + void Visit(ShaderNodes::ReturnStatement& node) override; void Visit(ShaderNodes::Sample2D& node) override; void Visit(ShaderNodes::StatementBlock& node) override; void Visit(ShaderNodes::SwizzleOp& node) override; diff --git a/include/Nazara/Shader/ShaderAstSerializer.hpp b/include/Nazara/Shader/ShaderAstSerializer.hpp index ad8af504d..b3e674fae 100644 --- a/include/Nazara/Shader/ShaderAstSerializer.hpp +++ b/include/Nazara/Shader/ShaderAstSerializer.hpp @@ -41,6 +41,7 @@ namespace Nz void Serialize(ShaderNodes::IntrinsicCall& node); void Serialize(ShaderNodes::NamedVariable& var); void Serialize(ShaderNodes::NoOp& node); + void Serialize(ShaderNodes::ReturnStatement& node); void Serialize(ShaderNodes::Sample2D& node); void Serialize(ShaderNodes::StatementBlock& node); void Serialize(ShaderNodes::SwizzleOp& node); diff --git a/include/Nazara/Shader/ShaderAstValidator.hpp b/include/Nazara/Shader/ShaderAstValidator.hpp index 579893aa4..90ec82c71 100644 --- a/include/Nazara/Shader/ShaderAstValidator.hpp +++ b/include/Nazara/Shader/ShaderAstValidator.hpp @@ -48,6 +48,7 @@ namespace Nz void Visit(ShaderNodes::ExpressionStatement& node) override; void Visit(ShaderNodes::Identifier& node) override; void Visit(ShaderNodes::IntrinsicCall& node) override; + void Visit(ShaderNodes::ReturnStatement& node) override; void Visit(ShaderNodes::Sample2D& node) override; void Visit(ShaderNodes::StatementBlock& node) override; void Visit(ShaderNodes::SwizzleOp& node) override; diff --git a/include/Nazara/Shader/ShaderAstVisitor.hpp b/include/Nazara/Shader/ShaderAstVisitor.hpp index 79fb23e9e..183a58f92 100644 --- a/include/Nazara/Shader/ShaderAstVisitor.hpp +++ b/include/Nazara/Shader/ShaderAstVisitor.hpp @@ -36,6 +36,7 @@ namespace Nz virtual void Visit(ShaderNodes::Identifier& node) = 0; virtual void Visit(ShaderNodes::IntrinsicCall& node) = 0; virtual void Visit(ShaderNodes::NoOp& node) = 0; + virtual void Visit(ShaderNodes::ReturnStatement& node) = 0; virtual void Visit(ShaderNodes::Sample2D& node) = 0; virtual void Visit(ShaderNodes::StatementBlock& node) = 0; virtual void Visit(ShaderNodes::SwizzleOp& node) = 0; diff --git a/include/Nazara/Shader/ShaderAstVisitorExcept.hpp b/include/Nazara/Shader/ShaderAstVisitorExcept.hpp index 65e507062..5076284fe 100644 --- a/include/Nazara/Shader/ShaderAstVisitorExcept.hpp +++ b/include/Nazara/Shader/ShaderAstVisitorExcept.hpp @@ -31,6 +31,7 @@ namespace Nz void Visit(ShaderNodes::Identifier& node) override; void Visit(ShaderNodes::IntrinsicCall& node) override; void Visit(ShaderNodes::NoOp& node) override; + void Visit(ShaderNodes::ReturnStatement& node) override; void Visit(ShaderNodes::Sample2D& node) override; void Visit(ShaderNodes::StatementBlock& node) override; void Visit(ShaderNodes::SwizzleOp& node) override; diff --git a/include/Nazara/Shader/ShaderEnums.hpp b/include/Nazara/Shader/ShaderEnums.hpp index 64d8729f3..87f2f4cd7 100644 --- a/include/Nazara/Shader/ShaderEnums.hpp +++ b/include/Nazara/Shader/ShaderEnums.hpp @@ -91,6 +91,7 @@ namespace Nz::ShaderNodes Identifier, IntrinsicCall, NoOp, + ReturnStatement, Sample2D, SwizzleOp, StatementBlock, diff --git a/include/Nazara/Shader/ShaderLangParser.hpp b/include/Nazara/Shader/ShaderLangParser.hpp index be6da0a35..6b3d296a3 100644 --- a/include/Nazara/Shader/ShaderLangParser.hpp +++ b/include/Nazara/Shader/ShaderLangParser.hpp @@ -10,6 +10,7 @@ #include #include #include +#include namespace Nz::ShaderLang { @@ -19,6 +20,18 @@ namespace Nz::ShaderLang using exception::exception; }; + class ReservedKeyword : public std::exception + { + public: + using exception::exception; + }; + + class UnknownType : public std::exception + { + public: + using exception::exception; + }; + class UnexpectedToken : public std::exception { public: @@ -31,19 +44,39 @@ namespace Nz::ShaderLang inline Parser(); ~Parser() = default; - void Parse(const std::vector& tokens); + ShaderAst Parse(const std::vector& tokens); private: + // Flow control const Token& Advance(); void Expect(const Token& token, TokenType type); - void ExpectNext(TokenType type); - void ParseFunctionBody(); - void ParseFunctionDeclaration(); - void ParseFunctionParameter(); + const Token& ExpectNext(TokenType type); const Token& PeekNext(); + // Statements + ShaderNodes::StatementPtr ParseFunctionBody(); + void ParseFunctionDeclaration(); + ShaderAst::FunctionParameter ParseFunctionParameter(); + ShaderNodes::StatementPtr ParseReturnStatement(); + ShaderNodes::StatementPtr ParseStatement(); + ShaderNodes::StatementPtr ParseStatementList(); + + // Expressions + ShaderNodes::ExpressionPtr ParseBinOpRhs(int exprPrecedence, ShaderNodes::ExpressionPtr lhs); + ShaderNodes::ExpressionPtr ParseExpression(); + ShaderNodes::ExpressionPtr ParseIdentifier(); + ShaderNodes::ExpressionPtr ParseIntegerExpression(); + ShaderNodes::ExpressionPtr ParseParenthesisExpression(); + ShaderNodes::ExpressionPtr ParsePrimaryExpression(); + + std::string ParseIdentifierAsName(); + ShaderExpressionType ParseIdentifierAsType(); + + static int GetTokenPrecedence(TokenType token); + struct Context { + ShaderAst result; std::size_t tokenCount; std::size_t tokenIndex = 0; const Token* tokens; diff --git a/include/Nazara/Shader/ShaderLangTokenList.hpp b/include/Nazara/Shader/ShaderLangTokenList.hpp index b968c590e..caaa2964d 100644 --- a/include/Nazara/Shader/ShaderLangTokenList.hpp +++ b/include/Nazara/Shader/ShaderLangTokenList.hpp @@ -10,7 +10,6 @@ #define NAZARA_SHADERLANG_TOKEN_LAST(X) NAZARA_SHADERLANG_TOKEN(X) #endif -NAZARA_SHADERLANG_TOKEN(Add) NAZARA_SHADERLANG_TOKEN(BoolFalse) NAZARA_SHADERLANG_TOKEN(BoolTrue) NAZARA_SHADERLANG_TOKEN(ClosingParenthesis) @@ -26,11 +25,12 @@ NAZARA_SHADERLANG_TOKEN(FunctionReturn) NAZARA_SHADERLANG_TOKEN(IntegerValue) NAZARA_SHADERLANG_TOKEN(Identifier) NAZARA_SHADERLANG_TOKEN(Multiply) +NAZARA_SHADERLANG_TOKEN(Minus) +NAZARA_SHADERLANG_TOKEN(Plus) NAZARA_SHADERLANG_TOKEN(OpenCurlyBracket) NAZARA_SHADERLANG_TOKEN(OpenParenthesis) NAZARA_SHADERLANG_TOKEN(Semicolon) NAZARA_SHADERLANG_TOKEN(Return) -NAZARA_SHADERLANG_TOKEN(Subtract) #undef NAZARA_SHADERLANG_TOKEN #undef NAZARA_SHADERLANG_TOKEN_LAST diff --git a/include/Nazara/Shader/ShaderNodes.hpp b/include/Nazara/Shader/ShaderNodes.hpp index e2e082b97..0d1d57183 100644 --- a/include/Nazara/Shader/ShaderNodes.hpp +++ b/include/Nazara/Shader/ShaderNodes.hpp @@ -168,6 +168,17 @@ namespace Nz static inline std::shared_ptr Build(); }; + struct NAZARA_SHADER_API ReturnStatement : public Statement + { + inline ReturnStatement(); + + void Visit(ShaderAstVisitor& visitor) override; + + ExpressionPtr returnExpr; + + static inline std::shared_ptr Build(ExpressionPtr expr = nullptr); + }; + ////////////////////////////////////////////////////////////////////////// struct NAZARA_SHADER_API AssignOp : public Expression diff --git a/include/Nazara/Shader/ShaderNodes.inl b/include/Nazara/Shader/ShaderNodes.inl index d050a4a31..c1e2b22c3 100644 --- a/include/Nazara/Shader/ShaderNodes.inl +++ b/include/Nazara/Shader/ShaderNodes.inl @@ -194,7 +194,7 @@ namespace Nz::ShaderNodes } - inline ShaderNodes::NoOp::NoOp() : + inline NoOp::NoOp() : Statement(NodeType::NoOp) { } @@ -205,6 +205,20 @@ namespace Nz::ShaderNodes } + inline ReturnStatement::ReturnStatement() : + Statement(NodeType::ReturnStatement) + { + } + + inline std::shared_ptr ShaderNodes::ReturnStatement::Build(ExpressionPtr expr) + { + auto node = std::make_shared(); + node->returnExpr = std::move(expr); + + return node; + } + + inline AssignOp::AssignOp() : Expression(NodeType::AssignOp) { diff --git a/include/Nazara/Shader/SpirvAstVisitor.hpp b/include/Nazara/Shader/SpirvAstVisitor.hpp index 0cac761ca..cdf6fa2fe 100644 --- a/include/Nazara/Shader/SpirvAstVisitor.hpp +++ b/include/Nazara/Shader/SpirvAstVisitor.hpp @@ -43,6 +43,7 @@ namespace Nz void Visit(ShaderNodes::Identifier& node) override; void Visit(ShaderNodes::IntrinsicCall& node) override; void Visit(ShaderNodes::NoOp& node) override; + void Visit(ShaderNodes::ReturnStatement& node) override; void Visit(ShaderNodes::Sample2D& node) override; void Visit(ShaderNodes::StatementBlock& node) override; void Visit(ShaderNodes::SwizzleOp& node) override; diff --git a/include/Nazara/Shader/SpirvBlock.hpp b/include/Nazara/Shader/SpirvBlock.hpp index 5fbbe0843..6c6a9310d 100644 --- a/include/Nazara/Shader/SpirvBlock.hpp +++ b/include/Nazara/Shader/SpirvBlock.hpp @@ -8,14 +8,14 @@ #define NAZARA_SPIRVBLOCK_HPP #include -#include +#include #include #include #include namespace Nz { - class NAZARA_SHADER_API SpirvBlock : public SpirvSection + class NAZARA_SHADER_API SpirvBlock : public SpirvSectionBase { public: inline SpirvBlock(SpirvWriter& writer); @@ -23,13 +23,24 @@ namespace Nz SpirvBlock(SpirvBlock&&) = default; ~SpirvBlock() = default; + inline std::size_t Append(SpirvOp opcode, const OpSize& wordCount); + template std::size_t Append(SpirvOp opcode, Args&&... args); + template std::size_t AppendVariadic(SpirvOp opcode, F&& callback); + inline UInt32 GetLabelId() const; + inline bool IsTerminated() const; + SpirvBlock& operator=(const SpirvBlock&) = delete; SpirvBlock& operator=(SpirvBlock&&) = default; + static inline bool IsTerminationInstruction(SpirvOp op); + private: + inline void HandleSpirvOp(SpirvOp op); + UInt32 m_labelId; + bool m_isTerminated; }; } diff --git a/include/Nazara/Shader/SpirvBlock.inl b/include/Nazara/Shader/SpirvBlock.inl index 3ce1f3050..2dc50e76b 100644 --- a/include/Nazara/Shader/SpirvBlock.inl +++ b/include/Nazara/Shader/SpirvBlock.inl @@ -7,16 +7,70 @@ namespace Nz { - inline SpirvBlock::SpirvBlock(SpirvWriter& writer) + inline SpirvBlock::SpirvBlock(SpirvWriter& writer) : + m_isTerminated(false) { m_labelId = writer.AllocateResultId(); Append(SpirvOp::OpLabel, m_labelId); } + inline std::size_t SpirvBlock::Append(SpirvOp opcode, const OpSize& wordCount) + { + HandleSpirvOp(opcode); + + return SpirvSectionBase::Append(opcode, wordCount); + } + + template + std::size_t SpirvBlock::Append(SpirvOp opcode, Args&&... args) + { + HandleSpirvOp(opcode); + + return SpirvSectionBase::Append(opcode, std::forward(args)...); + } + + template + std::size_t SpirvBlock::AppendVariadic(SpirvOp opcode, F&& callback) + { + HandleSpirvOp(opcode); + + return SpirvSectionBase::AppendVariadic(opcode, std::forward(callback)); + } + inline UInt32 SpirvBlock::GetLabelId() const { return m_labelId; } + + inline bool SpirvBlock::IsTerminated() const + { + return m_isTerminated; + } + + inline bool SpirvBlock::IsTerminationInstruction(SpirvOp op) + { + switch (op) + { + case SpirvOp::OpBranch: + case SpirvOp::OpBranchConditional: + case SpirvOp::OpKill: + case SpirvOp::OpReturn: + case SpirvOp::OpReturnValue: + case SpirvOp::OpSwitch: + case SpirvOp::OpUnreachable: + return true; + + default: + return false; + } + } + + inline void SpirvBlock::HandleSpirvOp(SpirvOp op) + { + assert(!m_isTerminated); + if (IsTerminationInstruction(op)) + m_isTerminated = true; + } } #include diff --git a/include/Nazara/Shader/SpirvExpressionLoad.hpp b/include/Nazara/Shader/SpirvExpressionLoad.hpp index bb44bba71..f59369a52 100644 --- a/include/Nazara/Shader/SpirvExpressionLoad.hpp +++ b/include/Nazara/Shader/SpirvExpressionLoad.hpp @@ -36,6 +36,7 @@ namespace Nz using ShaderVarVisitor::Visit; void Visit(ShaderNodes::InputVariable& var) override; void Visit(ShaderNodes::LocalVariable& var) override; + void Visit(ShaderNodes::ParameterVariable& var) override; void Visit(ShaderNodes::UniformVariable& var) override; SpirvExpressionLoad& operator=(const SpirvExpressionLoad&) = delete; diff --git a/include/Nazara/Shader/SpirvPrinter.hpp b/include/Nazara/Shader/SpirvPrinter.hpp index fbfe0eeb2..c7c7815f7 100644 --- a/include/Nazara/Shader/SpirvPrinter.hpp +++ b/include/Nazara/Shader/SpirvPrinter.hpp @@ -10,6 +10,7 @@ #include #include #include +#include namespace Nz { @@ -23,7 +24,9 @@ namespace Nz SpirvPrinter(SpirvPrinter&&) = default; ~SpirvPrinter() = default; + inline std::string Print(const std::vector& codepoints); inline std::string Print(const UInt32* codepoints, std::size_t count); + inline std::string Print(const std::vector& codepoints, const Settings& settings); std::string Print(const UInt32* codepoints, std::size_t count, const Settings& settings); SpirvPrinter& operator=(const SpirvPrinter&) = default; diff --git a/include/Nazara/Shader/SpirvPrinter.inl b/include/Nazara/Shader/SpirvPrinter.inl index 1435293b0..866cc096f 100644 --- a/include/Nazara/Shader/SpirvPrinter.inl +++ b/include/Nazara/Shader/SpirvPrinter.inl @@ -12,11 +12,21 @@ namespace Nz { } + inline std::string SpirvPrinter::Print(const std::vector& codepoints) + { + return Print(codepoints.data(), codepoints.size()); + } + inline std::string SpirvPrinter::Print(const UInt32* codepoints, std::size_t count) { Settings settings; return Print(codepoints, count, settings); } + + inline std::string SpirvPrinter::Print(const std::vector& codepoints, const Settings& settings) + { + return Print(codepoints.data(), codepoints.size(), settings); + } } #include diff --git a/include/Nazara/Shader/SpirvSection.hpp b/include/Nazara/Shader/SpirvSection.hpp index b759cbe2e..498b4ec68 100644 --- a/include/Nazara/Shader/SpirvSection.hpp +++ b/include/Nazara/Shader/SpirvSection.hpp @@ -8,64 +8,25 @@ #define NAZARA_SPIRVSECTION_HPP #include -#include -#include -#include -#include +#include namespace Nz { - class NAZARA_SHADER_API SpirvSection + class NAZARA_SHADER_API SpirvSection : public SpirvSectionBase { public: - struct OpSize; - struct Raw; - SpirvSection() = default; SpirvSection(const SpirvSection&) = default; SpirvSection(SpirvSection&&) = default; ~SpirvSection() = default; - inline std::size_t Append(const char* str); - inline std::size_t Append(const std::string_view& str); - inline std::size_t Append(const std::string& str); - inline std::size_t Append(UInt32 value); - inline std::size_t Append(SpirvOp opcode, const OpSize& wordCount); - std::size_t Append(const Raw& raw); - inline std::size_t Append(std::initializer_list codepoints); - template std::size_t Append(SpirvOp opcode, const Args&... args); - template std::size_t AppendVariadic(SpirvOp opcode, F&& callback); - inline std::size_t Append(const SpirvSection& section); - template || std::is_enum_v>> std::size_t Append(T value); - - inline unsigned int CountWord(const char* str); - inline unsigned int CountWord(const std::string_view& str); - inline unsigned int CountWord(const std::string& str); - inline unsigned int CountWord(const Raw& raw); - template || std::is_enum_v>> unsigned int CountWord(const T& value); - template unsigned int CountWord(const T1& value, const T2& value2, const Args&... rest); - - inline const std::vector& GetBytecode() const; - inline std::size_t GetOutputOffset() const; + using SpirvSectionBase::Append; + using SpirvSectionBase::AppendRaw; + using SpirvSectionBase::AppendSection; + using SpirvSectionBase::AppendVariadic; SpirvSection& operator=(const SpirvSection&) = delete; SpirvSection& operator=(SpirvSection&&) = default; - - struct OpSize - { - unsigned int wc; - }; - - struct Raw - { - const void* ptr; - std::size_t size; - }; - - static inline UInt32 BuildOpcode(SpirvOp opcode, unsigned int wordCount); - - private: - std::vector m_bytecode; }; } diff --git a/include/Nazara/Shader/SpirvSection.inl b/include/Nazara/Shader/SpirvSection.inl index e6a400d06..941659162 100644 --- a/include/Nazara/Shader/SpirvSection.inl +++ b/include/Nazara/Shader/SpirvSection.inl @@ -7,151 +7,6 @@ namespace Nz { - inline std::size_t SpirvSection::Append(const char* str) - { - return Append(std::string_view(str)); - } - - inline std::size_t SpirvSection::Append(const std::string_view& str) - { - std::size_t offset = GetOutputOffset(); - - std::size_t size4 = CountWord(str); - for (std::size_t i = 0; i < size4; ++i) - { - UInt32 codepoint = 0; - for (std::size_t j = 0; j < 4; ++j) - { - std::size_t pos = i * 4 + j; - if (pos < str.size()) - codepoint |= UInt32(str[pos]) << (j * 8); - } - - Append(codepoint); - } - - return offset; - } - - inline std::size_t SpirvSection::Append(const std::string& str) - { - return Append(std::string_view(str)); - } - - inline std::size_t SpirvSection::Append(UInt32 value) - { - std::size_t offset = GetOutputOffset(); - m_bytecode.push_back(value); - - return offset; - } - - inline std::size_t SpirvSection::Append(SpirvOp opcode, const OpSize& wordCount) - { - return Append(BuildOpcode(opcode, wordCount.wc)); - } - - inline std::size_t SpirvSection::Append(std::initializer_list codepoints) - { - std::size_t offset = GetOutputOffset(); - - for (UInt32 cp : codepoints) - Append(cp); - - return offset; - } - - inline std::size_t SpirvSection::Append(const SpirvSection& section) - { - const std::vector& bytecode = section.GetBytecode(); - - std::size_t offset = GetOutputOffset(); - m_bytecode.resize(offset + bytecode.size()); - std::copy(bytecode.begin(), bytecode.end(), m_bytecode.begin() + offset); - - return offset; - } - - template - std::size_t SpirvSection::Append(SpirvOp opcode, const Args&... args) - { - unsigned int wordCount = 1 + (CountWord(args) + ... + 0); - std::size_t offset = Append(opcode, OpSize{ wordCount }); - if constexpr (sizeof...(args) > 0) - (Append(args), ...); - - return offset; - } - - template std::size_t SpirvSection::AppendVariadic(SpirvOp opcode, F&& callback) - { - std::size_t offset = Append(0); //< Will be filled later - - unsigned int wordCount = 1; - auto appendFunctor = [&](const auto& value) - { - wordCount += CountWord(value); - Append(value); - }; - callback(appendFunctor); - - m_bytecode[offset] = BuildOpcode(opcode, wordCount); - - return offset; - } - - template - std::size_t SpirvSection::Append(T value) - { - return Append(static_cast(value)); - } - - template - unsigned int SpirvSection::CountWord(const T& /*value*/) - { - return 1; - } - - template - unsigned int SpirvSection::CountWord(const T1& value, const T2& value2, const Args&... rest) - { - return CountWord(value) + CountWord(value2) + (CountWord(rest) + ...); - } - - inline unsigned int SpirvSection::CountWord(const char* str) - { - return CountWord(std::string_view(str)); - } - - inline unsigned int Nz::SpirvSection::CountWord(const std::string& str) - { - return CountWord(std::string_view(str)); - } - - inline unsigned int SpirvSection::CountWord(const Raw& raw) - { - return static_cast((raw.size + sizeof(UInt32) - 1) / sizeof(UInt32)); - } - - inline unsigned int SpirvSection::CountWord(const std::string_view& str) - { - return (static_cast(str.size() + 1) + sizeof(UInt32) - 1) / sizeof(UInt32); //< + 1 for null character - } - - inline const std::vector& SpirvSection::GetBytecode() const - { - return m_bytecode; - } - - inline std::size_t SpirvSection::GetOutputOffset() const - { - return m_bytecode.size(); - } - - inline UInt32 SpirvSection::BuildOpcode(SpirvOp opcode, unsigned int wordCount) - { - return UInt32(opcode) | UInt32(wordCount) << 16; - } } #include diff --git a/include/Nazara/Shader/SpirvSectionBase.hpp b/include/Nazara/Shader/SpirvSectionBase.hpp new file mode 100644 index 000000000..4783fd80b --- /dev/null +++ b/include/Nazara/Shader/SpirvSectionBase.hpp @@ -0,0 +1,75 @@ +// 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_SPIRVSECTIONBASE_HPP +#define NAZARA_SPIRVSECTIONBASE_HPP + +#include +#include +#include +#include +#include + +namespace Nz +{ + class NAZARA_SHADER_API SpirvSectionBase + { + public: + struct OpSize; + struct Raw; + + SpirvSectionBase() = default; + SpirvSectionBase(const SpirvSectionBase&) = default; + SpirvSectionBase(SpirvSectionBase&&) = default; + ~SpirvSectionBase() = default; + + inline const std::vector& GetBytecode() const; + inline std::size_t GetOutputOffset() const; + + SpirvSectionBase& operator=(const SpirvSectionBase&) = delete; + SpirvSectionBase& operator=(SpirvSectionBase&&) = default; + + struct OpSize + { + unsigned int wc; + }; + + struct Raw + { + const void* ptr; + std::size_t size; + }; + + static inline UInt32 BuildOpcode(SpirvOp opcode, unsigned int wordCount); + + protected: + inline std::size_t Append(SpirvOp opcode, const OpSize& wordCount); + template std::size_t Append(SpirvOp opcode, const Args&... args); + template std::size_t AppendVariadic(SpirvOp opcode, F&& callback); + inline std::size_t AppendRaw(const char* str); + inline std::size_t AppendRaw(const std::string_view& str); + inline std::size_t AppendRaw(const std::string& str); + inline std::size_t AppendRaw(UInt32 value); + std::size_t AppendRaw(const Raw& raw); + inline std::size_t AppendRaw(std::initializer_list codepoints); + inline std::size_t AppendSection(const SpirvSectionBase& section); + template || std::is_enum_v>> std::size_t AppendRaw(T value); + + inline unsigned int CountWord(const char* str); + inline unsigned int CountWord(const std::string_view& str); + inline unsigned int CountWord(const std::string& str); + inline unsigned int CountWord(const Raw& raw); + template || std::is_enum_v>> unsigned int CountWord(const T& value); + template unsigned int CountWord(const T1& value, const T2& value2, const Args&... rest); + + private: + std::vector m_bytecode; + }; +} + +#include + +#endif diff --git a/include/Nazara/Shader/SpirvSectionBase.inl b/include/Nazara/Shader/SpirvSectionBase.inl new file mode 100644 index 000000000..760bfea6b --- /dev/null +++ b/include/Nazara/Shader/SpirvSectionBase.inl @@ -0,0 +1,157 @@ +// 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 +#include + +namespace Nz +{ + inline std::size_t SpirvSectionBase::Append(SpirvOp opcode, const OpSize& wordCount) + { + return AppendRaw(BuildOpcode(opcode, wordCount.wc)); + } + + template + std::size_t SpirvSectionBase::Append(SpirvOp opcode, const Args&... args) + { + unsigned int wordCount = 1 + (CountWord(args) + ... + 0); + std::size_t offset = Append(opcode, OpSize{ wordCount }); + if constexpr (sizeof...(args) > 0) + (AppendRaw(args), ...); + + return offset; + } + + template std::size_t SpirvSectionBase::AppendVariadic(SpirvOp opcode, F&& callback) + { + std::size_t offset = AppendRaw(0); //< Will be filled later + + unsigned int wordCount = 1; + auto appendFunctor = [&](const auto& value) + { + wordCount += CountWord(value); + AppendRaw(value); + }; + callback(appendFunctor); + + m_bytecode[offset] = BuildOpcode(opcode, wordCount); + + return offset; + } + + inline std::size_t SpirvSectionBase::AppendRaw(const char* str) + { + return AppendRaw(std::string_view(str)); + } + + inline std::size_t SpirvSectionBase::AppendRaw(const std::string_view& str) + { + std::size_t offset = GetOutputOffset(); + + std::size_t size4 = CountWord(str); + for (std::size_t i = 0; i < size4; ++i) + { + UInt32 codepoint = 0; + for (std::size_t j = 0; j < 4; ++j) + { + std::size_t pos = i * 4 + j; + if (pos < str.size()) + codepoint |= UInt32(str[pos]) << (j * 8); + } + + AppendRaw(codepoint); + } + + return offset; + } + + inline std::size_t SpirvSectionBase::AppendRaw(const std::string& str) + { + return AppendRaw(std::string_view(str)); + } + + inline std::size_t SpirvSectionBase::AppendRaw(UInt32 value) + { + std::size_t offset = GetOutputOffset(); + m_bytecode.push_back(value); + + return offset; + } + + inline std::size_t SpirvSectionBase::AppendRaw(std::initializer_list codepoints) + { + std::size_t offset = GetOutputOffset(); + + for (UInt32 cp : codepoints) + AppendRaw(cp); + + return offset; + } + + inline std::size_t SpirvSectionBase::AppendSection(const SpirvSectionBase& section) + { + const std::vector& bytecode = section.GetBytecode(); + + std::size_t offset = GetOutputOffset(); + m_bytecode.resize(offset + bytecode.size()); + std::copy(bytecode.begin(), bytecode.end(), m_bytecode.begin() + offset); + + return offset; + } + + template + std::size_t SpirvSectionBase::AppendRaw(T value) + { + return AppendRaw(static_cast(value)); + } + + template + unsigned int SpirvSectionBase::CountWord(const T& /*value*/) + { + return 1; + } + + template + unsigned int SpirvSectionBase::CountWord(const T1& value, const T2& value2, const Args&... rest) + { + return CountWord(value) + CountWord(value2) + (CountWord(rest) + ...); + } + + inline unsigned int SpirvSectionBase::CountWord(const char* str) + { + return CountWord(std::string_view(str)); + } + + inline unsigned int Nz::SpirvSectionBase::CountWord(const std::string& str) + { + return CountWord(std::string_view(str)); + } + + inline unsigned int SpirvSectionBase::CountWord(const Raw& raw) + { + return static_cast((raw.size + sizeof(UInt32) - 1) / sizeof(UInt32)); + } + + inline unsigned int SpirvSectionBase::CountWord(const std::string_view& str) + { + return (static_cast(str.size() + 1) + sizeof(UInt32) - 1) / sizeof(UInt32); //< + 1 for null character + } + + inline const std::vector& SpirvSectionBase::GetBytecode() const + { + return m_bytecode; + } + + inline std::size_t SpirvSectionBase::GetOutputOffset() const + { + return m_bytecode.size(); + } + + inline UInt32 SpirvSectionBase::BuildOpcode(SpirvOp opcode, unsigned int wordCount) + { + return UInt32(opcode) | UInt32(wordCount) << 16; + } +} + +#include diff --git a/include/Nazara/Shader/SpirvWriter.hpp b/include/Nazara/Shader/SpirvWriter.hpp index 37ebc6ea0..eeaee1e60 100644 --- a/include/Nazara/Shader/SpirvWriter.hpp +++ b/include/Nazara/Shader/SpirvWriter.hpp @@ -57,6 +57,8 @@ namespace Nz void AppendHeader(); + SpirvConstantCache::Function BuildFunctionType(ShaderExpressionType retType, const std::vector& parameters); + UInt32 GetConstantId(const ShaderConstantValue& value) const; UInt32 GetFunctionTypeId(ShaderExpressionType retType, const std::vector& parameters); const ExtVar& GetBuiltinVariable(ShaderNodes::BuiltinEntry builtin) const; @@ -72,6 +74,8 @@ namespace Nz std::optional ReadInputVariable(const std::string& name, OnlyCache); UInt32 ReadLocalVariable(const std::string& name); std::optional ReadLocalVariable(const std::string& name, OnlyCache); + UInt32 ReadParameterVariable(const std::string& name); + std::optional ReadParameterVariable(const std::string& name, OnlyCache); UInt32 ReadUniformVariable(const std::string& name); std::optional ReadUniformVariable(const std::string& name, OnlyCache); UInt32 ReadVariable(ExtVar& var); @@ -89,8 +93,8 @@ namespace Nz struct Context { const ShaderAst* shader = nullptr; - const ShaderAst::Function* currentFunction = nullptr; const States* states = nullptr; + std::vector functionBlocks; }; struct ExtVar diff --git a/src/Nazara/Shader/GlslWriter.cpp b/src/Nazara/Shader/GlslWriter.cpp index f78896a3c..1920bf291 100644 --- a/src/Nazara/Shader/GlslWriter.cpp +++ b/src/Nazara/Shader/GlslWriter.cpp @@ -608,6 +608,18 @@ namespace Nz Append(var.name); } + void GlslWriter::Visit(ShaderNodes::ReturnStatement& node) + { + if (node.returnExpr) + { + Append("return "); + Visit(node.returnExpr); + Append(";"); + } + else + Append("return;"); + } + void GlslWriter::Visit(ShaderNodes::OutputVariable& var) { Append(var.name); diff --git a/src/Nazara/Shader/ShaderAst.cpp b/src/Nazara/Shader/ShaderAst.cpp index 2f43ee23b..ff84cfa55 100644 --- a/src/Nazara/Shader/ShaderAst.cpp +++ b/src/Nazara/Shader/ShaderAst.cpp @@ -13,7 +13,7 @@ namespace Nz conditionEntry.name = std::move(name); } - void ShaderAst::AddFunction(std::string name, ShaderNodes::StatementPtr statement, std::vector parameters, ShaderNodes::BasicType returnType) + void ShaderAst::AddFunction(std::string name, ShaderNodes::StatementPtr statement, std::vector parameters, ShaderExpressionType returnType) { auto& functionEntry = m_functions.emplace_back(); functionEntry.name = std::move(name); diff --git a/src/Nazara/Shader/ShaderAstCloner.cpp b/src/Nazara/Shader/ShaderAstCloner.cpp index ebbcfa560..1118029df 100644 --- a/src/Nazara/Shader/ShaderAstCloner.cpp +++ b/src/Nazara/Shader/ShaderAstCloner.cpp @@ -142,6 +142,11 @@ namespace Nz PushStatement(ShaderNodes::NoOp::Build()); } + void ShaderAstCloner::Visit(ShaderNodes::ReturnStatement& node) + { + PushStatement(ShaderNodes::ReturnStatement::Build(CloneExpression(node.returnExpr))); + } + void ShaderAstCloner::Visit(ShaderNodes::Sample2D& node) { PushExpression(ShaderNodes::Sample2D::Build(CloneExpression(node.sampler), CloneExpression(node.coordinates))); diff --git a/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp b/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp index d3b404011..f4d858d91 100644 --- a/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp +++ b/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp @@ -95,6 +95,12 @@ namespace Nz /* Nothing to do */ } + void ShaderAstRecursiveVisitor::Visit(ShaderNodes::ReturnStatement& node) + { + if (node.returnExpr) + Visit(node.returnExpr); + } + void ShaderAstRecursiveVisitor::Visit(ShaderNodes::Sample2D& node) { Visit(node.sampler); diff --git a/src/Nazara/Shader/ShaderAstSerializer.cpp b/src/Nazara/Shader/ShaderAstSerializer.cpp index b998d8637..13780339b 100644 --- a/src/Nazara/Shader/ShaderAstSerializer.cpp +++ b/src/Nazara/Shader/ShaderAstSerializer.cpp @@ -92,6 +92,11 @@ namespace Nz Serialize(node); } + void Visit(ShaderNodes::ReturnStatement& node) override + { + Serialize(node); + } + void Visit(ShaderNodes::Sample2D& node) override { Serialize(node); @@ -286,6 +291,11 @@ namespace Nz /* Nothing to do */ } + void ShaderAstSerializerBase::Serialize(ShaderNodes::ReturnStatement& node) + { + Node(node.returnExpr); + } + void ShaderAstSerializerBase::Serialize(ShaderNodes::Sample2D& node) { Node(node.sampler); @@ -391,7 +401,8 @@ namespace Nz m_stream << UInt32(shader.GetFunctionCount()); for (const auto& func : shader.GetFunctions()) { - m_stream << func.name << UInt32(func.returnType); + m_stream << func.name; + SerializeType(func.returnType); m_stream << UInt32(func.parameters.size()); for (const auto& param : func.parameters) @@ -634,11 +645,12 @@ namespace Nz for (UInt32 i = 0; i < funcCount; ++i) { std::string name; - ShaderNodes::BasicType retType; + ShaderExpressionType retType; std::vector parameters; Value(name); - Enum(retType); + Type(retType); + Container(parameters); for (auto& param : parameters) { @@ -653,7 +665,7 @@ namespace Nz ShaderNodes::StatementPtr statement = std::static_pointer_cast(node); - shader.AddFunction(std::move(name), std::move(statement), std::move(parameters), retType); + shader.AddFunction(std::move(name), std::move(statement), std::move(parameters), std::move(retType)); } return shader; @@ -693,6 +705,7 @@ namespace Nz HandleType(Identifier); HandleType(IntrinsicCall); HandleType(NoOp); + HandleType(ReturnStatement); HandleType(Sample2D); HandleType(SwizzleOp); HandleType(StatementBlock); diff --git a/src/Nazara/Shader/ShaderAstValidator.cpp b/src/Nazara/Shader/ShaderAstValidator.cpp index ec2d9a7d7..f081d7481 100644 --- a/src/Nazara/Shader/ShaderAstValidator.cpp +++ b/src/Nazara/Shader/ShaderAstValidator.cpp @@ -349,6 +349,22 @@ namespace Nz ShaderAstRecursiveVisitor::Visit(node); } + void ShaderAstValidator::Visit(ShaderNodes::ReturnStatement& node) + { + if (m_context->currentFunction->returnType != ShaderExpressionType(ShaderNodes::BasicType::Void)) + { + if (MandatoryExpr(node.returnExpr)->GetExpressionType() != m_context->currentFunction->returnType) + throw AstError{ "Return type doesn't match function return type" }; + } + else + { + if (node.returnExpr) + throw AstError{ "Unexpected expression for return (function doesn't return)" }; + } + + ShaderAstRecursiveVisitor::Visit(node); + } + void ShaderAstValidator::Visit(ShaderNodes::Sample2D& node) { if (MandatoryExpr(node.sampler)->GetExpressionType() != ShaderExpressionType{ ShaderNodes::BasicType::Sampler2D }) diff --git a/src/Nazara/Shader/ShaderAstVisitorExcept.cpp b/src/Nazara/Shader/ShaderAstVisitorExcept.cpp index 7843281d4..b8f8c7d16 100644 --- a/src/Nazara/Shader/ShaderAstVisitorExcept.cpp +++ b/src/Nazara/Shader/ShaderAstVisitorExcept.cpp @@ -78,6 +78,11 @@ namespace Nz throw std::runtime_error("unhandled NoOp node"); } + void ShaderAstVisitorExcept::Visit(ShaderNodes::ReturnStatement& node) + { + throw std::runtime_error("unhandled ReturnStatement node"); + } + void ShaderAstVisitorExcept::Visit(ShaderNodes::Sample2D& /*node*/) { throw std::runtime_error("unhandled Sample2D node"); diff --git a/src/Nazara/Shader/ShaderLangLexer.cpp b/src/Nazara/Shader/ShaderLangLexer.cpp index a93cefa85..8782a54fb 100644 --- a/src/Nazara/Shader/ShaderLangLexer.cpp +++ b/src/Nazara/Shader/ShaderLangLexer.cpp @@ -103,7 +103,7 @@ namespace Nz::ShaderLang break; } - tokenType = TokenType::Subtract; + tokenType = TokenType::Minus; break; } @@ -193,7 +193,7 @@ namespace Nz::ShaderLang char* end; double value = std::strtod(valueStr.c_str(), &end); - if (end != &str[currentPos]) + if (end != &str[currentPos + 1]) throw BadNumber{}; token.data = value; @@ -204,7 +204,7 @@ namespace Nz::ShaderLang long long value; std::from_chars_result r = std::from_chars(&str[start], &str[currentPos + 1], value); - if (r.ptr != &str[currentPos]) + if (r.ptr != &str[currentPos + 1]) { if (r.ec == std::errc::result_out_of_range) throw NumberOutOfRange{}; @@ -218,7 +218,7 @@ namespace Nz::ShaderLang break; } - case '+': tokenType = TokenType::Add; break; + case '+': tokenType = TokenType::Plus; break; case '*': tokenType = TokenType::Multiply; break; case ':': tokenType = TokenType::Colon; break; case ';': tokenType = TokenType::Semicolon; break; diff --git a/src/Nazara/Shader/ShaderLangParser.cpp b/src/Nazara/Shader/ShaderLangParser.cpp index 482afd007..cea55ee2e 100644 --- a/src/Nazara/Shader/ShaderLangParser.cpp +++ b/src/Nazara/Shader/ShaderLangParser.cpp @@ -8,7 +8,33 @@ namespace Nz::ShaderLang { - void Parser::Parse(const std::vector& tokens) + namespace + { + std::unordered_map identifierToBasicType = { + { "bool", ShaderNodes::BasicType::Boolean }, + + { "i32", ShaderNodes::BasicType::Int1 }, + { "vec2i32", ShaderNodes::BasicType::Int2 }, + { "vec3i32", ShaderNodes::BasicType::Int3 }, + { "vec4i32", ShaderNodes::BasicType::Int4 }, + + { "f32", ShaderNodes::BasicType::Float1 }, + { "vec2f32", ShaderNodes::BasicType::Float2 }, + { "vec3f32", ShaderNodes::BasicType::Float3 }, + { "vec4f32", ShaderNodes::BasicType::Float4 }, + + { "mat4x4f32", ShaderNodes::BasicType::Mat4x4 }, + { "sampler2D", ShaderNodes::BasicType::Sampler2D }, + { "void", ShaderNodes::BasicType::Void }, + + { "u32", ShaderNodes::BasicType::UInt1 }, + { "vec2u32", ShaderNodes::BasicType::UInt3 }, + { "vec3u32", ShaderNodes::BasicType::UInt3 }, + { "vec4u32", ShaderNodes::BasicType::UInt4 }, + }; + } + + ShaderAst Parser::Parse(const std::vector& tokens) { Context context; context.tokenCount = tokens.size(); @@ -16,18 +42,28 @@ namespace Nz::ShaderLang m_context = &context; - for (const Token& token : tokens) + m_context->tokenIndex = -1; + + bool reachedEndOfStream = false; + while (!reachedEndOfStream) { - switch (token.type) + const Token& nextToken = PeekNext(); + switch (nextToken.type) { case TokenType::FunctionDeclaration: ParseFunctionDeclaration(); break; + case TokenType::EndOfStream: + reachedEndOfStream = true; + break; + default: throw UnexpectedToken{}; } } + + return std::move(context.result); } const Token& Parser::Advance() @@ -42,24 +78,34 @@ namespace Nz::ShaderLang throw ExpectedToken{}; } - void Parser::ExpectNext(TokenType type) + const Token& Parser::ExpectNext(TokenType type) { - Expect(m_context->tokens[m_context->tokenIndex + 1], type); + const Token& token = Advance(); + Expect(token, type); + + return token; } - void Parser::ParseFunctionBody() + const Token& Parser::PeekNext() { + assert(m_context->tokenIndex + 1 < m_context->tokenCount); + return m_context->tokens[m_context->tokenIndex + 1]; + } + ShaderNodes::StatementPtr Parser::ParseFunctionBody() + { + return ParseStatementList(); } void Parser::ParseFunctionDeclaration() { - ExpectNext(TokenType::Identifier); + ExpectNext(TokenType::FunctionDeclaration); - std::string functionName = std::get(Advance().data); + std::string functionName = ParseIdentifierAsName(); ExpectNext(TokenType::OpenParenthesis); - Advance(); + + std::vector parameters; bool firstParameter = true; for (;;) @@ -74,45 +120,192 @@ namespace Nz::ShaderLang Advance(); } - ParseFunctionParameter(); + parameters.push_back(ParseFunctionParameter()); firstParameter = false; } ExpectNext(TokenType::ClosingParenthesis); - Advance(); + ShaderExpressionType returnType = ShaderNodes::BasicType::Void; if (PeekNext().type == TokenType::FunctionReturn) { - Advance(); + Advance(); //< Consume -> - std::string returnType = std::get(Advance().data); + returnType = ParseIdentifierAsType(); } - ExpectNext(TokenType::OpenCurlyBracket); - Advance(); - ParseFunctionBody(); + ShaderNodes::StatementPtr functionBody = ParseFunctionBody(); ExpectNext(TokenType::ClosingCurlyBracket); - Advance(); + + m_context->result.AddFunction(functionName, functionBody, std::move(parameters), returnType); } - void Parser::ParseFunctionParameter() + ShaderAst::FunctionParameter Parser::ParseFunctionParameter() { - ExpectNext(TokenType::Identifier); - std::string parameterName = std::get(Advance().data); + std::string parameterName = ParseIdentifierAsName(); ExpectNext(TokenType::Colon); - Advance(); - ExpectNext(TokenType::Identifier); - std::string parameterType = std::get(Advance().data); + ShaderExpressionType parameterType = ParseIdentifierAsType(); + + return { parameterName, parameterType }; } - const Token& Parser::PeekNext() + ShaderNodes::StatementPtr Parser::ParseReturnStatement() { - assert(m_context->tokenIndex + 1 < m_context->tokenCount); - return m_context->tokens[m_context->tokenIndex + 1]; + ExpectNext(TokenType::Return); + + ShaderNodes::ExpressionPtr expr; + if (PeekNext().type != TokenType::Semicolon) + expr = ParseExpression(); + + return ShaderNodes::ReturnStatement::Build(std::move(expr)); + } + + ShaderNodes::StatementPtr Parser::ParseStatement() + { + const Token& token = PeekNext(); + + ShaderNodes::StatementPtr statement; + switch (token.type) + { + case TokenType::Return: + statement = ParseReturnStatement(); + break; + + default: + break; + } + + ExpectNext(TokenType::Semicolon); + + return statement; + } + + ShaderNodes::StatementPtr Parser::ParseStatementList() + { + std::vector statements; + while (PeekNext().type != TokenType::ClosingCurlyBracket) + { + statements.push_back(ParseStatement()); + } + + return ShaderNodes::StatementBlock::Build(std::move(statements)); + } + + ShaderNodes::ExpressionPtr Parser::ParseBinOpRhs(int exprPrecedence, ShaderNodes::ExpressionPtr lhs) + { + for (;;) + { + const Token& currentOp = PeekNext(); + + int tokenPrecedence = GetTokenPrecedence(currentOp.type); + if (tokenPrecedence < exprPrecedence) + return lhs; + + Advance(); + ShaderNodes::ExpressionPtr rhs = ParsePrimaryExpression(); + + const Token& nextOp = PeekNext(); + + int nextTokenPrecedence = GetTokenPrecedence(nextOp.type); + if (tokenPrecedence < nextTokenPrecedence) + rhs = ParseBinOpRhs(tokenPrecedence + 1, std::move(rhs)); + + ShaderNodes::BinaryType binaryType; + { + switch (currentOp.type) + { + case TokenType::Plus: binaryType = ShaderNodes::BinaryType::Add; break; + case TokenType::Minus: binaryType = ShaderNodes::BinaryType::Subtract; break; + case TokenType::Multiply: binaryType = ShaderNodes::BinaryType::Multiply; break; + case TokenType::Divide: binaryType = ShaderNodes::BinaryType::Divide; break; + default: throw UnexpectedToken{}; + } + } + + + lhs = ShaderNodes::BinaryOp::Build(binaryType, std::move(lhs), std::move(rhs)); + } + } + + ShaderNodes::ExpressionPtr Parser::ParseExpression() + { + return ParseBinOpRhs(0, ParsePrimaryExpression()); + } + + ShaderNodes::ExpressionPtr Parser::ParseIdentifier() + { + const Token& identifier = ExpectNext(TokenType::Identifier); + + return ShaderNodes::Identifier::Build(ShaderNodes::ParameterVariable::Build(std::get(identifier.data), ShaderNodes::BasicType::Float3)); + } + + ShaderNodes::ExpressionPtr Parser::ParseIntegerExpression() + { + const Token& integer = ExpectNext(TokenType::IntegerValue); + return ShaderNodes::Constant::Build(static_cast(std::get(integer.data))); + } + + ShaderNodes::ExpressionPtr Parser::ParseParenthesisExpression() + { + ExpectNext(TokenType::OpenParenthesis); + ShaderNodes::ExpressionPtr expression = ParseExpression(); + ExpectNext(TokenType::ClosingParenthesis); + + return expression; + } + + ShaderNodes::ExpressionPtr Parser::ParsePrimaryExpression() + { + const Token& token = PeekNext(); + switch (token.type) + { + case TokenType::BoolFalse: return ShaderNodes::Constant::Build(false); + case TokenType::BoolTrue: return ShaderNodes::Constant::Build(true); + case TokenType::Identifier: return ParseIdentifier(); + case TokenType::IntegerValue: return ParseIntegerExpression(); + case TokenType::OpenParenthesis: return ParseParenthesisExpression(); + default: throw UnexpectedToken{}; + } + } + + std::string Parser::ParseIdentifierAsName() + { + const Token& identifierToken = ExpectNext(TokenType::Identifier); + + std::string identifier = std::get(identifierToken.data); + + auto it = identifierToBasicType.find(identifier); + if (it != identifierToBasicType.end()) + throw ReservedKeyword{}; + + return identifier; + } + + ShaderExpressionType Parser::ParseIdentifierAsType() + { + const Token& identifier = ExpectNext(TokenType::Identifier); + + auto it = identifierToBasicType.find(std::get(identifier.data)); + if (it == identifierToBasicType.end()) + throw UnknownType{}; + + return it->second; + } + + int Parser::GetTokenPrecedence(TokenType token) + { + switch (token) + { + case TokenType::Plus: return 20; + case TokenType::Divide: return 40; + case TokenType::Multiply: return 40; + case TokenType::Minus: return 20; + default: return -1; + } } } diff --git a/src/Nazara/Shader/ShaderNodes.cpp b/src/Nazara/Shader/ShaderNodes.cpp index 0e617297a..97a21506b 100644 --- a/src/Nazara/Shader/ShaderNodes.cpp +++ b/src/Nazara/Shader/ShaderNodes.cpp @@ -69,6 +69,11 @@ namespace Nz::ShaderNodes visitor.Visit(*this); } + void ReturnStatement::Visit(ShaderAstVisitor& visitor) + { + visitor.Visit(*this); + } + ShaderExpressionType AssignOp::GetExpressionType() const { return left->GetExpressionType(); diff --git a/src/Nazara/Shader/SpirvAstVisitor.cpp b/src/Nazara/Shader/SpirvAstVisitor.cpp index fee8b7d2e..688648e70 100644 --- a/src/Nazara/Shader/SpirvAstVisitor.cpp +++ b/src/Nazara/Shader/SpirvAstVisitor.cpp @@ -611,6 +611,14 @@ namespace Nz // nothing to do } + void SpirvAstVisitor::Visit(ShaderNodes::ReturnStatement& node) + { + if (node.returnExpr) + m_currentBlock->Append(SpirvOp::OpReturnValue, EvaluateExpression(node.returnExpr)); + else + m_currentBlock->Append(SpirvOp::OpReturn); + } + void SpirvAstVisitor::Visit(ShaderNodes::Sample2D& node) { UInt32 typeId = m_writer.GetTypeId(ShaderNodes::BasicType::Float4); diff --git a/src/Nazara/Shader/SpirvConstantCache.cpp b/src/Nazara/Shader/SpirvConstantCache.cpp index e764cbf49..fd27b2dc6 100644 --- a/src/Nazara/Shader/SpirvConstantCache.cpp +++ b/src/Nazara/Shader/SpirvConstantCache.cpp @@ -18,6 +18,7 @@ namespace Nz template overloaded(Ts...)->overloaded; } + struct SpirvConstantCache::Eq { bool Compare(const ConstantBool& lhs, const ConstantBool& rhs) const @@ -353,6 +354,12 @@ namespace Nz }, v); } + void Register(const std::vector& lhs) + { + for (std::size_t i = 0; i < lhs.size(); ++i) + cache.Register(*lhs[i]); + } + template void Register(const std::vector& lhs) { diff --git a/src/Nazara/Shader/SpirvExpressionLoad.cpp b/src/Nazara/Shader/SpirvExpressionLoad.cpp index 93af139e0..caddbec43 100644 --- a/src/Nazara/Shader/SpirvExpressionLoad.cpp +++ b/src/Nazara/Shader/SpirvExpressionLoad.cpp @@ -109,6 +109,11 @@ namespace Nz m_value = Value{ m_writer.ReadLocalVariable(var.name) }; } + void SpirvExpressionLoad::Visit(ShaderNodes::ParameterVariable& var) + { + m_value = Value{ m_writer.ReadParameterVariable(var.name) }; + } + void SpirvExpressionLoad::Visit(ShaderNodes::UniformVariable& var) { auto uniformVar = m_writer.GetUniformVariable(var.name); diff --git a/src/Nazara/Shader/SpirvSection.cpp b/src/Nazara/Shader/SpirvSectionBase.cpp similarity index 85% rename from src/Nazara/Shader/SpirvSection.cpp rename to src/Nazara/Shader/SpirvSectionBase.cpp index c3d62ade3..9451e93db 100644 --- a/src/Nazara/Shader/SpirvSection.cpp +++ b/src/Nazara/Shader/SpirvSectionBase.cpp @@ -2,13 +2,13 @@ // This file is part of the "Nazara Engine - Shader generator" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include #include namespace Nz { - std::size_t SpirvSection::Append(const Raw& raw) + std::size_t SpirvSectionBase::AppendRaw(const Raw& raw) { std::size_t offset = GetOutputOffset(); @@ -30,7 +30,7 @@ namespace Nz codepoint |= UInt32(ptr[pos]) << (j * 8); } - Append(codepoint); + AppendRaw(codepoint); } return offset; diff --git a/src/Nazara/Shader/SpirvWriter.cpp b/src/Nazara/Shader/SpirvWriter.cpp index bdc4c12f3..6316e42ee 100644 --- a/src/Nazara/Shader/SpirvWriter.cpp +++ b/src/Nazara/Shader/SpirvWriter.cpp @@ -191,16 +191,17 @@ namespace Nz { UInt32 typeId; UInt32 id; - std::vector paramsId; }; tsl::ordered_map inputIds; tsl::ordered_map outputIds; + tsl::ordered_map parameterIds; tsl::ordered_map uniformIds; std::unordered_map extensionInstructions; std::unordered_map builtinIds; std::unordered_map varToResult; std::vector funcs; + std::vector functionBlocks; std::vector resultIds; UInt32 nextVarIndex = 1; SpirvConstantCache constantTypeCache; //< init after nextVarIndex @@ -307,7 +308,7 @@ namespace Nz builtinData.typeId = GetTypeId(builtinType); builtinData.varId = varId; - state.annotations.Append(SpirvOp::OpDecorate, builtinData.varId, SpvDecorationBuiltIn, builtinDecoration); + state.annotations.Append(SpirvOp::OpDecorate, builtinData.varId, SpirvDecoration::BuiltIn, builtinDecoration); state.builtinIds.emplace(builtin->entry, builtinData); } @@ -329,7 +330,7 @@ namespace Nz state.inputIds.emplace(input.name, std::move(inputData)); if (input.locationIndex) - state.annotations.Append(SpirvOp::OpDecorate, varId, SpvDecorationLocation, *input.locationIndex); + state.annotations.Append(SpirvOp::OpDecorate, varId, SpirvDecoration::Location, *input.locationIndex); } for (const auto& output : shader.GetOutputs()) @@ -349,7 +350,7 @@ namespace Nz state.outputIds.emplace(output.name, std::move(outputData)); if (output.locationIndex) - state.annotations.Append(SpirvOp::OpDecorate, varId, SpvDecorationLocation, *output.locationIndex); + state.annotations.Append(SpirvOp::OpDecorate, varId, SpirvDecoration::Location, *output.locationIndex); } for (const auto& uniform : shader.GetUniforms()) @@ -370,8 +371,8 @@ namespace Nz if (uniform.bindingIndex) { - state.annotations.Append(SpirvOp::OpDecorate, varId, SpvDecorationBinding, *uniform.bindingIndex); - state.annotations.Append(SpirvOp::OpDecorate, varId, SpvDecorationDescriptorSet, 0); + state.annotations.Append(SpirvOp::OpDecorate, varId, SpirvDecoration::Binding, *uniform.bindingIndex); + state.annotations.Append(SpirvOp::OpDecorate, varId, SpirvDecoration::DescriptorSet, 0); } } @@ -396,77 +397,86 @@ namespace Nz state.instructions.Append(SpirvOp::OpFunction, GetTypeId(func.returnType), funcData.id, 0, funcData.typeId); - std::vector blocks; - blocks.emplace_back(*this); + state.functionBlocks.clear(); + state.functionBlocks.emplace_back(*this); + + state.parameterIds.clear(); for (const auto& param : func.parameters) { UInt32 paramResultId = AllocateResultId(); - funcData.paramsId.push_back(paramResultId); + state.instructions.Append(SpirvOp::OpFunctionParameter, GetTypeId(param.type), paramResultId); - blocks.back().Append(SpirvOp::OpFunctionParameter, GetTypeId(param.type), paramResultId); + ExtVar parameterData; + parameterData.pointerTypeId = GetPointerTypeId(param.type, SpirvStorageClass::Function); + parameterData.typeId = GetTypeId(param.type); + parameterData.varId = paramResultId; + + state.parameterIds.emplace(param.name, std::move(parameterData)); } - SpirvAstVisitor visitor(*this, blocks); + SpirvAstVisitor visitor(*this, state.functionBlocks); visitor.Visit(functionStatements[funcIndex]); - if (func.returnType == ShaderNodes::BasicType::Void) - blocks.back().Append(SpirvOp::OpReturn); - else - throw std::runtime_error("returning values from functions is not yet supported"); //< TODO + if (!state.functionBlocks.back().IsTerminated()) + { + assert(func.returnType == ShaderExpressionType(ShaderNodes::BasicType::Void)); + state.functionBlocks.back().Append(SpirvOp::OpReturn); + } - blocks.back().Append(SpirvOp::OpFunctionEnd); + for (SpirvBlock& block : state.functionBlocks) + state.instructions.AppendSection(block); - for (SpirvBlock& block : blocks) - state.instructions.Append(block); + state.instructions.Append(SpirvOp::OpFunctionEnd); } - assert(entryPointIndex != std::numeric_limits::max()); - m_currentState->constantTypeCache.Write(m_currentState->annotations, m_currentState->constants, m_currentState->debugInfo); AppendHeader(); - SpvExecutionModel execModel; - const auto& entryFuncData = shader.GetFunction(entryPointIndex); - const auto& entryFunc = state.funcs[entryPointIndex]; - - assert(m_context.shader); - switch (m_context.shader->GetStage()) + if (entryPointIndex != std::numeric_limits::max()) { - case ShaderStageType::Fragment: - execModel = SpvExecutionModelFragment; - break; + SpvExecutionModel execModel; + const auto& entryFuncData = shader.GetFunction(entryPointIndex); + const auto& entryFunc = state.funcs[entryPointIndex]; - case ShaderStageType::Vertex: - execModel = SpvExecutionModelVertex; - break; + assert(m_context.shader); + switch (m_context.shader->GetStage()) + { + case ShaderStageType::Fragment: + execModel = SpvExecutionModelFragment; + break; - default: - throw std::runtime_error("not yet implemented"); + case ShaderStageType::Vertex: + execModel = SpvExecutionModelVertex; + break; + + default: + throw std::runtime_error("not yet implemented"); + } + + // OpEntryPoint Vertex %main "main" %outNormal %inNormals %outTexCoords %inTexCoord %_ %inPos + + state.header.AppendVariadic(SpirvOp::OpEntryPoint, [&](const auto& appender) + { + appender(execModel); + appender(entryFunc.id); + appender(entryFuncData.name); + + for (const auto& [name, varData] : state.builtinIds) + appender(varData.varId); + + for (const auto& [name, varData] : state.inputIds) + appender(varData.varId); + + for (const auto& [name, varData] : state.outputIds) + appender(varData.varId); + }); + + if (m_context.shader->GetStage() == ShaderStageType::Fragment) + state.header.Append(SpirvOp::OpExecutionMode, entryFunc.id, SpvExecutionModeOriginUpperLeft); } - // OpEntryPoint Vertex %main "main" %outNormal %inNormals %outTexCoords %inTexCoord %_ %inPos - - state.header.AppendVariadic(SpirvOp::OpEntryPoint, [&](const auto& appender) - { - appender(execModel); - appender(entryFunc.id); - appender(entryFuncData.name); - - for (const auto& [name, varData] : state.builtinIds) - appender(varData.varId); - - for (const auto& [name, varData] : state.inputIds) - appender(varData.varId); - - for (const auto& [name, varData] : state.outputIds) - appender(varData.varId); - }); - - if (m_context.shader->GetStage() == ShaderStageType::Fragment) - state.header.Append(SpirvOp::OpExecutionMode, entryFunc.id, SpvExecutionModeOriginUpperLeft); - std::vector ret; MergeSections(ret, state.header); MergeSections(ret, state.debugInfo); @@ -489,14 +499,14 @@ namespace Nz void SpirvWriter::AppendHeader() { - m_currentState->header.Append(SpvMagicNumber); //< Spir-V magic number + m_currentState->header.AppendRaw(SpvMagicNumber); //< Spir-V magic number UInt32 version = (m_environment.spvMajorVersion << 16) | m_environment.spvMinorVersion << 8; - m_currentState->header.Append(version); //< Spir-V version number (1.0 for compatibility) - m_currentState->header.Append(0); //< Generator identifier (TODO: Register generator to Khronos) + m_currentState->header.AppendRaw(version); //< Spir-V version number (1.0 for compatibility) + m_currentState->header.AppendRaw(0); //< Generator identifier (TODO: Register generator to Khronos) - m_currentState->header.Append(m_currentState->nextVarIndex); //< Bound (ID count) - m_currentState->header.Append(0); //< Instruction schema (required to be 0 for now) + m_currentState->header.AppendRaw(m_currentState->nextVarIndex); //< Bound (ID count) + m_currentState->header.AppendRaw(0); //< Instruction schema (required to be 0 for now) m_currentState->header.Append(SpirvOp::OpCapability, SpvCapabilityShader); @@ -506,6 +516,20 @@ namespace Nz m_currentState->header.Append(SpirvOp::OpMemoryModel, SpvAddressingModelLogical, SpvMemoryModelGLSL450); } + SpirvConstantCache::Function SpirvWriter::BuildFunctionType(ShaderExpressionType retType, const std::vector& parameters) + { + std::vector parameterTypes; + parameterTypes.reserve(parameters.size()); + + for (const auto& parameter : parameters) + parameterTypes.push_back(SpirvConstantCache::BuildPointerType(*m_context.shader, parameter.type, SpirvStorageClass::Function)); + + return SpirvConstantCache::Function{ + SpirvConstantCache::BuildType(*m_context.shader, retType), + std::move(parameterTypes) + }; + } + UInt32 SpirvWriter::GetConstantId(const ShaderConstantValue& value) const { return m_currentState->constantTypeCache.GetId(*SpirvConstantCache::BuildConstant(value)); @@ -513,18 +537,7 @@ namespace Nz UInt32 SpirvWriter::GetFunctionTypeId(ShaderExpressionType retType, const std::vector& parameters) { - std::vector parameterTypes; - parameterTypes.reserve(parameters.size()); - - for (const auto& parameter : parameters) - parameterTypes.push_back(SpirvConstantCache::BuildType(*m_context.shader, parameter.type)); - - return m_currentState->constantTypeCache.GetId({ - SpirvConstantCache::Function { - SpirvConstantCache::BuildType(*m_context.shader, retType), - std::move(parameterTypes) - } - }); + return m_currentState->constantTypeCache.GetId({ BuildFunctionType(retType, parameters) }); } auto SpirvWriter::GetBuiltinVariable(ShaderNodes::BuiltinEntry builtin) const -> const ExtVar& @@ -602,6 +615,22 @@ namespace Nz return it->second; } + UInt32 SpirvWriter::ReadParameterVariable(const std::string& name) + { + auto it = m_currentState->parameterIds.find(name); + assert(it != m_currentState->parameterIds.end()); + + return ReadVariable(it.value()); + } + + std::optional SpirvWriter::ReadParameterVariable(const std::string& name, OnlyCache) + { + auto it = m_currentState->parameterIds.find(name); + assert(it != m_currentState->parameterIds.end()); + + return ReadVariable(it.value(), OnlyCache{}); + } + UInt32 SpirvWriter::ReadUniformVariable(const std::string& name) { auto it = m_currentState->uniformIds.find(name); @@ -623,7 +652,7 @@ namespace Nz if (!var.valueId.has_value()) { UInt32 resultId = AllocateResultId(); - m_currentState->instructions.Append(SpirvOp::OpLoad, var.typeId, resultId, var.varId); + m_currentState->functionBlocks.back().Append(SpirvOp::OpLoad, var.typeId, resultId, var.varId); var.valueId = resultId; } @@ -646,18 +675,7 @@ namespace Nz UInt32 SpirvWriter::RegisterFunctionType(ShaderExpressionType retType, const std::vector& parameters) { - std::vector parameterTypes; - parameterTypes.reserve(parameters.size()); - - for (const auto& parameter : parameters) - parameterTypes.push_back(SpirvConstantCache::BuildType(*m_context.shader, parameter.type)); - - return m_currentState->constantTypeCache.Register({ - SpirvConstantCache::Function { - SpirvConstantCache::BuildType(*m_context.shader, retType), - std::move(parameterTypes) - } - }); + return m_currentState->constantTypeCache.Register({ BuildFunctionType(retType, parameters) }); } UInt32 SpirvWriter::RegisterPointerType(ShaderExpressionType type, SpirvStorageClass storageClass) From fed7370e7733ff5ee9856f4d0541735798ea9ff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 10 Mar 2021 11:18:13 +0100 Subject: [PATCH 077/278] Rework shader AST (WIP) --- include/Nazara/Renderer/RenderDevice.hpp | 4 +- include/Nazara/Shader.hpp | 17 +- include/Nazara/Shader/GlslWriter.hpp | 86 +-- include/Nazara/Shader/GlslWriter.inl | 120 ---- include/Nazara/Shader/ShaderAst.hpp | 130 ---- include/Nazara/Shader/ShaderAst.inl | 128 ---- include/Nazara/Shader/ShaderAstCache.hpp | 48 ++ include/Nazara/Shader/ShaderAstCache.inl | 37 + include/Nazara/Shader/ShaderAstCloner.hpp | 90 ++- .../Nazara/Shader/ShaderAstExpressionType.hpp | 57 ++ .../Nazara/Shader/ShaderAstExpressionType.inl | 17 + .../Shader/ShaderAstExpressionVisitor.hpp | 32 + .../ShaderAstExpressionVisitorExcept.hpp | 26 + include/Nazara/Shader/ShaderAstNodes.hpp | 53 ++ include/Nazara/Shader/ShaderAstOptimizer.hpp | 35 +- .../Shader/ShaderAstRecursiveVisitor.hpp | 49 +- include/Nazara/Shader/ShaderAstSerializer.hpp | 84 ++- include/Nazara/Shader/ShaderAstSerializer.inl | 42 +- .../Shader/ShaderAstStatementVisitor.hpp | 32 + .../ShaderAstStatementVisitorExcept.hpp | 26 + ...rExpressionType.hpp => ShaderAstTypes.hpp} | 25 +- ...rExpressionType.inl => ShaderAstTypes.inl} | 12 +- include/Nazara/Shader/ShaderAstUtils.hpp | 36 +- include/Nazara/Shader/ShaderAstUtils.inl | 4 +- include/Nazara/Shader/ShaderAstValidator.hpp | 78 +-- include/Nazara/Shader/ShaderAstValidator.inl | 6 +- include/Nazara/Shader/ShaderAstVisitor.hpp | 49 -- .../Nazara/Shader/ShaderAstVisitorExcept.hpp | 41 -- include/Nazara/Shader/ShaderBuilder.hpp | 100 ++- include/Nazara/Shader/ShaderBuilder.inl | 116 ++- include/Nazara/Shader/ShaderEnums.hpp | 39 +- include/Nazara/Shader/ShaderEnums.inl | 57 ++ include/Nazara/Shader/ShaderLangParser.hpp | 33 +- include/Nazara/Shader/ShaderLangTokenList.hpp | 4 +- include/Nazara/Shader/ShaderNodes.hpp | 505 ++++++-------- include/Nazara/Shader/ShaderNodes.inl | 388 +---------- include/Nazara/Shader/ShaderVarVisitor.hpp | 38 - .../Nazara/Shader/ShaderVarVisitorExcept.hpp | 28 - include/Nazara/Shader/ShaderVariables.hpp | 128 ---- include/Nazara/Shader/ShaderVariables.inl | 65 -- include/Nazara/Shader/ShaderWriter.hpp | 2 - include/Nazara/Shader/SpirvAstVisitor.hpp | 47 +- include/Nazara/Shader/SpirvConstantCache.hpp | 11 +- include/Nazara/Shader/SpirvExpressionLoad.hpp | 19 +- .../Nazara/Shader/SpirvExpressionStore.hpp | 20 +- include/Nazara/Shader/SpirvWriter.hpp | 31 +- include/Nazara/Shader/SpirvWriter.inl | 5 +- src/Nazara/Graphics/BasicMaterial.cpp | 4 +- src/Nazara/Graphics/UberShader.cpp | 10 +- src/Nazara/Shader/GlslWriter.cpp | 454 +++++------- src/Nazara/Shader/ShaderAst.cpp | 56 -- src/Nazara/Shader/ShaderAstCloner.cpp | 255 +++---- src/Nazara/Shader/ShaderAstExpressionType.cpp | 198 ++++++ ...tor.cpp => ShaderAstExpressionVisitor.cpp} | 11 +- .../ShaderAstExpressionVisitorExcept.cpp | 15 + src/Nazara/Shader/ShaderAstOptimizer.cpp | 166 ++--- .../Shader/ShaderAstRecursiveVisitor.cpp | 129 ++-- src/Nazara/Shader/ShaderAstSerializer.cpp | 659 +++++------------- ...itor.cpp => ShaderAstStatementVisitor.cpp} | 11 +- .../ShaderAstStatementVisitorExcept.cpp | 15 + src/Nazara/Shader/ShaderAstUtils.cpp | 60 +- src/Nazara/Shader/ShaderAstValidator.cpp | 543 +++++++-------- src/Nazara/Shader/ShaderAstVisitorExcept.cpp | 100 --- src/Nazara/Shader/ShaderLangLexer.cpp | 10 +- src/Nazara/Shader/ShaderLangParser.cpp | 138 ++-- src/Nazara/Shader/ShaderNodes.cpp | 268 +------ src/Nazara/Shader/ShaderVarVisitorExcept.cpp | 40 -- src/Nazara/Shader/ShaderVariables.cpp | 77 -- src/Nazara/Shader/SpirvAstVisitor.cpp | 475 ++++++------- src/Nazara/Shader/SpirvConstantCache.cpp | 64 +- src/Nazara/Shader/SpirvExpressionLoad.cpp | 43 +- src/Nazara/Shader/SpirvExpressionStore.cpp | 33 +- src/Nazara/Shader/SpirvWriter.cpp | 199 +++--- 73 files changed, 2721 insertions(+), 4312 deletions(-) delete mode 100644 include/Nazara/Shader/ShaderAst.hpp delete mode 100644 include/Nazara/Shader/ShaderAst.inl create mode 100644 include/Nazara/Shader/ShaderAstCache.hpp create mode 100644 include/Nazara/Shader/ShaderAstCache.inl create mode 100644 include/Nazara/Shader/ShaderAstExpressionType.hpp create mode 100644 include/Nazara/Shader/ShaderAstExpressionType.inl create mode 100644 include/Nazara/Shader/ShaderAstExpressionVisitor.hpp create mode 100644 include/Nazara/Shader/ShaderAstExpressionVisitorExcept.hpp create mode 100644 include/Nazara/Shader/ShaderAstNodes.hpp create mode 100644 include/Nazara/Shader/ShaderAstStatementVisitor.hpp create mode 100644 include/Nazara/Shader/ShaderAstStatementVisitorExcept.hpp rename include/Nazara/Shader/{ShaderExpressionType.hpp => ShaderAstTypes.hpp} (56%) rename include/Nazara/Shader/{ShaderExpressionType.inl => ShaderAstTypes.inl} (89%) delete mode 100644 include/Nazara/Shader/ShaderAstVisitor.hpp delete mode 100644 include/Nazara/Shader/ShaderAstVisitorExcept.hpp create mode 100644 include/Nazara/Shader/ShaderEnums.inl delete mode 100644 include/Nazara/Shader/ShaderVarVisitor.hpp delete mode 100644 include/Nazara/Shader/ShaderVarVisitorExcept.hpp delete mode 100644 include/Nazara/Shader/ShaderVariables.hpp delete mode 100644 include/Nazara/Shader/ShaderVariables.inl delete mode 100644 src/Nazara/Shader/ShaderAst.cpp create mode 100644 src/Nazara/Shader/ShaderAstExpressionType.cpp rename src/Nazara/Shader/{ShaderAstVisitor.cpp => ShaderAstExpressionVisitor.cpp} (52%) create mode 100644 src/Nazara/Shader/ShaderAstExpressionVisitorExcept.cpp rename src/Nazara/Shader/{ShaderVarVisitor.cpp => ShaderAstStatementVisitor.cpp} (51%) create mode 100644 src/Nazara/Shader/ShaderAstStatementVisitorExcept.cpp delete mode 100644 src/Nazara/Shader/ShaderAstVisitorExcept.cpp delete mode 100644 src/Nazara/Shader/ShaderVarVisitorExcept.cpp delete mode 100644 src/Nazara/Shader/ShaderVariables.cpp diff --git a/include/Nazara/Renderer/RenderDevice.hpp b/include/Nazara/Renderer/RenderDevice.hpp index 8030c0f55..feb3a153c 100644 --- a/include/Nazara/Renderer/RenderDevice.hpp +++ b/include/Nazara/Renderer/RenderDevice.hpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -24,7 +25,6 @@ namespace Nz { class CommandPool; - class ShaderAst; class ShaderStage; class NAZARA_RENDERER_API RenderDevice @@ -39,7 +39,7 @@ namespace Nz virtual std::shared_ptr InstantiateRenderPass(std::vector attachments, std::vector subpassDescriptions, std::vector subpassDependencies) = 0; virtual std::shared_ptr InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) = 0; virtual std::shared_ptr InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) = 0; - virtual std::shared_ptr InstantiateShaderStage(const ShaderAst& shaderAst, const ShaderWriter::States& states) = 0; + virtual std::shared_ptr InstantiateShaderStage(const ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states) = 0; virtual std::shared_ptr InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) = 0; std::shared_ptr InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const std::filesystem::path& sourcePath); virtual std::shared_ptr InstantiateTexture(const TextureInfo& params) = 0; diff --git a/include/Nazara/Shader.hpp b/include/Nazara/Shader.hpp index f8e41ff22..9c59a649d 100644 --- a/include/Nazara/Shader.hpp +++ b/include/Nazara/Shader.hpp @@ -32,23 +32,25 @@ #include #include #include -#include +#include #include +#include +#include +#include #include #include #include +#include +#include +#include #include #include -#include -#include #include #include #include -#include +#include +#include #include -#include -#include -#include #include #include #include @@ -58,6 +60,7 @@ #include #include #include +#include #include #endif // NAZARA_GLOBAL_SHADER_HPP diff --git a/include/Nazara/Shader/GlslWriter.hpp b/include/Nazara/Shader/GlslWriter.hpp index 5a6f7049d..fd3c299ce 100644 --- a/include/Nazara/Shader/GlslWriter.hpp +++ b/include/Nazara/Shader/GlslWriter.hpp @@ -9,9 +9,7 @@ #include #include -#include -#include -#include +#include #include #include #include @@ -19,7 +17,7 @@ namespace Nz { - class NAZARA_SHADER_API GlslWriter : public ShaderWriter, public ShaderVarVisitor, public ShaderAstVisitor + class NAZARA_SHADER_API GlslWriter : public ShaderWriter, public ShaderAst::AstRecursiveVisitor { public: struct Environment; @@ -30,7 +28,7 @@ namespace Nz GlslWriter(GlslWriter&&) = delete; ~GlslWriter() = default; - std::string Generate(const ShaderAst& shader, const States& conditions = {}); + std::string Generate(ShaderAst::StatementPtr& shader, const States& conditions = {}); void SetEnv(Environment environment); @@ -46,67 +44,45 @@ namespace Nz static const char* GetFlipYUniformName(); private: - void Append(ShaderExpressionType type); - void Append(ShaderNodes::BuiltinEntry builtin); - void Append(ShaderNodes::BasicType type); - void Append(ShaderNodes::MemoryLayout layout); + void Append(ShaderAst::ShaderExpressionType type); + void Append(ShaderAst::BuiltinEntry builtin); + void Append(ShaderAst::BasicType type); + void Append(ShaderAst::MemoryLayout layout); template void Append(const T& param); void AppendCommentSection(const std::string& section); - void AppendField(const std::string& structName, std::size_t* memberIndex, std::size_t remainingMembers); - void AppendFunction(const ShaderAst::Function& func); - void AppendFunctionPrototype(const ShaderAst::Function& func); + void AppendField(std::size_t scopeId, const std::string& structName, const std::string* memberIdentifier, std::size_t remainingMembers); void AppendLine(const std::string& txt = {}); - template void DeclareVariables(const ShaderAst& shader, const std::vector& variables, const std::string& keyword = {}, const std::string& section = {}); - void EnterScope(); void LeaveScope(); - using ShaderVarVisitor::Visit; - using ShaderAstVisitor::Visit; - void Visit(ShaderNodes::ExpressionPtr& expr, bool encloseIfRequired = false); - void Visit(ShaderNodes::AccessMember& node) override; - void Visit(ShaderNodes::AssignOp& node) override; - void Visit(ShaderNodes::Branch& node) override; - void Visit(ShaderNodes::BinaryOp& node) override; - void Visit(ShaderNodes::BuiltinVariable& var) override; - void Visit(ShaderNodes::Cast& node) override; - void Visit(ShaderNodes::ConditionalExpression& node) override; - void Visit(ShaderNodes::ConditionalStatement& node) override; - void Visit(ShaderNodes::Constant& node) override; - void Visit(ShaderNodes::DeclareVariable& node) override; - void Visit(ShaderNodes::Discard& node) override; - void Visit(ShaderNodes::ExpressionStatement& node) override; - void Visit(ShaderNodes::Identifier& node) override; - void Visit(ShaderNodes::InputVariable& var) override; - void Visit(ShaderNodes::IntrinsicCall& node) override; - void Visit(ShaderNodes::LocalVariable& var) override; - void Visit(ShaderNodes::NoOp& node) override; - void Visit(ShaderNodes::ParameterVariable& var) override; - void Visit(ShaderNodes::ReturnStatement& node) override; - void Visit(ShaderNodes::OutputVariable& var) override; - void Visit(ShaderNodes::Sample2D& node) override; - void Visit(ShaderNodes::StatementBlock& node) override; - void Visit(ShaderNodes::SwizzleOp& node) override; - void Visit(ShaderNodes::UniformVariable& var) override; + void Visit(ShaderAst::ExpressionPtr& expr, bool encloseIfRequired = false); - static bool HasExplicitBinding(const ShaderAst& shader); - static bool HasExplicitLocation(const ShaderAst& shader); + void Visit(ShaderAst::AccessMemberExpression& node) override; + void Visit(ShaderAst::AssignExpression& node) override; + void Visit(ShaderAst::BinaryExpression& node) override; + void Visit(ShaderAst::CastExpression& node) override; + void Visit(ShaderAst::ConditionalExpression& node) override; + void Visit(ShaderAst::ConstantExpression& node) override; + void Visit(ShaderAst::IdentifierExpression& node) override; + void Visit(ShaderAst::IntrinsicExpression& node) override; + void Visit(ShaderAst::SwizzleExpression& node) override; - struct Context - { - const ShaderAst* shader = nullptr; - const ShaderAst::Function* currentFunction = nullptr; - const States* states = nullptr; - }; + void Visit(ShaderAst::BranchStatement& node) override; + void Visit(ShaderAst::ConditionalStatement& node) override; + void Visit(ShaderAst::DeclareFunctionStatement& node) override; + void Visit(ShaderAst::DeclareVariableStatement& node) override; + void Visit(ShaderAst::DiscardStatement& node) override; + void Visit(ShaderAst::ExpressionStatement& node) override; + void Visit(ShaderAst::MultiStatement& node) override; + void Visit(ShaderAst::NoOpStatement& node) override; + void Visit(ShaderAst::ReturnStatement& node) override; - struct State - { - std::stringstream stream; - unsigned int indentLevel = 0; - }; + static bool HasExplicitBinding(ShaderAst::StatementPtr& shader); + static bool HasExplicitLocation(ShaderAst::StatementPtr& shader); + + struct State; - Context m_context; Environment m_environment; State* m_currentState; }; diff --git a/include/Nazara/Shader/GlslWriter.inl b/include/Nazara/Shader/GlslWriter.inl index fd5cbe094..1ecd13aee 100644 --- a/include/Nazara/Shader/GlslWriter.inl +++ b/include/Nazara/Shader/GlslWriter.inl @@ -3,130 +3,10 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include #include namespace Nz { - template - void GlslWriter::Append(const T& param) - { - NazaraAssert(m_currentState, "This function should only be called while processing an AST"); - - m_currentState->stream << param; - } - - template - void GlslWriter::DeclareVariables(const ShaderAst& shader, const std::vector& variables, const std::string& keyword, const std::string& section) - { - if (!variables.empty()) - { - if (!section.empty()) - AppendCommentSection(section); - - for (const auto& var : variables) - { - if constexpr (std::is_same_v) - { - if (var.locationIndex) - { - Append("layout(location = "); - Append(*var.locationIndex); - Append(") "); - } - - if (!keyword.empty()) - { - Append(keyword); - Append(" "); - } - - Append(var.type); - Append(" "); - Append(var.name); - AppendLine(";"); - } - else if constexpr (std::is_same_v) - { - if (var.bindingIndex || var.memoryLayout) - { - Append("layout("); - - bool first = true; - if (var.bindingIndex) - { - if (!first) - Append(", "); - - Append("binding = "); - Append(*var.bindingIndex); - - first = false; - } - - if (var.memoryLayout) - { - if (!first) - Append(", "); - - Append(*var.memoryLayout); - - first = false; - } - - Append(") "); - } - - if (!keyword.empty()) - { - Append(keyword); - Append(" "); - } - - std::visit([&](auto&& arg) - { - using U = std::decay_t; - if constexpr (std::is_same_v) - { - Append(arg); - Append(" "); - Append(var.name); - } - else if constexpr (std::is_same_v) - { - const auto& structs = shader.GetStructs(); - auto it = std::find_if(structs.begin(), structs.end(), [&](const auto& s) { return s.name == arg; }); - if (it == structs.end()) - throw std::runtime_error("struct " + arg + " has not been defined"); - - const auto& s = *it; - - AppendLine(var.name + "_interface"); - AppendLine("{"); - for (const auto& m : s.members) - { - Append("\t"); - Append(m.type); - Append(" "); - Append(m.name); - AppendLine(";"); - } - Append("} "); - Append(var.name); - } - else - static_assert(AlwaysFalse::value, "non-exhaustive visitor"); - - }, var.type); - - AppendLine(";"); - AppendLine(); - } - } - - AppendLine(); - } - } } #include diff --git a/include/Nazara/Shader/ShaderAst.hpp b/include/Nazara/Shader/ShaderAst.hpp deleted file mode 100644 index f34b0ac9f..000000000 --- a/include/Nazara/Shader/ShaderAst.hpp +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright (C) 2020 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_SHADER_AST_HPP -#define NAZARA_SHADER_AST_HPP - -#include -#include -#include -#include -#include -#include -#include - -namespace Nz -{ - class NAZARA_SHADER_API ShaderAst - { - public: - struct Condition; - struct Function; - struct FunctionParameter; - struct InputOutput; - struct Struct; - struct StructMember; - struct Uniform; - struct VariableBase; - - inline ShaderAst(ShaderStageType shaderStage); - ShaderAst(const ShaderAst&) = default; - ShaderAst(ShaderAst&&) noexcept = default; - ~ShaderAst() = default; - - void AddCondition(std::string name); - void AddFunction(std::string name, ShaderNodes::StatementPtr statement, std::vector parameters = {}, ShaderExpressionType returnType = ShaderNodes::BasicType::Void); - void AddInput(std::string name, ShaderExpressionType type, std::optional locationIndex = {}); - void AddOutput(std::string name, ShaderExpressionType type, std::optional locationIndex = {}); - void AddStruct(std::string name, std::vector members); - void AddUniform(std::string name, ShaderExpressionType type, std::optional bindingIndex = {}, std::optional memoryLayout = {}); - - inline std::size_t FindConditionByName(const std::string_view& conditionName) const; - - inline const Condition& GetCondition(std::size_t i) const; - inline std::size_t GetConditionCount() const; - inline const std::vector& GetConditions() const; - inline const Function& GetFunction(std::size_t i) const; - inline std::size_t GetFunctionCount() const; - inline const std::vector& GetFunctions() const; - inline const InputOutput& GetInput(std::size_t i) const; - inline std::size_t GetInputCount() const; - inline const std::vector& GetInputs() const; - inline const InputOutput& GetOutput(std::size_t i) const; - inline std::size_t GetOutputCount() const; - inline const std::vector& 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& GetStructs() const; - inline const Uniform& GetUniform(std::size_t i) const; - inline std::size_t GetUniformCount() const; - inline const std::vector& GetUniforms() const; - - ShaderAst& operator=(const ShaderAst&) = default; - ShaderAst& operator=(ShaderAst&&) noexcept = default; - - struct Condition - { - std::string name; - }; - - struct VariableBase - { - std::string name; - ShaderExpressionType type; - }; - - struct FunctionParameter : VariableBase - { - }; - - struct Function - { - std::string name; - std::vector parameters; - ShaderExpressionType returnType; - ShaderNodes::StatementPtr statement; - }; - - struct InputOutput : VariableBase - { - std::optional locationIndex; - }; - - struct Uniform : VariableBase - { - std::optional bindingIndex; - std::optional memoryLayout; - }; - - struct Struct - { - std::string name; - std::vector members; - }; - - struct StructMember - { - std::string name; - ShaderExpressionType type; - }; - - static constexpr std::size_t InvalidCondition = std::numeric_limits::max(); - - private: - std::vector m_conditions; - std::vector m_functions; - std::vector m_inputs; - std::vector m_outputs; - std::vector m_structs; - std::vector m_uniforms; - ShaderStageType m_stage; - }; -} - -#include - -#endif // NAZARA_SHADER_AST_HPP diff --git a/include/Nazara/Shader/ShaderAst.inl b/include/Nazara/Shader/ShaderAst.inl deleted file mode 100644 index 64bce4583..000000000 --- a/include/Nazara/Shader/ShaderAst.inl +++ /dev/null @@ -1,128 +0,0 @@ -// 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 -#include - -namespace Nz -{ - inline ShaderAst::ShaderAst(ShaderStageType shaderStage) : - m_stage(shaderStage) - { - } - - inline std::size_t ShaderAst::FindConditionByName(const std::string_view& conditionName) const - { - for (std::size_t i = 0; i < m_conditions.size(); ++i) - { - if (m_conditions[i].name == conditionName) - return i; - } - - return InvalidCondition; - } - - inline auto Nz::ShaderAst::GetCondition(std::size_t i) const -> const Condition& - { - assert(i < m_functions.size()); - return m_conditions[i]; - } - - inline std::size_t ShaderAst::GetConditionCount() const - { - return m_conditions.size(); - } - - inline auto ShaderAst::GetConditions() const -> const std::vector& - { - return m_conditions; - } - - inline auto ShaderAst::GetFunction(std::size_t i) const -> const Function& - { - assert(i < m_functions.size()); - return m_functions[i]; - } - - inline std::size_t ShaderAst::GetFunctionCount() const - { - return m_functions.size(); - } - - inline auto ShaderAst::GetFunctions() const -> const std::vector& - { - return m_functions; - } - - inline auto ShaderAst::GetInput(std::size_t i) const -> const InputOutput& - { - assert(i < m_inputs.size()); - return m_inputs[i]; - } - - inline std::size_t ShaderAst::GetInputCount() const - { - return m_inputs.size(); - } - - inline auto ShaderAst::GetInputs() const -> const std::vector& - { - return m_inputs; - } - - inline auto ShaderAst::GetOutput(std::size_t i) const -> const InputOutput& - { - assert(i < m_outputs.size()); - return m_outputs[i]; - } - - inline std::size_t ShaderAst::GetOutputCount() const - { - return m_outputs.size(); - } - - inline auto ShaderAst::GetOutputs() const -> const std::vector& - { - 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()); - return m_structs[i]; - } - - inline std::size_t ShaderAst::GetStructCount() const - { - return m_structs.size(); - } - - inline auto ShaderAst::GetStructs() const -> const std::vector& - { - return m_structs; - } - - inline auto ShaderAst::GetUniform(std::size_t i) const -> const Uniform& - { - assert(i < m_uniforms.size()); - return m_uniforms[i]; - } - - inline std::size_t ShaderAst::GetUniformCount() const - { - return m_uniforms.size(); - } - - inline auto ShaderAst::GetUniforms() const -> const std::vector& - { - return m_uniforms; - } -} - -#include diff --git a/include/Nazara/Shader/ShaderAstCache.hpp b/include/Nazara/Shader/ShaderAstCache.hpp new file mode 100644 index 000000000..595b6b410 --- /dev/null +++ b/include/Nazara/Shader/ShaderAstCache.hpp @@ -0,0 +1,48 @@ +// 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_SHADERASTCACHE_HPP +#define NAZARA_SHADERASTCACHE_HPP + +#include +#include +#include +#include + +namespace Nz::ShaderAst +{ + struct AstCache + { + struct Variable + { + ShaderExpressionType type; + }; + + struct Identifier + { + std::string name; + std::variant value; + }; + + struct Scope + { + std::optional parentScopeIndex; + std::vector identifiers; + }; + + inline const Identifier* FindIdentifier(std::size_t startingScopeId, const std::string& identifierName) const; + inline std::size_t GetScopeId(const Node* node) const; + + ShaderStageType stageType = ShaderStageType::Undefined; + std::unordered_map nodeExpressionType; + std::unordered_map scopeIdByNode; + std::vector scopes; + }; +} + +#include + +#endif diff --git a/include/Nazara/Shader/ShaderAstCache.inl b/include/Nazara/Shader/ShaderAstCache.inl new file mode 100644 index 000000000..48cd769f9 --- /dev/null +++ b/include/Nazara/Shader/ShaderAstCache.inl @@ -0,0 +1,37 @@ +// 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 +#include + +namespace Nz::ShaderAst +{ + inline auto AstCache::FindIdentifier(std::size_t startingScopeId, const std::string& identifierName) const -> const Identifier* + { + assert(startingScopeId < scopes.size()); + + std::optional scopeId = startingScopeId; + do + { + const auto& scope = scopes[*scopeId]; + auto it = std::find_if(scope.identifiers.rbegin(), scope.identifiers.rend(), [&](const auto& identifier) { return identifier.name == identifierName; }); + if (it != scope.identifiers.rend()) + return &*it; + + scopeId = scope.parentScopeIndex; + } while (scopeId); + + return nullptr; + } + + inline std::size_t AstCache::GetScopeId(const Node* node) const + { + auto it = scopeIdByNode.find(node); + assert(it == scopeIdByNode.end()); + + return it->second; + } +} + +#include diff --git a/include/Nazara/Shader/ShaderAstCloner.hpp b/include/Nazara/Shader/ShaderAstCloner.hpp index b777e2ba6..23e69234a 100644 --- a/include/Nazara/Shader/ShaderAstCloner.hpp +++ b/include/Nazara/Shader/ShaderAstCloner.hpp @@ -9,70 +9,62 @@ #include #include -#include -#include +#include +#include #include -namespace Nz +namespace Nz::ShaderAst { - class NAZARA_SHADER_API ShaderAstCloner : public ShaderAstVisitor, public ShaderVarVisitor + class NAZARA_SHADER_API AstCloner : public AstExpressionVisitor, public AstStatementVisitor { public: - ShaderAstCloner() = default; - ShaderAstCloner(const ShaderAstCloner&) = delete; - ShaderAstCloner(ShaderAstCloner&&) = delete; - ~ShaderAstCloner() = default; + AstCloner() = default; + AstCloner(const AstCloner&) = delete; + AstCloner(AstCloner&&) = delete; + ~AstCloner() = default; - ShaderNodes::StatementPtr Clone(const ShaderNodes::StatementPtr& statement); + ExpressionPtr Clone(ExpressionPtr& statement); + StatementPtr Clone(StatementPtr& statement); - ShaderAstCloner& operator=(const ShaderAstCloner&) = delete; - ShaderAstCloner& operator=(ShaderAstCloner&&) = delete; + AstCloner& operator=(const AstCloner&) = delete; + AstCloner& operator=(AstCloner&&) = delete; protected: - ShaderNodes::ExpressionPtr CloneExpression(const ShaderNodes::ExpressionPtr& expr); - ShaderNodes::StatementPtr CloneStatement(const ShaderNodes::StatementPtr& statement); - ShaderNodes::VariablePtr CloneVariable(const ShaderNodes::VariablePtr& statement); + ExpressionPtr CloneExpression(ExpressionPtr& expr); + StatementPtr CloneStatement(StatementPtr& statement); - using ShaderAstVisitor::Visit; - void Visit(ShaderNodes::AccessMember& node) override; - void Visit(ShaderNodes::AssignOp& node) override; - void Visit(ShaderNodes::BinaryOp& node) override; - void Visit(ShaderNodes::Branch& node) override; - void Visit(ShaderNodes::Cast& node) override; - void Visit(ShaderNodes::ConditionalExpression& node) override; - void Visit(ShaderNodes::ConditionalStatement& node) override; - void Visit(ShaderNodes::Constant& node) override; - void Visit(ShaderNodes::DeclareVariable& node) override; - void Visit(ShaderNodes::Discard& node) override; - void Visit(ShaderNodes::ExpressionStatement& node) override; - void Visit(ShaderNodes::Identifier& node) override; - void Visit(ShaderNodes::IntrinsicCall& node) override; - void Visit(ShaderNodes::NoOp& node) override; - void Visit(ShaderNodes::ReturnStatement& node) override; - void Visit(ShaderNodes::Sample2D& node) override; - void Visit(ShaderNodes::StatementBlock& node) override; - void Visit(ShaderNodes::SwizzleOp& node) override; + using AstExpressionVisitor::Visit; + using AstStatementVisitor::Visit; - using ShaderVarVisitor::Visit; - void Visit(ShaderNodes::BuiltinVariable& var) override; - void Visit(ShaderNodes::InputVariable& var) override; - void Visit(ShaderNodes::LocalVariable& var) override; - void Visit(ShaderNodes::OutputVariable& var) override; - void Visit(ShaderNodes::ParameterVariable& var) override; - void Visit(ShaderNodes::UniformVariable& var) override; + void Visit(AccessMemberExpression& node) override; + void Visit(AssignExpression& node) override; + void Visit(BinaryExpression& node) override; + void Visit(CastExpression& node) override; + void Visit(ConditionalExpression& node) override; + void Visit(ConstantExpression& node) override; + void Visit(IdentifierExpression& node) override; + void Visit(IntrinsicExpression& node) override; + void Visit(SwizzleExpression& node) override; + void Visit(BranchStatement& node) override; + void Visit(ConditionalStatement& node) override; + void Visit(DeclareFunctionStatement& node) override; + void Visit(DeclareStructStatement& node) override; + void Visit(DeclareVariableStatement& node) override; + void Visit(DiscardStatement& node) override; + void Visit(ExpressionStatement& node) override; + void Visit(MultiStatement& node) override; + void Visit(NoOpStatement& node) override; + void Visit(ReturnStatement& node) override; - void PushExpression(ShaderNodes::ExpressionPtr expression); - void PushStatement(ShaderNodes::StatementPtr statement); - void PushVariable(ShaderNodes::VariablePtr variable); + void PushExpression(ExpressionPtr expression); + void PushStatement(StatementPtr statement); - ShaderNodes::ExpressionPtr PopExpression(); - ShaderNodes::StatementPtr PopStatement(); - ShaderNodes::VariablePtr PopVariable(); + ExpressionPtr PopExpression(); + StatementPtr PopStatement(); private: - std::vector m_expressionStack; - std::vector m_statementStack; - std::vector m_variableStack; + std::vector m_expressionStack; + std::vector m_statementStack; }; } diff --git a/include/Nazara/Shader/ShaderAstExpressionType.hpp b/include/Nazara/Shader/ShaderAstExpressionType.hpp new file mode 100644 index 000000000..4ad7731e8 --- /dev/null +++ b/include/Nazara/Shader/ShaderAstExpressionType.hpp @@ -0,0 +1,57 @@ +// 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_SHADERASTEXPRESSIONTYPE_HPP +#define NAZARA_SHADERASTEXPRESSIONTYPE_HPP + +#include +#include +#include +#include +#include + +namespace Nz::ShaderAst +{ + struct AstCache; + + class NAZARA_SHADER_API ExpressionTypeVisitor : public AstExpressionVisitor + { + public: + ExpressionTypeVisitor() = default; + ExpressionTypeVisitor(const ExpressionTypeVisitor&) = delete; + ExpressionTypeVisitor(ExpressionTypeVisitor&&) = delete; + ~ExpressionTypeVisitor() = default; + + ShaderExpressionType GetExpressionType(Expression& expression, AstCache* cache); + + ExpressionTypeVisitor& operator=(const ExpressionTypeVisitor&) = delete; + ExpressionTypeVisitor& operator=(ExpressionTypeVisitor&&) = delete; + + private: + ShaderExpressionType GetExpressionTypeInternal(Expression& expression); + + void Visit(Expression& expression); + + void Visit(AccessMemberExpression& node) override; + void Visit(AssignExpression& node) override; + void Visit(BinaryExpression& node) override; + void Visit(CastExpression& node) override; + void Visit(ConditionalExpression& node) override; + void Visit(ConstantExpression& node) override; + void Visit(IdentifierExpression& node) override; + void Visit(IntrinsicExpression& node) override; + void Visit(SwizzleExpression& node) override; + + AstCache* m_cache; + std::optional m_lastExpressionType; + }; + + inline ShaderExpressionType GetExpressionType(Expression& expression, AstCache* cache = nullptr); +} + +#include + +#endif diff --git a/include/Nazara/Shader/ShaderAstExpressionType.inl b/include/Nazara/Shader/ShaderAstExpressionType.inl new file mode 100644 index 000000000..f71146200 --- /dev/null +++ b/include/Nazara/Shader/ShaderAstExpressionType.inl @@ -0,0 +1,17 @@ +// 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 +#include + +namespace Nz::ShaderAst +{ + inline ShaderExpressionType GetExpressionType(Expression& expression, AstCache* cache) + { + ExpressionTypeVisitor visitor; + return visitor.GetExpressionType(expression, cache); + } +} + +#include diff --git a/include/Nazara/Shader/ShaderAstExpressionVisitor.hpp b/include/Nazara/Shader/ShaderAstExpressionVisitor.hpp new file mode 100644 index 000000000..83e8b0271 --- /dev/null +++ b/include/Nazara/Shader/ShaderAstExpressionVisitor.hpp @@ -0,0 +1,32 @@ +// 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_SHADERASTEXPRESSIONVISITOR_HPP +#define NAZARA_SHADERASTEXPRESSIONVISITOR_HPP + +#include +#include +#include + +namespace Nz::ShaderAst +{ + class NAZARA_SHADER_API AstExpressionVisitor + { + public: + AstExpressionVisitor() = default; + AstExpressionVisitor(const AstExpressionVisitor&) = delete; + AstExpressionVisitor(AstExpressionVisitor&&) = delete; + virtual ~AstExpressionVisitor(); + +#define NAZARA_SHADERAST_EXPRESSION(NodeType) virtual void Visit(NodeType& node) = 0; +#include + + AstExpressionVisitor& operator=(const AstExpressionVisitor&) = delete; + AstExpressionVisitor& operator=(AstExpressionVisitor&&) = delete; + }; +} + +#endif diff --git a/include/Nazara/Shader/ShaderAstExpressionVisitorExcept.hpp b/include/Nazara/Shader/ShaderAstExpressionVisitorExcept.hpp new file mode 100644 index 000000000..f28e98c78 --- /dev/null +++ b/include/Nazara/Shader/ShaderAstExpressionVisitorExcept.hpp @@ -0,0 +1,26 @@ +// 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_SHADERASTEXPRESSIONVISITOREXCEPT_HPP +#define NAZARA_SHADERASTEXPRESSIONVISITOREXCEPT_HPP + +#include +#include +#include + +namespace Nz::ShaderAst +{ + class NAZARA_SHADER_API ExpressionVisitorExcept : public AstExpressionVisitor + { + public: + using AstExpressionVisitor::Visit; + +#define NAZARA_SHADERAST_EXPRESSION(Node) void Visit(ShaderAst::Node& node) override; +#include + }; +} + +#endif diff --git a/include/Nazara/Shader/ShaderAstNodes.hpp b/include/Nazara/Shader/ShaderAstNodes.hpp new file mode 100644 index 000000000..7bbce68a9 --- /dev/null +++ b/include/Nazara/Shader/ShaderAstNodes.hpp @@ -0,0 +1,53 @@ +// Copyright (C) 2020 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#if !defined(NAZARA_SHADERAST_NODE) && !defined(NAZARA_SHADERAST_EXPRESSION) && !defined(NAZARA_SHADERAST_STATEMENT) +#error You must define NAZARA_SHADERAST_NODE or NAZARA_SHADERAST_EXPRESSION or NAZARA_SHADERAST_STATEMENT before including this file +#endif + +#ifndef NAZARA_SHADERAST_NODE +#define NAZARA_SHADERAST_NODE(X) +#endif + +#ifndef NAZARA_SHADERAST_NODE_LAST +#define NAZARA_SHADERAST_NODE_LAST(X) +#endif + +#ifndef NAZARA_SHADERAST_EXPRESSION +#define NAZARA_SHADERAST_EXPRESSION(X) NAZARA_SHADERAST_NODE(X) +#endif + +#ifndef NAZARA_SHADERAST_STATEMENT +#define NAZARA_SHADERAST_STATEMENT(X) NAZARA_SHADERAST_NODE(X) +#endif + +#ifndef NAZARA_SHADERAST_STATEMENT_LAST +#define NAZARA_SHADERAST_STATEMENT_LAST(X) NAZARA_SHADERAST_STATEMENT(X) +#endif + +NAZARA_SHADERAST_EXPRESSION(AccessMemberExpression) +NAZARA_SHADERAST_EXPRESSION(AssignExpression) +NAZARA_SHADERAST_EXPRESSION(BinaryExpression) +NAZARA_SHADERAST_EXPRESSION(CastExpression) +NAZARA_SHADERAST_EXPRESSION(ConditionalExpression) +NAZARA_SHADERAST_EXPRESSION(ConstantExpression) +NAZARA_SHADERAST_EXPRESSION(IdentifierExpression) +NAZARA_SHADERAST_EXPRESSION(IntrinsicExpression) +NAZARA_SHADERAST_EXPRESSION(SwizzleExpression) +NAZARA_SHADERAST_STATEMENT(BranchStatement) +NAZARA_SHADERAST_STATEMENT(ConditionalStatement) +NAZARA_SHADERAST_STATEMENT(DeclareFunctionStatement) +NAZARA_SHADERAST_STATEMENT(DeclareStructStatement) +NAZARA_SHADERAST_STATEMENT(DeclareVariableStatement) +NAZARA_SHADERAST_STATEMENT(DiscardStatement) +NAZARA_SHADERAST_STATEMENT(ExpressionStatement) +NAZARA_SHADERAST_STATEMENT(MultiStatement) +NAZARA_SHADERAST_STATEMENT(NoOpStatement) +NAZARA_SHADERAST_STATEMENT_LAST(ReturnStatement) + +#undef NAZARA_SHADERAST_EXPRESSION +#undef NAZARA_SHADERAST_NODE +#undef NAZARA_SHADERAST_NODE_LAST +#undef NAZARA_SHADERAST_STATEMENT +#undef NAZARA_SHADERAST_STATEMENT_LAST diff --git a/include/Nazara/Shader/ShaderAstOptimizer.hpp b/include/Nazara/Shader/ShaderAstOptimizer.hpp index d7d56b7cf..83d5fa499 100644 --- a/include/Nazara/Shader/ShaderAstOptimizer.hpp +++ b/include/Nazara/Shader/ShaderAstOptimizer.hpp @@ -12,35 +12,32 @@ #include #include -namespace Nz +namespace Nz::ShaderAst { - class ShaderAst; - - class NAZARA_SHADER_API ShaderAstOptimizer : public ShaderAstCloner + class NAZARA_SHADER_API AstOptimizer : public AstCloner { public: - ShaderAstOptimizer() = default; - ShaderAstOptimizer(const ShaderAstOptimizer&) = delete; - ShaderAstOptimizer(ShaderAstOptimizer&&) = delete; - ~ShaderAstOptimizer() = default; + AstOptimizer() = default; + AstOptimizer(const AstOptimizer&) = delete; + AstOptimizer(AstOptimizer&&) = delete; + ~AstOptimizer() = default; - ShaderNodes::StatementPtr Optimise(const ShaderNodes::StatementPtr& statement); - ShaderNodes::StatementPtr Optimise(const ShaderNodes::StatementPtr& statement, const ShaderAst& shader, UInt64 enabledConditions); + StatementPtr Optimise(StatementPtr& statement); + StatementPtr Optimise(StatementPtr& statement, UInt64 enabledConditions); - ShaderAstOptimizer& operator=(const ShaderAstOptimizer&) = delete; - ShaderAstOptimizer& operator=(ShaderAstOptimizer&&) = delete; + AstOptimizer& operator=(const AstOptimizer&) = delete; + AstOptimizer& operator=(AstOptimizer&&) = delete; protected: - using ShaderAstCloner::Visit; - void Visit(ShaderNodes::BinaryOp& node) override; - void Visit(ShaderNodes::Branch& node) override; - void Visit(ShaderNodes::ConditionalExpression& node) override; - void Visit(ShaderNodes::ConditionalStatement& node) override; + using AstCloner::Visit; + void Visit(BinaryExpression& node) override; + void Visit(ConditionalExpression& node) override; + void Visit(BranchStatement& node) override; + void Visit(ConditionalStatement& node) override; - template void PropagateConstant(const std::shared_ptr& lhs, const std::shared_ptr& rhs); + template void PropagateConstant(std::unique_ptr&& lhs, std::unique_ptr&& rhs); private: - const ShaderAst* m_shaderAst; UInt64 m_enabledConditions; }; } diff --git a/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp b/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp index 1b7e1eebd..68251ddc0 100644 --- a/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp +++ b/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp @@ -9,36 +9,37 @@ #include #include -#include +#include +#include -namespace Nz +namespace Nz::ShaderAst { - class NAZARA_SHADER_API ShaderAstRecursiveVisitor : public ShaderAstVisitor + class NAZARA_SHADER_API AstRecursiveVisitor : public AstExpressionVisitor, public AstStatementVisitor { public: - ShaderAstRecursiveVisitor() = default; - ~ShaderAstRecursiveVisitor() = default; + AstRecursiveVisitor() = default; + ~AstRecursiveVisitor() = default; - using ShaderAstVisitor::Visit; + void Visit(AccessMemberExpression& node) override; + void Visit(AssignExpression& node) override; + void Visit(BinaryExpression& node) override; + void Visit(CastExpression& node) override; + void Visit(ConditionalExpression& node) override; + void Visit(ConstantExpression& node) override; + void Visit(IdentifierExpression& node) override; + void Visit(IntrinsicExpression& node) override; + void Visit(SwizzleExpression& node) override; - void Visit(ShaderNodes::AccessMember& node) override; - void Visit(ShaderNodes::AssignOp& node) override; - void Visit(ShaderNodes::BinaryOp& node) override; - void Visit(ShaderNodes::Branch& node) override; - void Visit(ShaderNodes::Cast& node) override; - void Visit(ShaderNodes::ConditionalExpression& node) override; - void Visit(ShaderNodes::ConditionalStatement& node) override; - void Visit(ShaderNodes::Constant& node) override; - void Visit(ShaderNodes::DeclareVariable& node) override; - void Visit(ShaderNodes::Discard& node) override; - void Visit(ShaderNodes::ExpressionStatement& node) override; - void Visit(ShaderNodes::Identifier& node) override; - void Visit(ShaderNodes::IntrinsicCall& node) override; - void Visit(ShaderNodes::NoOp& node) override; - void Visit(ShaderNodes::ReturnStatement& node) override; - void Visit(ShaderNodes::Sample2D& node) override; - void Visit(ShaderNodes::StatementBlock& node) override; - void Visit(ShaderNodes::SwizzleOp& node) override; + void Visit(BranchStatement& node) override; + void Visit(ConditionalStatement& node) override; + void Visit(DeclareFunctionStatement& node) override; + void Visit(DeclareStructStatement& node) override; + void Visit(DeclareVariableStatement& node) override; + void Visit(DiscardStatement& node) override; + void Visit(ExpressionStatement& node) override; + void Visit(MultiStatement& node) override; + void Visit(NoOpStatement& node) override; + void Visit(ReturnStatement& node) override; }; } diff --git a/include/Nazara/Shader/ShaderAstSerializer.hpp b/include/Nazara/Shader/ShaderAstSerializer.hpp index b3e674fae..fe09ea604 100644 --- a/include/Nazara/Shader/ShaderAstSerializer.hpp +++ b/include/Nazara/Shader/ShaderAstSerializer.hpp @@ -11,40 +11,38 @@ #include #include #include -#include #include -#include -namespace Nz +namespace Nz::ShaderAst { - class NAZARA_SHADER_API ShaderAstSerializerBase + class NAZARA_SHADER_API AstSerializerBase { public: - ShaderAstSerializerBase() = default; - ShaderAstSerializerBase(const ShaderAstSerializerBase&) = delete; - ShaderAstSerializerBase(ShaderAstSerializerBase&&) = delete; - ~ShaderAstSerializerBase() = default; + AstSerializerBase() = default; + AstSerializerBase(const AstSerializerBase&) = delete; + AstSerializerBase(AstSerializerBase&&) = delete; + ~AstSerializerBase() = default; - void Serialize(ShaderNodes::AccessMember& node); - void Serialize(ShaderNodes::AssignOp& node); - void Serialize(ShaderNodes::BinaryOp& node); - void Serialize(ShaderNodes::BuiltinVariable& var); - void Serialize(ShaderNodes::Branch& node); - void Serialize(ShaderNodes::Cast& node); - void Serialize(ShaderNodes::ConditionalExpression& node); - void Serialize(ShaderNodes::ConditionalStatement& node); - void Serialize(ShaderNodes::Constant& node); - void Serialize(ShaderNodes::DeclareVariable& node); - void Serialize(ShaderNodes::Discard& node); - void Serialize(ShaderNodes::ExpressionStatement& node); - void Serialize(ShaderNodes::Identifier& node); - void Serialize(ShaderNodes::IntrinsicCall& node); - void Serialize(ShaderNodes::NamedVariable& var); - void Serialize(ShaderNodes::NoOp& node); - void Serialize(ShaderNodes::ReturnStatement& node); - void Serialize(ShaderNodes::Sample2D& node); - void Serialize(ShaderNodes::StatementBlock& node); - void Serialize(ShaderNodes::SwizzleOp& node); + void Serialize(AccessMemberExpression& node); + void Serialize(AssignExpression& node); + void Serialize(BinaryExpression& node); + void Serialize(CastExpression& node); + void Serialize(ConditionalExpression& node); + void Serialize(ConstantExpression& node); + void Serialize(IdentifierExpression& node); + void Serialize(IntrinsicExpression& node); + void Serialize(SwizzleExpression& node); + + void Serialize(BranchStatement& node); + void Serialize(ConditionalStatement& node); + void Serialize(DeclareFunctionStatement& node); + void Serialize(DeclareStructStatement& node); + void Serialize(DeclareVariableStatement& node); + void Serialize(DiscardStatement& node); + void Serialize(ExpressionStatement& node); + void Serialize(MultiStatement& node); + void Serialize(NoOpStatement& node); + void Serialize(ReturnStatement& node); protected: template void Container(T& container); @@ -54,8 +52,8 @@ namespace Nz virtual bool IsWriting() const = 0; - virtual void Node(ShaderNodes::NodePtr& node) = 0; - template void Node(std::shared_ptr& node); + virtual void Node(ExpressionPtr& node) = 0; + virtual void Node(StatementPtr& node) = 0; virtual void Type(ShaderExpressionType& type) = 0; @@ -74,23 +72,20 @@ namespace Nz virtual void Value(UInt32& val) = 0; virtual void Value(UInt64& val) = 0; inline void SizeT(std::size_t& val); - - virtual void Variable(ShaderNodes::VariablePtr& var) = 0; - template void Variable(std::shared_ptr& var); }; - class NAZARA_SHADER_API ShaderAstSerializer final : public ShaderAstSerializerBase + class NAZARA_SHADER_API ShaderAstSerializer final : public AstSerializerBase { public: inline ShaderAstSerializer(ByteStream& stream); ~ShaderAstSerializer() = default; - void Serialize(const ShaderAst& shader); + void Serialize(StatementPtr& shader); private: bool IsWriting() const override; - void Node(const ShaderNodes::NodePtr& node); - void Node(ShaderNodes::NodePtr& node) override; + void Node(ExpressionPtr& node) override; + void Node(StatementPtr& node) override; void Type(ShaderExpressionType& type) override; void Value(bool& val) override; void Value(float& val) override; @@ -106,22 +101,22 @@ namespace Nz void Value(UInt16& val) override; void Value(UInt32& val) override; void Value(UInt64& val) override; - void Variable(ShaderNodes::VariablePtr& var) override; ByteStream& m_stream; }; - class NAZARA_SHADER_API ShaderAstUnserializer final : public ShaderAstSerializerBase + class NAZARA_SHADER_API ShaderAstUnserializer final : public AstSerializerBase { public: ShaderAstUnserializer(ByteStream& stream); ~ShaderAstUnserializer() = default; - ShaderAst Unserialize(); + StatementPtr Unserialize(); private: bool IsWriting() const override; - void Node(ShaderNodes::NodePtr& node) override; + void Node(ExpressionPtr& node) override; + void Node(StatementPtr& node) override; void Type(ShaderExpressionType& type) override; void Value(bool& val) override; void Value(float& val) override; @@ -137,14 +132,13 @@ namespace Nz void Value(UInt16& val) override; void Value(UInt32& val) override; void Value(UInt64& val) override; - void Variable(ShaderNodes::VariablePtr& var) override; ByteStream& m_stream; }; - NAZARA_SHADER_API ByteArray SerializeShader(const ShaderAst& shader); - inline ShaderAst UnserializeShader(const void* data, std::size_t size); - NAZARA_SHADER_API ShaderAst UnserializeShader(ByteStream& stream); + NAZARA_SHADER_API ByteArray SerializeShader(StatementPtr& shader); + inline StatementPtr UnserializeShader(const void* data, std::size_t size); + NAZARA_SHADER_API StatementPtr UnserializeShader(ByteStream& stream); } #include diff --git a/include/Nazara/Shader/ShaderAstSerializer.inl b/include/Nazara/Shader/ShaderAstSerializer.inl index 6b61c1197..c1b2d41c6 100644 --- a/include/Nazara/Shader/ShaderAstSerializer.inl +++ b/include/Nazara/Shader/ShaderAstSerializer.inl @@ -5,10 +5,10 @@ #include #include -namespace Nz +namespace Nz::ShaderAst { template - void ShaderAstSerializerBase::Container(T& container) + void AstSerializerBase::Container(T& container) { bool isWriting = IsWriting(); @@ -23,7 +23,7 @@ namespace Nz template - void ShaderAstSerializerBase::Enum(T& enumVal) + void AstSerializerBase::Enum(T& enumVal) { bool isWriting = IsWriting(); @@ -37,7 +37,7 @@ namespace Nz } template - void ShaderAstSerializerBase::OptEnum(std::optional& optVal) + void AstSerializerBase::OptEnum(std::optional& optVal) { bool isWriting = IsWriting(); @@ -55,7 +55,7 @@ namespace Nz } template - void ShaderAstSerializerBase::OptVal(std::optional& optVal) + void AstSerializerBase::OptVal(std::optional& optVal) { bool isWriting = IsWriting(); @@ -77,21 +77,7 @@ namespace Nz } } - template - void ShaderAstSerializerBase::Node(std::shared_ptr& node) - { - bool isWriting = IsWriting(); - - ShaderNodes::NodePtr value; - if (isWriting) - value = node; - - Node(value); - if (!isWriting) - node = std::static_pointer_cast(value); - } - - inline void ShaderAstSerializerBase::SizeT(std::size_t& val) + inline void AstSerializerBase::SizeT(std::size_t& val) { bool isWriting = IsWriting(); @@ -105,20 +91,6 @@ namespace Nz val = static_cast(fixedVal); } - template - void ShaderAstSerializerBase::Variable(std::shared_ptr& var) - { - bool isWriting = IsWriting(); - - ShaderNodes::VariablePtr value; - if (isWriting) - value = var; - - Variable(value); - if (!isWriting) - var = std::static_pointer_cast(value); - } - inline ShaderAstSerializer::ShaderAstSerializer(ByteStream& stream) : m_stream(stream) { @@ -129,7 +101,7 @@ namespace Nz { } - inline ShaderAst UnserializeShader(const void* data, std::size_t size) + inline StatementPtr UnserializeShader(const void* data, std::size_t size) { ByteStream byteStream(data, size); return UnserializeShader(byteStream); diff --git a/include/Nazara/Shader/ShaderAstStatementVisitor.hpp b/include/Nazara/Shader/ShaderAstStatementVisitor.hpp new file mode 100644 index 000000000..2da7e28a1 --- /dev/null +++ b/include/Nazara/Shader/ShaderAstStatementVisitor.hpp @@ -0,0 +1,32 @@ +// 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_SHADERASTSTATEMENTVISITOR_HPP +#define NAZARA_SHADERASTSTATEMENTVISITOR_HPP + +#include +#include +#include + +namespace Nz::ShaderAst +{ + class NAZARA_SHADER_API AstStatementVisitor + { + public: + AstStatementVisitor() = default; + AstStatementVisitor(const AstStatementVisitor&) = delete; + AstStatementVisitor(AstStatementVisitor&&) = delete; + virtual ~AstStatementVisitor(); + +#define NAZARA_SHADERAST_STATEMENT(NodeType) virtual void Visit(ShaderAst::NodeType& node) = 0; +#include + + AstStatementVisitor& operator=(const AstStatementVisitor&) = delete; + AstStatementVisitor& operator=(AstStatementVisitor&&) = delete; + }; +} + +#endif diff --git a/include/Nazara/Shader/ShaderAstStatementVisitorExcept.hpp b/include/Nazara/Shader/ShaderAstStatementVisitorExcept.hpp new file mode 100644 index 000000000..d5a85416f --- /dev/null +++ b/include/Nazara/Shader/ShaderAstStatementVisitorExcept.hpp @@ -0,0 +1,26 @@ +// 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_SHADERASTSTATEMENTVISITOREXCEPT_HPP +#define NAZARA_SHADERASTSTATEMENTVISITOREXCEPT_HPP + +#include +#include +#include + +namespace Nz::ShaderAst +{ + class NAZARA_SHADER_API StatementVisitorExcept : public AstStatementVisitor + { + public: + using AstStatementVisitor::Visit; + +#define NAZARA_SHADERAST_STATEMENT(Node) void Visit(ShaderAst::Node& node) override; +#include + }; +} + +#endif diff --git a/include/Nazara/Shader/ShaderExpressionType.hpp b/include/Nazara/Shader/ShaderAstTypes.hpp similarity index 56% rename from include/Nazara/Shader/ShaderExpressionType.hpp rename to include/Nazara/Shader/ShaderAstTypes.hpp index 6d5385121..e1f50d4e7 100644 --- a/include/Nazara/Shader/ShaderExpressionType.hpp +++ b/include/Nazara/Shader/ShaderAstTypes.hpp @@ -4,17 +4,30 @@ #pragma once -#ifndef NAZARA_SHADER_EXPRESSIONTYPE_HPP -#define NAZARA_SHADER_EXPRESSIONTYPE_HPP +#ifndef NAZARA_SHADER_ASTTYPES_HPP +#define NAZARA_SHADER_ASTTYPES_HPP #include #include #include #include +#include -namespace Nz +namespace Nz::ShaderAst { - using ShaderExpressionType = std::variant; + using ShaderExpressionType = std::variant; + + struct StructDescription + { + struct StructMember + { + std::string name; + ShaderExpressionType type; + }; + + std::string name; + std::vector members; + }; inline bool IsBasicType(const ShaderExpressionType& type); inline bool IsMatrixType(const ShaderExpressionType& type); @@ -22,6 +35,6 @@ namespace Nz inline bool IsStructType(const ShaderExpressionType& type); } -#include +#include -#endif // NAZARA_SHADER_EXPRESSIONTYPE_HPP +#endif // NAZARA_SHADER_ASTTYPES_HPP diff --git a/include/Nazara/Shader/ShaderExpressionType.inl b/include/Nazara/Shader/ShaderAstTypes.inl similarity index 89% rename from include/Nazara/Shader/ShaderExpressionType.inl rename to include/Nazara/Shader/ShaderAstTypes.inl index 8f72fb376..6eed4a945 100644 --- a/include/Nazara/Shader/ShaderExpressionType.inl +++ b/include/Nazara/Shader/ShaderAstTypes.inl @@ -2,18 +2,18 @@ // This file is part of the "Nazara Engine - Shader generator" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include #include -namespace Nz +namespace Nz::ShaderAst { inline bool IsBasicType(const ShaderExpressionType& type) { return std::visit([&](auto&& arg) { using T = std::decay_t; - if constexpr (std::is_same_v) + if constexpr (std::is_same_v) return true; else if constexpr (std::is_same_v) return false; @@ -25,8 +25,6 @@ namespace Nz inline bool IsMatrixType(const ShaderExpressionType& type) { - using namespace ShaderNodes; - if (!IsBasicType(type)) return false; @@ -58,8 +56,6 @@ namespace Nz inline bool IsSamplerType(const ShaderExpressionType& type) { - using namespace ShaderNodes; - if (!IsBasicType(type)) return false; @@ -94,7 +90,7 @@ namespace Nz return std::visit([&](auto&& arg) { using T = std::decay_t; - if constexpr (std::is_same_v) + if constexpr (std::is_same_v) return false; else if constexpr (std::is_same_v) return true; diff --git a/include/Nazara/Shader/ShaderAstUtils.hpp b/include/Nazara/Shader/ShaderAstUtils.hpp index e78ee657f..3f577ed3e 100644 --- a/include/Nazara/Shader/ShaderAstUtils.hpp +++ b/include/Nazara/Shader/ShaderAstUtils.hpp @@ -10,14 +10,12 @@ #include #include #include -#include +#include #include -namespace Nz +namespace Nz::ShaderAst { - class ShaderAst; - - class NAZARA_SHADER_API ShaderAstValueCategory final : public ShaderAstVisitorExcept + class NAZARA_SHADER_API ShaderAstValueCategory final : public AstExpressionVisitor { public: ShaderAstValueCategory() = default; @@ -25,28 +23,28 @@ namespace Nz ShaderAstValueCategory(ShaderAstValueCategory&&) = delete; ~ShaderAstValueCategory() = default; - ShaderNodes::ExpressionCategory GetExpressionCategory(const ShaderNodes::ExpressionPtr& expression); + ExpressionCategory GetExpressionCategory(Expression& expression); ShaderAstValueCategory& operator=(const ShaderAstValueCategory&) = delete; ShaderAstValueCategory& operator=(ShaderAstValueCategory&&) = delete; private: - using ShaderAstVisitorExcept::Visit; - void Visit(ShaderNodes::AccessMember& node) override; - void Visit(ShaderNodes::AssignOp& node) override; - void Visit(ShaderNodes::BinaryOp& node) override; - void Visit(ShaderNodes::Cast& node) override; - void Visit(ShaderNodes::ConditionalExpression& node) override; - void Visit(ShaderNodes::Constant& node) override; - void Visit(ShaderNodes::Identifier& node) override; - void Visit(ShaderNodes::IntrinsicCall& node) override; - void Visit(ShaderNodes::Sample2D& node) override; - void Visit(ShaderNodes::SwizzleOp& node) override; + using AstExpressionVisitor::Visit; - ShaderNodes::ExpressionCategory m_expressionCategory; + void Visit(AccessMemberExpression& node) override; + void Visit(AssignExpression& node) override; + void Visit(BinaryExpression& node) override; + void Visit(CastExpression& node) override; + void Visit(ConditionalExpression& node) override; + void Visit(ConstantExpression& node) override; + void Visit(IdentifierExpression& node) override; + void Visit(IntrinsicExpression& node) override; + void Visit(SwizzleExpression& node) override; + + ExpressionCategory m_expressionCategory; }; - inline ShaderNodes::ExpressionCategory GetExpressionCategory(const ShaderNodes::ExpressionPtr& expression); + inline ExpressionCategory GetExpressionCategory(Expression& expression); } #include diff --git a/include/Nazara/Shader/ShaderAstUtils.inl b/include/Nazara/Shader/ShaderAstUtils.inl index 852b2e685..dec5ed3a9 100644 --- a/include/Nazara/Shader/ShaderAstUtils.inl +++ b/include/Nazara/Shader/ShaderAstUtils.inl @@ -5,9 +5,9 @@ #include #include -namespace Nz +namespace Nz::ShaderAst { - ShaderNodes::ExpressionCategory GetExpressionCategory(const ShaderNodes::ExpressionPtr& expression) + ExpressionCategory GetExpressionCategory(Expression& expression) { ShaderAstValueCategory visitor; return visitor.GetExpressionCategory(expression); diff --git a/include/Nazara/Shader/ShaderAstValidator.hpp b/include/Nazara/Shader/ShaderAstValidator.hpp index 90ec82c71..00d708d96 100644 --- a/include/Nazara/Shader/ShaderAstValidator.hpp +++ b/include/Nazara/Shader/ShaderAstValidator.hpp @@ -8,66 +8,62 @@ #define NAZARA_SHADERVALIDATOR_HPP #include -#include -#include #include -#include +#include #include -#include +#include -namespace Nz +namespace Nz::ShaderAst { - class NAZARA_SHADER_API ShaderAstValidator : public ShaderAstRecursiveVisitor, public ShaderVarVisitor + class NAZARA_SHADER_API AstValidator : public AstRecursiveVisitor { public: - inline ShaderAstValidator(const ShaderAst& shader); - ShaderAstValidator(const ShaderAstValidator&) = delete; - ShaderAstValidator(ShaderAstValidator&&) = delete; - ~ShaderAstValidator() = default; + inline AstValidator(); + AstValidator(const AstValidator&) = delete; + AstValidator(AstValidator&&) = delete; + ~AstValidator() = default; - bool Validate(std::string* error = nullptr); + bool Validate(StatementPtr& node, std::string* error = nullptr, AstCache* cache = nullptr); private: - const ShaderNodes::ExpressionPtr& MandatoryExpr(const ShaderNodes::ExpressionPtr& node); - const ShaderNodes::NodePtr& MandatoryNode(const ShaderNodes::NodePtr& node); - void TypeMustMatch(const ShaderNodes::ExpressionPtr& left, const ShaderNodes::ExpressionPtr& right); + Expression& MandatoryExpr(ExpressionPtr& node); + Statement& MandatoryStatement(StatementPtr& node); + void TypeMustMatch(ExpressionPtr& left, ExpressionPtr& right); void TypeMustMatch(const ShaderExpressionType& left, const ShaderExpressionType& right); - const ShaderAst::StructMember& CheckField(const std::string& structName, std::size_t* memberIndex, std::size_t remainingMembers); + ShaderExpressionType CheckField(const std::string& structName, const std::string* memberIdentifier, std::size_t remainingMembers); - using ShaderAstRecursiveVisitor::Visit; - void Visit(ShaderNodes::AccessMember& node) override; - void Visit(ShaderNodes::AssignOp& node) override; - void Visit(ShaderNodes::BinaryOp& node) override; - void Visit(ShaderNodes::Branch& node) override; - void Visit(ShaderNodes::Cast& node) override; - void Visit(ShaderNodes::ConditionalExpression& node) override; - void Visit(ShaderNodes::ConditionalStatement& node) override; - void Visit(ShaderNodes::Constant& node) override; - void Visit(ShaderNodes::DeclareVariable& node) override; - void Visit(ShaderNodes::ExpressionStatement& node) override; - void Visit(ShaderNodes::Identifier& node) override; - void Visit(ShaderNodes::IntrinsicCall& node) override; - void Visit(ShaderNodes::ReturnStatement& node) override; - void Visit(ShaderNodes::Sample2D& node) override; - void Visit(ShaderNodes::StatementBlock& node) override; - void Visit(ShaderNodes::SwizzleOp& node) override; + AstCache::Scope& EnterScope(); + void ExitScope(); - using ShaderVarVisitor::Visit; - void Visit(ShaderNodes::BuiltinVariable& var) override; - void Visit(ShaderNodes::InputVariable& var) override; - void Visit(ShaderNodes::LocalVariable& var) override; - void Visit(ShaderNodes::OutputVariable& var) override; - void Visit(ShaderNodes::ParameterVariable& var) override; - void Visit(ShaderNodes::UniformVariable& var) override; + void RegisterExpressionType(Expression& node, ShaderExpressionType expressionType); + void RegisterScope(Node& node); + + void Visit(AccessMemberExpression& node) override; + void Visit(AssignExpression& node) override; + void Visit(BinaryExpression& node) override; + void Visit(CastExpression& node) override; + void Visit(ConditionalExpression& node) override; + void Visit(ConstantExpression& node) override; + void Visit(IdentifierExpression& node) override; + void Visit(IntrinsicExpression& node) override; + void Visit(SwizzleExpression& node) override; + + void Visit(BranchStatement& node) override; + void Visit(ConditionalStatement& node) override; + void Visit(DeclareFunctionStatement& node) override; + void Visit(DeclareStructStatement& node) override; + void Visit(DeclareVariableStatement& node) override; + void Visit(ExpressionStatement& node) override; + void Visit(MultiStatement& node) override; + void Visit(ReturnStatement& node) override; struct Context; - const ShaderAst& m_shader; Context* m_context; }; - NAZARA_SHADER_API bool ValidateShader(const ShaderAst& shader, std::string* error = nullptr); + NAZARA_SHADER_API bool ValidateAst(StatementPtr& node, std::string* error = nullptr, AstCache* cache = nullptr); } #include diff --git a/include/Nazara/Shader/ShaderAstValidator.inl b/include/Nazara/Shader/ShaderAstValidator.inl index eed116766..2020badd4 100644 --- a/include/Nazara/Shader/ShaderAstValidator.inl +++ b/include/Nazara/Shader/ShaderAstValidator.inl @@ -5,10 +5,10 @@ #include #include -namespace Nz +namespace Nz::ShaderAst { - ShaderAstValidator::ShaderAstValidator(const ShaderAst& shader) : - m_shader(shader) + AstValidator::AstValidator() : + m_context(nullptr) { } } diff --git a/include/Nazara/Shader/ShaderAstVisitor.hpp b/include/Nazara/Shader/ShaderAstVisitor.hpp deleted file mode 100644 index 183a58f92..000000000 --- a/include/Nazara/Shader/ShaderAstVisitor.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// 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_SHADERASTVISITOR_HPP -#define NAZARA_SHADERASTVISITOR_HPP - -#include -#include -#include - -namespace Nz -{ - class NAZARA_SHADER_API ShaderAstVisitor - { - public: - ShaderAstVisitor() = default; - ShaderAstVisitor(const ShaderAstVisitor&) = delete; - ShaderAstVisitor(ShaderAstVisitor&&) = delete; - virtual ~ShaderAstVisitor(); - - void Visit(const ShaderNodes::NodePtr& node); - virtual void Visit(ShaderNodes::AccessMember& node) = 0; - virtual void Visit(ShaderNodes::AssignOp& node) = 0; - virtual void Visit(ShaderNodes::BinaryOp& node) = 0; - virtual void Visit(ShaderNodes::Branch& node) = 0; - virtual void Visit(ShaderNodes::Cast& node) = 0; - virtual void Visit(ShaderNodes::ConditionalExpression& node) = 0; - virtual void Visit(ShaderNodes::ConditionalStatement& node) = 0; - virtual void Visit(ShaderNodes::Constant& node) = 0; - virtual void Visit(ShaderNodes::DeclareVariable& node) = 0; - virtual void Visit(ShaderNodes::Discard& node) = 0; - virtual void Visit(ShaderNodes::ExpressionStatement& node) = 0; - virtual void Visit(ShaderNodes::Identifier& node) = 0; - virtual void Visit(ShaderNodes::IntrinsicCall& node) = 0; - virtual void Visit(ShaderNodes::NoOp& node) = 0; - virtual void Visit(ShaderNodes::ReturnStatement& node) = 0; - virtual void Visit(ShaderNodes::Sample2D& node) = 0; - virtual void Visit(ShaderNodes::StatementBlock& node) = 0; - virtual void Visit(ShaderNodes::SwizzleOp& node) = 0; - - ShaderAstVisitor& operator=(const ShaderAstVisitor&) = delete; - ShaderAstVisitor& operator=(ShaderAstVisitor&&) = delete; - }; -} - -#endif diff --git a/include/Nazara/Shader/ShaderAstVisitorExcept.hpp b/include/Nazara/Shader/ShaderAstVisitorExcept.hpp deleted file mode 100644 index 5076284fe..000000000 --- a/include/Nazara/Shader/ShaderAstVisitorExcept.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// 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_SHADERASTVISITOREXCEPT_HPP -#define NAZARA_SHADERASTVISITOREXCEPT_HPP - -#include -#include -#include - -namespace Nz -{ - class NAZARA_SHADER_API ShaderAstVisitorExcept : public ShaderAstVisitor - { - public: - using ShaderAstVisitor::Visit; - void Visit(ShaderNodes::AccessMember& node) override; - void Visit(ShaderNodes::AssignOp& node) override; - void Visit(ShaderNodes::BinaryOp& node) override; - void Visit(ShaderNodes::Branch& node) override; - void Visit(ShaderNodes::Cast& node) override; - void Visit(ShaderNodes::ConditionalExpression& node) override; - void Visit(ShaderNodes::ConditionalStatement& node) override; - void Visit(ShaderNodes::Constant& node) override; - void Visit(ShaderNodes::DeclareVariable& node) override; - void Visit(ShaderNodes::Discard& node) override; - void Visit(ShaderNodes::ExpressionStatement& node) override; - void Visit(ShaderNodes::Identifier& node) override; - void Visit(ShaderNodes::IntrinsicCall& node) override; - void Visit(ShaderNodes::NoOp& node) override; - void Visit(ShaderNodes::ReturnStatement& node) override; - void Visit(ShaderNodes::Sample2D& node) override; - void Visit(ShaderNodes::StatementBlock& node) override; - void Visit(ShaderNodes::SwizzleOp& node) override; - }; -} - -#endif diff --git a/include/Nazara/Shader/ShaderBuilder.hpp b/include/Nazara/Shader/ShaderBuilder.hpp index 61dab693e..6a18b25ed 100644 --- a/include/Nazara/Shader/ShaderBuilder.hpp +++ b/include/Nazara/Shader/ShaderBuilder.hpp @@ -13,70 +13,60 @@ namespace Nz::ShaderBuilder { - template - struct AssignOpBuilder + namespace Impl { - constexpr AssignOpBuilder() = default; + struct Binary + { + inline std::unique_ptr operator()(ShaderAst::BinaryType op, ShaderAst::ExpressionPtr left, ShaderAst::ExpressionPtr right) const; + }; - std::shared_ptr operator()(const ShaderNodes::ExpressionPtr& left, const ShaderNodes::ExpressionPtr& right) const; - }; + struct Branch + { + inline std::unique_ptr operator()(ShaderAst::ExpressionPtr condition, ShaderAst::StatementPtr truePath, ShaderAst::StatementPtr falsePath = nullptr) const; + inline std::unique_ptr operator()(std::vector condStatements, ShaderAst::StatementPtr elseStatement = nullptr) const; + }; - template - struct BinOpBuilder - { - constexpr BinOpBuilder() = default; + struct Constant + { + inline std::unique_ptr operator()(ShaderConstantValue value) const; + }; - std::shared_ptr operator()(const ShaderNodes::ExpressionPtr& left, const ShaderNodes::ExpressionPtr& right) const; - }; + struct DeclareFunction + { + inline std::unique_ptr operator()(std::string name, std::vector parameters, std::vector statements, ShaderAst::ShaderExpressionType returnType = ShaderAst::BasicType::Void) const; + }; - struct BuiltinBuilder - { - constexpr BuiltinBuilder() = default; + struct DeclareVariable + { + inline std::unique_ptr operator()(std::string name, ShaderAst::ShaderExpressionType type, ShaderAst::ExpressionPtr initialValue = nullptr) const; + }; - inline std::shared_ptr operator()(ShaderNodes::BuiltinEntry builtin) const; - }; + struct Identifier + { + inline std::unique_ptr operator()(std::string name) const; + }; - template - struct GenBuilder - { - constexpr GenBuilder() = default; + struct Return + { + inline std::unique_ptr operator()(ShaderAst::ExpressionPtr expr = nullptr) const; + }; - template std::shared_ptr operator()(Args&&... args) const; - }; + template + struct NoParam + { + std::unique_ptr operator()() const; + }; + } - constexpr GenBuilder AccessMember; - constexpr BinOpBuilder Add; - constexpr AssignOpBuilder Assign; - constexpr BuiltinBuilder Builtin; - constexpr GenBuilder Block; - constexpr GenBuilder Branch; - constexpr GenBuilder ConditionalExpression; - constexpr GenBuilder ConditionalStatement; - constexpr GenBuilder Constant; - constexpr GenBuilder DeclareVariable; - constexpr GenBuilder Discard; - constexpr BinOpBuilder Division; - constexpr BinOpBuilder Equal; - constexpr BinOpBuilder GreaterThan; - constexpr BinOpBuilder GreaterThanOrEqual; - constexpr BinOpBuilder LessThan; - constexpr BinOpBuilder LessThanOrEqual; - constexpr BinOpBuilder NotEqual; - constexpr GenBuilder ExprStatement; - constexpr GenBuilder Identifier; - constexpr GenBuilder IntrinsicCall; - constexpr GenBuilder Input; - constexpr GenBuilder Local; - constexpr BinOpBuilder Multiply; - constexpr GenBuilder Output; - constexpr GenBuilder Parameter; - constexpr GenBuilder Sample2D; - constexpr GenBuilder StatementBlock; - constexpr GenBuilder Swizzle; - constexpr BinOpBuilder Subtract; - constexpr GenBuilder Uniform; - - template std::shared_ptr Cast(Args&&... args); + constexpr Impl::Binary Binary; + constexpr Impl::Branch Branch; + constexpr Impl::Constant Constant; + constexpr Impl::DeclareFunction DeclareFunction; + constexpr Impl::DeclareVariable DeclareVariable; + constexpr Impl::NoParam Discard; + constexpr Impl::Identifier Identifier; + constexpr Impl::NoParam NoOp; + constexpr Impl::Return Return; } #include diff --git a/include/Nazara/Shader/ShaderBuilder.inl b/include/Nazara/Shader/ShaderBuilder.inl index c3221c84f..ef7e89849 100644 --- a/include/Nazara/Shader/ShaderBuilder.inl +++ b/include/Nazara/Shader/ShaderBuilder.inl @@ -7,45 +7,87 @@ namespace Nz::ShaderBuilder { + inline std::unique_ptr Impl::Binary::operator()(ShaderAst::BinaryType op, ShaderAst::ExpressionPtr left, ShaderAst::ExpressionPtr right) const + { + auto constantNode = std::make_unique(); + constantNode->op = op; + constantNode->left = std::move(left); + constantNode->right = std::move(right); + + return constantNode; + } + + inline std::unique_ptr Impl::Branch::operator()(ShaderAst::ExpressionPtr condition, ShaderAst::StatementPtr truePath, ShaderAst::StatementPtr falsePath) const + { + auto branchNode = std::make_unique(); + + auto& condStatement = branchNode->condStatements.emplace_back(); + condStatement.condition = std::move(condition); + condStatement.statement = std::move(truePath); + + branchNode->elseStatement = std::move(falsePath); + + return branchNode; + } + + inline std::unique_ptr Impl::Branch::operator()(std::vector condStatements, ShaderAst::StatementPtr elseStatement) const + { + auto branchNode = std::make_unique(); + branchNode->condStatements = std::move(condStatements); + branchNode->elseStatement = std::move(elseStatement); + + return branchNode; + } + + inline std::unique_ptr Impl::Constant::operator()(ShaderConstantValue value) const + { + auto constantNode = std::make_unique(); + constantNode->value = std::move(value); + + return constantNode; + } + + inline std::unique_ptr Impl::DeclareFunction::operator()(std::string name, std::vector parameters, std::vector statements, ShaderAst::ShaderExpressionType returnType) const + { + auto declareFunctionNode = std::make_unique(); + declareFunctionNode->name = std::move(name); + declareFunctionNode->parameters = std::move(parameters); + declareFunctionNode->returnType = std::move(returnType); + declareFunctionNode->statements = std::move(statements); + + return declareFunctionNode; + } + + inline std::unique_ptr Nz::ShaderBuilder::Impl::DeclareVariable::operator()(std::string name, ShaderAst::ShaderExpressionType type, ShaderAst::ExpressionPtr initialValue) const + { + auto declareVariableNode = std::make_unique(); + declareVariableNode->varName = std::move(name); + declareVariableNode->varType = std::move(type); + declareVariableNode->initialExpression = std::move(initialValue); + + return declareVariableNode; + } + + inline std::unique_ptr Impl::Identifier::operator()(std::string name) const + { + auto identifierNode = std::make_unique(); + identifierNode->identifier = std::move(name); + + return identifierNode; + } + + inline std::unique_ptr Impl::Return::operator()(ShaderAst::ExpressionPtr expr) const + { + auto returnNode = std::make_unique(); + returnNode->returnExpr = std::move(expr); + + return returnNode; + } + template - template - std::shared_ptr GenBuilder::operator()(Args&&... args) const + std::unique_ptr Impl::NoParam::operator()() const { - return T::Build(std::forward(args)...); - } - - template - std::shared_ptr AssignOpBuilder::operator()(const ShaderNodes::ExpressionPtr& left, const ShaderNodes::ExpressionPtr& right) const - { - return ShaderNodes::AssignOp::Build(op, left, right); - } - - template - std::shared_ptr BinOpBuilder::operator()(const ShaderNodes::ExpressionPtr& left, const ShaderNodes::ExpressionPtr& right) const - { - return ShaderNodes::BinaryOp::Build(op, left, right); - } - - inline std::shared_ptr BuiltinBuilder::operator()(ShaderNodes::BuiltinEntry builtin) const - { - ShaderNodes::BasicType exprType = ShaderNodes::BasicType::Void; - - switch (builtin) - { - case ShaderNodes::BuiltinEntry::VertexPosition: - exprType = ShaderNodes::BasicType::Float4; - break; - } - - NazaraAssert(exprType != ShaderNodes::BasicType::Void, "Unhandled builtin"); - - return ShaderNodes::BuiltinVariable::Build(builtin, exprType); - } - - template - std::shared_ptr Cast(Args&&... args) - { - return ShaderNodes::Cast::Build(Type, std::forward(args)...); + return std::make_unique(); } } diff --git a/include/Nazara/Shader/ShaderEnums.hpp b/include/Nazara/Shader/ShaderEnums.hpp index 87f2f4cd7..f5182c243 100644 --- a/include/Nazara/Shader/ShaderEnums.hpp +++ b/include/Nazara/Shader/ShaderEnums.hpp @@ -9,7 +9,7 @@ #include -namespace Nz::ShaderNodes +namespace Nz::ShaderAst { enum class AssignType { @@ -77,35 +77,9 @@ namespace Nz::ShaderNodes { None = -1, - AccessMember, - AssignOp, - BinaryOp, - Branch, - Cast, - Constant, - ConditionalExpression, - ConditionalStatement, - DeclareVariable, - Discard, - ExpressionStatement, - Identifier, - IntrinsicCall, - NoOp, - ReturnStatement, - Sample2D, - SwizzleOp, - StatementBlock, - - Max = StatementBlock - }; - - enum class SsaInstruction - { - OpAdd, - OpDiv, - OpMul, - OpSub, - OpSample +#define NAZARA_SHADERAST_NODE(Node) Node, +#define NAZARA_SHADERAST_STATEMENT_LAST(Node) Node, Max = Node +#include }; enum class SwizzleComponent @@ -127,6 +101,11 @@ namespace Nz::ShaderNodes ParameterVariable, UniformVariable }; + + inline std::size_t GetComponentCount(BasicType type); + inline BasicType GetComponentType(BasicType type); } +#include + #endif // NAZARA_SHADER_ENUMS_HPP diff --git a/include/Nazara/Shader/ShaderEnums.inl b/include/Nazara/Shader/ShaderEnums.inl new file mode 100644 index 000000000..fbd01ad49 --- /dev/null +++ b/include/Nazara/Shader/ShaderEnums.inl @@ -0,0 +1,57 @@ +// 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 +#include + +namespace Nz::ShaderAst +{ + inline std::size_t GetComponentCount(BasicType type) + { + switch (type) + { + case BasicType::Float2: + case BasicType::Int2: + return 2; + + case BasicType::Float3: + case BasicType::Int3: + return 3; + + case BasicType::Float4: + case BasicType::Int4: + return 4; + + case BasicType::Mat4x4: + return 4; + + default: + return 1; + } + } + + inline BasicType GetComponentType(BasicType type) + { + switch (type) + { + case BasicType::Float2: + case BasicType::Float3: + case BasicType::Float4: + return BasicType::Float1; + + case BasicType::Int2: + case BasicType::Int3: + case BasicType::Int4: + return BasicType::Int1; + + case BasicType::Mat4x4: + return BasicType::Float4; + + default: + return type; + } + } +} + +#include diff --git a/include/Nazara/Shader/ShaderLangParser.hpp b/include/Nazara/Shader/ShaderLangParser.hpp index 6b3d296a3..0588ecc44 100644 --- a/include/Nazara/Shader/ShaderLangParser.hpp +++ b/include/Nazara/Shader/ShaderLangParser.hpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include namespace Nz::ShaderLang { @@ -44,7 +44,7 @@ namespace Nz::ShaderLang inline Parser(); ~Parser() = default; - ShaderAst Parse(const std::vector& tokens); + ShaderAst::StatementPtr Parse(const std::vector& tokens); private: // Flow control @@ -54,29 +54,30 @@ namespace Nz::ShaderLang const Token& PeekNext(); // Statements - ShaderNodes::StatementPtr ParseFunctionBody(); - void ParseFunctionDeclaration(); - ShaderAst::FunctionParameter ParseFunctionParameter(); - ShaderNodes::StatementPtr ParseReturnStatement(); - ShaderNodes::StatementPtr ParseStatement(); - ShaderNodes::StatementPtr ParseStatementList(); + std::vector ParseFunctionBody(); + ShaderAst::StatementPtr ParseFunctionDeclaration(); + ShaderAst::DeclareFunctionStatement::Parameter ParseFunctionParameter(); + ShaderAst::StatementPtr ParseReturnStatement(); + ShaderAst::StatementPtr ParseStatement(); + std::vector ParseStatementList(); + ShaderAst::StatementPtr ParseVariableDeclaration(); // Expressions - ShaderNodes::ExpressionPtr ParseBinOpRhs(int exprPrecedence, ShaderNodes::ExpressionPtr lhs); - ShaderNodes::ExpressionPtr ParseExpression(); - ShaderNodes::ExpressionPtr ParseIdentifier(); - ShaderNodes::ExpressionPtr ParseIntegerExpression(); - ShaderNodes::ExpressionPtr ParseParenthesisExpression(); - ShaderNodes::ExpressionPtr ParsePrimaryExpression(); + ShaderAst::ExpressionPtr ParseBinOpRhs(int exprPrecedence, ShaderAst::ExpressionPtr lhs); + ShaderAst::ExpressionPtr ParseExpression(); + ShaderAst::ExpressionPtr ParseIdentifier(); + ShaderAst::ExpressionPtr ParseIntegerExpression(); + ShaderAst::ExpressionPtr ParseParenthesisExpression(); + ShaderAst::ExpressionPtr ParsePrimaryExpression(); std::string ParseIdentifierAsName(); - ShaderExpressionType ParseIdentifierAsType(); + ShaderAst::ShaderExpressionType ParseIdentifierAsType(); static int GetTokenPrecedence(TokenType token); struct Context { - ShaderAst result; + std::unique_ptr root; std::size_t tokenCount; std::size_t tokenIndex = 0; const Token* tokens; diff --git a/include/Nazara/Shader/ShaderLangTokenList.hpp b/include/Nazara/Shader/ShaderLangTokenList.hpp index caaa2964d..d8eb56139 100644 --- a/include/Nazara/Shader/ShaderLangTokenList.hpp +++ b/include/Nazara/Shader/ShaderLangTokenList.hpp @@ -6,10 +6,11 @@ #error You must define NAZARA_SHADERLANG_TOKEN before including this file #endif -#ifndef NAZARA_SHADERLANG_TOKENT_LAST +#ifndef NAZARA_SHADERLANG_TOKEN_LAST #define NAZARA_SHADERLANG_TOKEN_LAST(X) NAZARA_SHADERLANG_TOKEN(X) #endif +NAZARA_SHADERLANG_TOKEN(Assign) NAZARA_SHADERLANG_TOKEN(BoolFalse) NAZARA_SHADERLANG_TOKEN(BoolTrue) NAZARA_SHADERLANG_TOKEN(ClosingParenthesis) @@ -24,6 +25,7 @@ NAZARA_SHADERLANG_TOKEN(FunctionDeclaration) NAZARA_SHADERLANG_TOKEN(FunctionReturn) NAZARA_SHADERLANG_TOKEN(IntegerValue) NAZARA_SHADERLANG_TOKEN(Identifier) +NAZARA_SHADERLANG_TOKEN(Let) NAZARA_SHADERLANG_TOKEN(Multiply) NAZARA_SHADERLANG_TOKEN(Minus) NAZARA_SHADERLANG_TOKEN(Plus) diff --git a/include/Nazara/Shader/ShaderNodes.hpp b/include/Nazara/Shader/ShaderNodes.hpp index 0d1d57183..7aeef561c 100644 --- a/include/Nazara/Shader/ShaderNodes.hpp +++ b/include/Nazara/Shader/ShaderNodes.hpp @@ -14,308 +14,245 @@ #include #include #include -#include -#include +#include #include #include #include #include -namespace Nz +namespace Nz::ShaderAst { - class ShaderAstVisitor; + class AstExpressionVisitor; + class AstStatementVisitor; - namespace ShaderNodes + struct NAZARA_SHADER_API Node { - class Node; + Node() = default; + Node(const Node&) = delete; + Node(Node&&) noexcept = default; + virtual ~Node(); - using NodePtr = std::shared_ptr; + virtual NodeType GetType() const = 0; - class NAZARA_SHADER_API Node + Node& operator=(const Node&) = delete; + Node& operator=(Node&&) noexcept = default; + }; + + // Expressions + + struct Expression; + + using ExpressionPtr = std::unique_ptr; + + struct NAZARA_SHADER_API Expression : Node + { + Expression() = default; + Expression(const Expression&) = delete; + Expression(Expression&&) noexcept = default; + ~Expression() = default; + + virtual void Visit(AstExpressionVisitor& visitor) = 0; + + Expression& operator=(const Expression&) = delete; + Expression& operator=(Expression&&) noexcept = default; + }; + + struct NAZARA_SHADER_API AccessMemberExpression : public Expression + { + NodeType GetType() const override; + void Visit(AstExpressionVisitor& visitor) override; + + ExpressionPtr structExpr; + std::vector memberIdentifiers; + }; + + struct NAZARA_SHADER_API AssignExpression : public Expression + { + NodeType GetType() const override; + void Visit(AstExpressionVisitor& visitor) override; + + AssignType op; + ExpressionPtr left; + ExpressionPtr right; + }; + + struct NAZARA_SHADER_API BinaryExpression : public Expression + { + NodeType GetType() const override; + void Visit(AstExpressionVisitor& visitor) override; + + BinaryType op; + ExpressionPtr left; + ExpressionPtr right; + }; + + struct NAZARA_SHADER_API CastExpression : public Expression + { + NodeType GetType() const override; + void Visit(AstExpressionVisitor& visitor) override; + + BasicType targetType; + std::array expressions; + }; + + struct NAZARA_SHADER_API ConditionalExpression : public Expression + { + NodeType GetType() const override; + void Visit(AstExpressionVisitor& visitor) override; + + std::string conditionName; + ExpressionPtr falsePath; + ExpressionPtr truePath; + }; + + struct NAZARA_SHADER_API ConstantExpression : public Expression + { + NodeType GetType() const override; + void Visit(AstExpressionVisitor& visitor) override; + + ShaderConstantValue value; + }; + + struct NAZARA_SHADER_API IdentifierExpression : public Expression + { + NodeType GetType() const override; + void Visit(AstExpressionVisitor& visitor) override; + + std::string identifier; + }; + + struct NAZARA_SHADER_API IntrinsicExpression : public Expression + { + NodeType GetType() const override; + void Visit(AstExpressionVisitor& visitor) override; + + IntrinsicType intrinsic; + std::vector parameters; + }; + + struct NAZARA_SHADER_API SwizzleExpression : public Expression + { + NodeType GetType() const override; + void Visit(AstExpressionVisitor& visitor) override; + + std::array components; + std::size_t componentCount; + ExpressionPtr expression; + }; + + // Statements + + struct Statement; + + using StatementPtr = std::unique_ptr; + + struct NAZARA_SHADER_API Statement : Node + { + Statement() = default; + Statement(const Statement&) = delete; + Statement(Statement&&) noexcept = default; + ~Statement() = default; + + virtual void Visit(AstStatementVisitor& visitor) = 0; + + Statement& operator=(const Statement&) = delete; + Statement& operator=(Statement&&) noexcept = default; + }; + + struct NAZARA_SHADER_API BranchStatement : public Statement + { + NodeType GetType() const override; + void Visit(AstStatementVisitor& visitor) override; + + struct ConditionalStatement { - public: - virtual ~Node(); - - inline NodeType GetType() const; - inline bool IsStatement() const; - - virtual void Visit(ShaderAstVisitor& visitor) = 0; - - static inline unsigned int GetComponentCount(BasicType type); - static inline BasicType GetComponentType(BasicType type); - - protected: - inline Node(NodeType type, bool isStatement); - - private: - NodeType m_type; - bool m_isStatement; - }; - - class Expression; - - using ExpressionPtr = std::shared_ptr; - - class NAZARA_SHADER_API Expression : public Node, public std::enable_shared_from_this - { - public: - inline Expression(NodeType type); - - virtual ShaderExpressionType GetExpressionType() const = 0; + ExpressionPtr condition; + StatementPtr statement; }; - class Statement; + std::vector condStatements; + StatementPtr elseStatement; + }; - using StatementPtr = std::shared_ptr; + struct NAZARA_SHADER_API ConditionalStatement : Statement + { + NodeType GetType() const override; + void Visit(AstStatementVisitor& visitor) override; - class NAZARA_SHADER_API Statement : public Node, public std::enable_shared_from_this + std::string conditionName; + StatementPtr statement; + }; + + struct NAZARA_SHADER_API DeclareFunctionStatement : Statement + { + NodeType GetType() const override; + void Visit(AstStatementVisitor& visitor) override; + + struct Parameter { - public: - inline Statement(NodeType type); + std::string name; + ShaderExpressionType type; }; - struct NAZARA_SHADER_API ExpressionStatement : public Statement - { - inline ExpressionStatement(); - - void Visit(ShaderAstVisitor& visitor) override; - - ExpressionPtr expression; - - static inline std::shared_ptr Build(ExpressionPtr expr); - }; - - ////////////////////////////////////////////////////////////////////////// - - struct NAZARA_SHADER_API ConditionalStatement : public Statement - { - inline ConditionalStatement(); - - void Visit(ShaderAstVisitor& visitor) override; - - std::string conditionName; - StatementPtr statement; - - static inline std::shared_ptr Build(std::string condition, StatementPtr statementPtr); - }; - - struct NAZARA_SHADER_API StatementBlock : public Statement - { - inline StatementBlock(); - - void Visit(ShaderAstVisitor& visitor) override; - - std::vector statements; - - static inline std::shared_ptr Build(std::vector statements); - template static std::shared_ptr Build(Args&&... args); - }; - - struct NAZARA_SHADER_API DeclareVariable : public Statement - { - inline DeclareVariable(); - - void Visit(ShaderAstVisitor& visitor) override; - - ExpressionPtr expression; - VariablePtr variable; - - static inline std::shared_ptr Build(VariablePtr variable, ExpressionPtr expression = nullptr); - }; - - struct NAZARA_SHADER_API Discard : public Statement - { - inline Discard(); - - void Visit(ShaderAstVisitor& visitor) override; - - static inline std::shared_ptr Build(); - }; - - struct NAZARA_SHADER_API Identifier : public Expression - { - inline Identifier(); - - ShaderExpressionType GetExpressionType() const override; - void Visit(ShaderAstVisitor& visitor) override; - - VariablePtr var; - - static inline std::shared_ptr Build(VariablePtr variable); - }; - - struct NAZARA_SHADER_API AccessMember : public Expression - { - inline AccessMember(); - - ShaderExpressionType GetExpressionType() const override; - void Visit(ShaderAstVisitor& visitor) override; - - ExpressionPtr structExpr; - ShaderExpressionType exprType; - std::vector memberIndices; - - static inline std::shared_ptr Build(ExpressionPtr structExpr, std::size_t memberIndex, ShaderExpressionType exprType); - static inline std::shared_ptr Build(ExpressionPtr structExpr, std::vector memberIndices, ShaderExpressionType exprType); - }; - - struct NAZARA_SHADER_API NoOp : public Statement - { - inline NoOp(); - - void Visit(ShaderAstVisitor& visitor) override; - - static inline std::shared_ptr Build(); - }; - - struct NAZARA_SHADER_API ReturnStatement : public Statement - { - inline ReturnStatement(); - - void Visit(ShaderAstVisitor& visitor) override; - - ExpressionPtr returnExpr; - - static inline std::shared_ptr Build(ExpressionPtr expr = nullptr); - }; - - ////////////////////////////////////////////////////////////////////////// - - struct NAZARA_SHADER_API AssignOp : public Expression - { - inline AssignOp(); - - ShaderExpressionType GetExpressionType() const override; - void Visit(ShaderAstVisitor& visitor) override; - - AssignType op; - ExpressionPtr left; - ExpressionPtr right; - - static inline std::shared_ptr Build(AssignType op, ExpressionPtr left, ExpressionPtr right); - }; - - struct NAZARA_SHADER_API BinaryOp : public Expression - { - inline BinaryOp(); - - ShaderExpressionType GetExpressionType() const override; - void Visit(ShaderAstVisitor& visitor) override; - - BinaryType op; - ExpressionPtr left; - ExpressionPtr right; - - static inline std::shared_ptr Build(BinaryType op, ExpressionPtr left, ExpressionPtr right); - }; - - struct NAZARA_SHADER_API Branch : public Statement - { - struct ConditionalStatement; - - inline Branch(); - - void Visit(ShaderAstVisitor& visitor) override; - - std::vector condStatements; - StatementPtr elseStatement; - - struct ConditionalStatement - { - ExpressionPtr condition; - StatementPtr statement; - }; - - static inline std::shared_ptr Build(ExpressionPtr condition, StatementPtr trueStatement, StatementPtr falseStatement = nullptr); - static inline std::shared_ptr Build(std::vector statements, StatementPtr elseStatement = nullptr); - }; - - struct NAZARA_SHADER_API Cast : public Expression - { - inline Cast(); - - ShaderExpressionType GetExpressionType() const override; - void Visit(ShaderAstVisitor& visitor) override; - - BasicType exprType; - std::array expressions; - - static inline std::shared_ptr Build(BasicType castTo, ExpressionPtr first, ExpressionPtr second = nullptr, ExpressionPtr third = nullptr, ExpressionPtr fourth = nullptr); - static inline std::shared_ptr Build(BasicType castTo, ExpressionPtr* expressions, std::size_t expressionCount); - }; - - struct NAZARA_SHADER_API ConditionalExpression : public Expression - { - inline ConditionalExpression(); - - ShaderExpressionType GetExpressionType() const override; - void Visit(ShaderAstVisitor& visitor) override; - - std::string conditionName; - ExpressionPtr falsePath; - ExpressionPtr truePath; - - static inline std::shared_ptr Build(std::string condition, ExpressionPtr truePath, ExpressionPtr falsePath); - }; - - struct NAZARA_SHADER_API Constant : public Expression - { - inline Constant(); - - ShaderExpressionType GetExpressionType() const override; - void Visit(ShaderAstVisitor& visitor) override; - - ShaderConstantValue value; - - template static std::shared_ptr Build(const T& value); - }; - - struct NAZARA_SHADER_API SwizzleOp : public Expression - { - inline SwizzleOp(); - - ShaderExpressionType GetExpressionType() const override; - void Visit(ShaderAstVisitor& visitor) override; - - std::array components; - std::size_t componentCount; - ExpressionPtr expression; - - static inline std::shared_ptr Build(ExpressionPtr expressionPtr, SwizzleComponent swizzleComponent); - static inline std::shared_ptr Build(ExpressionPtr expressionPtr, std::initializer_list swizzleComponents); - static inline std::shared_ptr Build(ExpressionPtr expressionPtr, const SwizzleComponent* components, std::size_t componentCount); - }; - - ////////////////////////////////////////////////////////////////////////// - - struct NAZARA_SHADER_API Sample2D : public Expression - { - inline Sample2D(); - - ShaderExpressionType GetExpressionType() const override; - void Visit(ShaderAstVisitor& visitor) override; - - ExpressionPtr sampler; - ExpressionPtr coordinates; - - static inline std::shared_ptr Build(ExpressionPtr samplerPtr, ExpressionPtr coordinatesPtr); - }; - - ////////////////////////////////////////////////////////////////////////// - - struct NAZARA_SHADER_API IntrinsicCall : public Expression - { - inline IntrinsicCall(); - - ShaderExpressionType GetExpressionType() const override; - void Visit(ShaderAstVisitor& visitor) override; - - IntrinsicType intrinsic; - std::vector parameters; - - static inline std::shared_ptr Build(IntrinsicType intrinsic, std::vector parameters); - }; - } + std::string name; + std::vector parameters; + std::vector statements; + ShaderExpressionType returnType = BasicType::Void; + }; + + struct NAZARA_SHADER_API DeclareStructStatement : Statement + { + NodeType GetType() const override; + void Visit(AstStatementVisitor& visitor) override; + + StructDescription description; + }; + + struct NAZARA_SHADER_API DeclareVariableStatement : Statement + { + NodeType GetType() const override; + void Visit(AstStatementVisitor& visitor) override; + + std::string varName; + ExpressionPtr initialExpression; + ShaderExpressionType varType; + }; + + struct NAZARA_SHADER_API DiscardStatement : Statement + { + NodeType GetType() const override; + void Visit(AstStatementVisitor& visitor) override; + }; + + struct NAZARA_SHADER_API ExpressionStatement : Statement + { + NodeType GetType() const override; + void Visit(AstStatementVisitor& visitor) override; + + ExpressionPtr expression; + }; + + struct NAZARA_SHADER_API MultiStatement : Statement + { + NodeType GetType() const override; + void Visit(AstStatementVisitor& visitor) override; + + std::vector statements; + }; + + struct NAZARA_SHADER_API NoOpStatement : Statement + { + NodeType GetType() const override; + void Visit(AstStatementVisitor& visitor) override; + }; + + struct NAZARA_SHADER_API ReturnStatement : Statement + { + NodeType GetType() const override; + void Visit(AstStatementVisitor& visitor) override; + + ExpressionPtr returnExpr; + }; } #include diff --git a/include/Nazara/Shader/ShaderNodes.inl b/include/Nazara/Shader/ShaderNodes.inl index c1e2b22c3..6c702a06e 100644 --- a/include/Nazara/Shader/ShaderNodes.inl +++ b/include/Nazara/Shader/ShaderNodes.inl @@ -5,394 +5,8 @@ #include #include -namespace Nz::ShaderNodes +namespace Nz::ShaderAst { - inline Node::Node(NodeType type, bool isStatement) : - m_type(type), - m_isStatement(isStatement) - { - } - - inline NodeType ShaderNodes::Node::GetType() const - { - return m_type; - } - - inline bool Node::IsStatement() const - { - return m_isStatement; - } - - inline unsigned int Node::GetComponentCount(BasicType type) - { - switch (type) - { - case BasicType::Float2: - case BasicType::Int2: - return 2; - - case BasicType::Float3: - case BasicType::Int3: - return 3; - - case BasicType::Float4: - case BasicType::Int4: - return 4; - - case BasicType::Mat4x4: - return 4; - - default: - return 1; - } - } - - inline BasicType Node::GetComponentType(BasicType type) - { - switch (type) - { - case BasicType::Float2: - case BasicType::Float3: - case BasicType::Float4: - return BasicType::Float1; - - case BasicType::Int2: - case BasicType::Int3: - case BasicType::Int4: - return BasicType::Int1; - - case BasicType::Mat4x4: - return BasicType::Float4; - - default: - return type; - } - } - - - inline Expression::Expression(NodeType type) : - Node(type, false) - { - } - - inline Statement::Statement(NodeType type) : - Node(type, true) - { - } - - - - inline ExpressionStatement::ExpressionStatement() : - Statement(NodeType::ExpressionStatement) - { - } - - inline std::shared_ptr ExpressionStatement::Build(ExpressionPtr expr) - { - auto node = std::make_shared(); - node->expression = std::move(expr); - - return node; - } - - inline ConditionalStatement::ConditionalStatement() : - Statement(NodeType::ConditionalStatement) - { - } - - inline std::shared_ptr ConditionalStatement::Build(std::string condition, StatementPtr statementPtr) - { - auto node = std::make_shared(); - node->conditionName = std::move(condition); - node->statement = std::move(statementPtr); - - return node; - } - - - inline StatementBlock::StatementBlock() : - Statement(NodeType::StatementBlock) - { - } - - inline std::shared_ptr StatementBlock::Build(std::vector statements) - { - auto node = std::make_shared(); - node->statements = std::move(statements); - - return node; - } - - template - std::shared_ptr StatementBlock::Build(Args&&... args) - { - auto node = std::make_shared(); - node->statements = std::vector({ std::forward(args)... }); - - return node; - } - - - inline DeclareVariable::DeclareVariable() : - Statement(NodeType::DeclareVariable) - { - } - - inline std::shared_ptr DeclareVariable::Build(VariablePtr variable, ExpressionPtr expression) - { - auto node = std::make_shared(); - node->expression = std::move(expression); - node->variable = std::move(variable); - - return node; - } - - - inline Discard::Discard() : - Statement(NodeType::Discard) - { - } - - inline std::shared_ptr Discard::Build() - { - return std::make_shared(); - } - - - inline Identifier::Identifier() : - Expression(NodeType::Identifier) - { - } - - inline std::shared_ptr Identifier::Build(VariablePtr variable) - { - auto node = std::make_shared(); - node->var = std::move(variable); - - return node; - } - - - inline AccessMember::AccessMember() : - Expression(NodeType::AccessMember) - { - } - - inline std::shared_ptr AccessMember::Build(ExpressionPtr structExpr, std::size_t memberIndex, ShaderExpressionType exprType) - { - return Build(std::move(structExpr), std::vector{ memberIndex }, exprType); - } - - inline std::shared_ptr AccessMember::Build(ExpressionPtr structExpr, std::vector memberIndices, ShaderExpressionType exprType) - { - auto node = std::make_shared(); - node->exprType = std::move(exprType); - node->memberIndices = std::move(memberIndices); - node->structExpr = std::move(structExpr); - - return node; - } - - - inline NoOp::NoOp() : - Statement(NodeType::NoOp) - { - } - - inline std::shared_ptr NoOp::Build() - { - return std::make_shared(); - } - - - inline ReturnStatement::ReturnStatement() : - Statement(NodeType::ReturnStatement) - { - } - - inline std::shared_ptr ShaderNodes::ReturnStatement::Build(ExpressionPtr expr) - { - auto node = std::make_shared(); - node->returnExpr = std::move(expr); - - return node; - } - - - inline AssignOp::AssignOp() : - Expression(NodeType::AssignOp) - { - } - - inline std::shared_ptr AssignOp::Build(AssignType op, ExpressionPtr left, ExpressionPtr right) - { - auto node = std::make_shared(); - node->op = op; - node->left = std::move(left); - node->right = std::move(right); - - return node; - } - - - inline BinaryOp::BinaryOp() : - Expression(NodeType::BinaryOp) - { - } - - inline std::shared_ptr BinaryOp::Build(BinaryType op, ExpressionPtr left, ExpressionPtr right) - { - auto node = std::make_shared(); - node->op = op; - node->left = std::move(left); - node->right = std::move(right); - - return node; - } - - - inline Branch::Branch() : - Statement(NodeType::Branch) - { - } - - inline std::shared_ptr Branch::Build(ExpressionPtr condition, StatementPtr trueStatement, StatementPtr falseStatement) - { - auto node = std::make_shared(); - node->condStatements.emplace_back(ConditionalStatement{ std::move(condition), std::move(trueStatement) }); - node->elseStatement = std::move(falseStatement); - - return node; - } - - inline std::shared_ptr Branch::Build(std::vector statements, StatementPtr elseStatement) - { - auto node = std::make_shared(); - node->condStatements = std::move(statements); - node->elseStatement = std::move(elseStatement); - - return node; - } - - - inline Cast::Cast() : - Expression(NodeType::Cast) - { - } - - inline std::shared_ptr Cast::Build(BasicType castTo, ExpressionPtr first, ExpressionPtr second, ExpressionPtr third, ExpressionPtr fourth) - { - auto node = std::make_shared(); - node->exprType = castTo; - node->expressions = { {first, second, third, fourth} }; - - return node; - } - - inline std::shared_ptr Cast::Build(BasicType castTo, ExpressionPtr* Expressions, std::size_t expressionCount) - { - auto node = std::make_shared(); - node->exprType = castTo; - for (std::size_t i = 0; i < expressionCount; ++i) - node->expressions[i] = Expressions[i]; - - return node; - } - - inline ConditionalExpression::ConditionalExpression() : - Expression(NodeType::ConditionalExpression) - { - } - - inline std::shared_ptr ShaderNodes::ConditionalExpression::Build(std::string condition, ExpressionPtr truePath, ExpressionPtr falsePath) - { - auto node = std::make_shared(); - node->conditionName = std::move(condition); - node->falsePath = std::move(falsePath); - node->truePath = std::move(truePath); - - return node; - } - - inline Constant::Constant() : - Expression(NodeType::Constant) - { - } - - template - std::shared_ptr Nz::ShaderNodes::Constant::Build(const T& value) - { - auto node = std::make_shared(); - node->value = value; - - return node; - } - - - inline SwizzleOp::SwizzleOp() : - Expression(NodeType::SwizzleOp) - { - } - - inline std::shared_ptr SwizzleOp::Build(ExpressionPtr expressionPtr, SwizzleComponent swizzleComponent) - { - return Build(std::move(expressionPtr), { swizzleComponent }); - } - - inline std::shared_ptr SwizzleOp::Build(ExpressionPtr expressionPtr, std::initializer_list swizzleComponents) - { - auto node = std::make_shared(); - node->componentCount = swizzleComponents.size(); - node->expression = std::move(expressionPtr); - - std::copy(swizzleComponents.begin(), swizzleComponents.end(), node->components.begin()); - - return node; - } - - inline std::shared_ptr SwizzleOp::Build(ExpressionPtr expressionPtr, const SwizzleComponent* components, std::size_t componentCount) - { - auto node = std::make_shared(); - - assert(componentCount < node->components.size()); - - node->componentCount = componentCount; - node->expression = std::move(expressionPtr); - - std::copy(components, components + componentCount, node->components.begin()); - - return node; - } - - - inline Sample2D::Sample2D() : - Expression(NodeType::Sample2D) - { - } - - inline std::shared_ptr Sample2D::Build(ExpressionPtr samplerPtr, ExpressionPtr coordinatesPtr) - { - auto node = std::make_shared(); - node->coordinates = std::move(coordinatesPtr); - node->sampler = std::move(samplerPtr); - - return node; - } - - - inline IntrinsicCall::IntrinsicCall() : - Expression(NodeType::IntrinsicCall) - { - } - - inline std::shared_ptr IntrinsicCall::Build(IntrinsicType intrinsic, std::vector parameters) - { - auto node = std::make_shared(); - node->intrinsic = intrinsic; - node->parameters = std::move(parameters); - - return node; - } } #include diff --git a/include/Nazara/Shader/ShaderVarVisitor.hpp b/include/Nazara/Shader/ShaderVarVisitor.hpp deleted file mode 100644 index babfb2b1e..000000000 --- a/include/Nazara/Shader/ShaderVarVisitor.hpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (C) 2015 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_SHADERVARVISITOR_HPP -#define NAZARA_SHADERVARVISITOR_HPP - -#include -#include -#include - -namespace Nz -{ - class NAZARA_SHADER_API ShaderVarVisitor - { - public: - ShaderVarVisitor() = default; - ShaderVarVisitor(const ShaderVarVisitor&) = delete; - ShaderVarVisitor(ShaderVarVisitor&&) = delete; - virtual ~ShaderVarVisitor(); - - void Visit(const ShaderNodes::VariablePtr& node); - - virtual void Visit(ShaderNodes::BuiltinVariable& var) = 0; - virtual void Visit(ShaderNodes::InputVariable& var) = 0; - virtual void Visit(ShaderNodes::LocalVariable& var) = 0; - virtual void Visit(ShaderNodes::OutputVariable& var) = 0; - virtual void Visit(ShaderNodes::ParameterVariable& var) = 0; - virtual void Visit(ShaderNodes::UniformVariable& var) = 0; - - ShaderVarVisitor& operator=(const ShaderVarVisitor&) = delete; - ShaderVarVisitor& operator=(ShaderVarVisitor&&) = delete; - }; -} - -#endif diff --git a/include/Nazara/Shader/ShaderVarVisitorExcept.hpp b/include/Nazara/Shader/ShaderVarVisitorExcept.hpp deleted file mode 100644 index 3fa769e21..000000000 --- a/include/Nazara/Shader/ShaderVarVisitorExcept.hpp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (C) 2015 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_SHADERVARVISITOREXCEPT_HPP -#define NAZARA_SHADERVARVISITOREXCEPT_HPP - -#include -#include - -namespace Nz -{ - class NAZARA_SHADER_API ShaderVarVisitorExcept : public ShaderVarVisitor - { - public: - using ShaderVarVisitor::Visit; - void Visit(ShaderNodes::BuiltinVariable& var) override; - void Visit(ShaderNodes::InputVariable& var) override; - void Visit(ShaderNodes::LocalVariable& var) override; - void Visit(ShaderNodes::OutputVariable& var) override; - void Visit(ShaderNodes::ParameterVariable& var) override; - void Visit(ShaderNodes::UniformVariable& var) override; - }; -} - -#endif diff --git a/include/Nazara/Shader/ShaderVariables.hpp b/include/Nazara/Shader/ShaderVariables.hpp deleted file mode 100644 index eb0bc8ede..000000000 --- a/include/Nazara/Shader/ShaderVariables.hpp +++ /dev/null @@ -1,128 +0,0 @@ -// 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_VARIABLES_HPP -#define NAZARA_SHADER_VARIABLES_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Nz -{ - class ShaderVarVisitor; - - namespace ShaderNodes - { - struct Variable; - - using VariablePtr = std::shared_ptr; - - struct NAZARA_SHADER_API Variable : std::enable_shared_from_this - { - virtual ~Variable(); - - virtual VariableType GetType() const = 0; - virtual void Visit(ShaderVarVisitor& visitor) = 0; - - ShaderExpressionType type; - }; - - struct BuiltinVariable; - - using BuiltinVariablePtr = std::shared_ptr; - - struct NAZARA_SHADER_API BuiltinVariable : public Variable - { - BuiltinEntry entry; - - VariableType GetType() const override; - void Visit(ShaderVarVisitor& visitor) override; - - static inline std::shared_ptr Build(BuiltinEntry entry, ShaderExpressionType varType); - }; - - struct NamedVariable; - - using NamedVariablePtr = std::shared_ptr; - - struct NAZARA_SHADER_API NamedVariable : public Variable - { - std::string name; - }; - - struct InputVariable; - - using InputVariablePtr = std::shared_ptr; - - struct NAZARA_SHADER_API InputVariable : public NamedVariable - { - VariableType GetType() const override; - void Visit(ShaderVarVisitor& visitor) override; - - static inline std::shared_ptr Build(std::string varName, ShaderExpressionType varType); - }; - - struct LocalVariable; - - using LocalVariablePtr = std::shared_ptr; - - struct NAZARA_SHADER_API LocalVariable : public NamedVariable - { - VariableType GetType() const override; - void Visit(ShaderVarVisitor& visitor) override; - - static inline std::shared_ptr Build(std::string varName, ShaderExpressionType varType); - }; - - struct OutputVariable; - - using OutputVariablePtr = std::shared_ptr; - - struct NAZARA_SHADER_API OutputVariable : public NamedVariable - { - VariableType GetType() const override; - void Visit(ShaderVarVisitor& visitor) override; - - static inline std::shared_ptr Build(std::string varName, ShaderExpressionType varType); - }; - - struct ParameterVariable; - - using ParameterVariablePtr = std::shared_ptr; - - struct NAZARA_SHADER_API ParameterVariable : public NamedVariable - { - VariableType GetType() const override; - void Visit(ShaderVarVisitor& visitor) override; - - static inline std::shared_ptr Build(std::string varName, ShaderExpressionType varType); - }; - - struct UniformVariable; - - using UniformVariablePtr = std::shared_ptr; - - struct NAZARA_SHADER_API UniformVariable : public NamedVariable - { - VariableType GetType() const override; - void Visit(ShaderVarVisitor& visitor) override; - - static inline std::shared_ptr Build(std::string varName, ShaderExpressionType varType); - }; - } -} - -#include - -#endif diff --git a/include/Nazara/Shader/ShaderVariables.inl b/include/Nazara/Shader/ShaderVariables.inl deleted file mode 100644 index 9f2415708..000000000 --- a/include/Nazara/Shader/ShaderVariables.inl +++ /dev/null @@ -1,65 +0,0 @@ -// 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 -#include - -namespace Nz::ShaderNodes -{ - inline std::shared_ptr BuiltinVariable::Build(BuiltinEntry variable, ShaderExpressionType varType) - { - auto node = std::make_shared(); - node->entry = variable; - node->type = varType; - - return node; - } - - inline std::shared_ptr InputVariable::Build(std::string varName, ShaderExpressionType varType) - { - auto node = std::make_shared(); - node->name = std::move(varName); - node->type = varType; - - return node; - } - - inline std::shared_ptr LocalVariable::Build(std::string varName, ShaderExpressionType varType) - { - auto node = std::make_shared(); - node->name = std::move(varName); - node->type = varType; - - return node; - } - - inline std::shared_ptr OutputVariable::Build(std::string varName, ShaderExpressionType varType) - { - auto node = std::make_shared(); - node->name = std::move(varName); - node->type = varType; - - return node; - } - - inline std::shared_ptr ParameterVariable::Build(std::string varName, ShaderExpressionType varType) - { - auto node = std::make_shared(); - node->name = std::move(varName); - node->type = varType; - - return node; - } - - inline std::shared_ptr UniformVariable::Build(std::string varName, ShaderExpressionType varType) - { - auto node = std::make_shared(); - node->name = std::move(varName); - node->type = varType; - - return node; - } -} - -#include diff --git a/include/Nazara/Shader/ShaderWriter.hpp b/include/Nazara/Shader/ShaderWriter.hpp index 337c3c3cf..47fb04a6f 100644 --- a/include/Nazara/Shader/ShaderWriter.hpp +++ b/include/Nazara/Shader/ShaderWriter.hpp @@ -14,8 +14,6 @@ namespace Nz { - class ShaderAst; - class NAZARA_SHADER_API ShaderWriter { public: diff --git a/include/Nazara/Shader/SpirvAstVisitor.hpp b/include/Nazara/Shader/SpirvAstVisitor.hpp index cdf6fa2fe..ffead5fef 100644 --- a/include/Nazara/Shader/SpirvAstVisitor.hpp +++ b/include/Nazara/Shader/SpirvAstVisitor.hpp @@ -9,8 +9,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -18,7 +18,7 @@ namespace Nz { class SpirvWriter; - class NAZARA_SHADER_API SpirvAstVisitor : public ShaderAstVisitorExcept + class NAZARA_SHADER_API SpirvAstVisitor : public ShaderAst::ExpressionVisitorExcept, public ShaderAst::StatementVisitorExcept { public: inline SpirvAstVisitor(SpirvWriter& writer, std::vector& blocks); @@ -26,27 +26,28 @@ namespace Nz SpirvAstVisitor(SpirvAstVisitor&&) = delete; ~SpirvAstVisitor() = default; - UInt32 EvaluateExpression(const ShaderNodes::ExpressionPtr& expr); + UInt32 EvaluateExpression(ShaderAst::ExpressionPtr& expr); - using ShaderAstVisitorExcept::Visit; - void Visit(ShaderNodes::AccessMember& node) override; - void Visit(ShaderNodes::AssignOp& node) override; - void Visit(ShaderNodes::BinaryOp& node) override; - void Visit(ShaderNodes::Branch& node) override; - void Visit(ShaderNodes::Cast& node) override; - void Visit(ShaderNodes::ConditionalExpression& node) override; - void Visit(ShaderNodes::ConditionalStatement& node) override; - void Visit(ShaderNodes::Constant& node) override; - void Visit(ShaderNodes::DeclareVariable& node) override; - void Visit(ShaderNodes::Discard& node) override; - void Visit(ShaderNodes::ExpressionStatement& node) override; - void Visit(ShaderNodes::Identifier& node) override; - void Visit(ShaderNodes::IntrinsicCall& node) override; - void Visit(ShaderNodes::NoOp& node) override; - void Visit(ShaderNodes::ReturnStatement& node) override; - void Visit(ShaderNodes::Sample2D& node) override; - void Visit(ShaderNodes::StatementBlock& node) override; - void Visit(ShaderNodes::SwizzleOp& node) override; + using ExpressionVisitorExcept::Visit; + using StatementVisitorExcept::Visit; + + void Visit(ShaderAst::AccessMemberExpression& node) override; + void Visit(ShaderAst::AssignExpression& node) override; + void Visit(ShaderAst::BinaryExpression& node) override; + void Visit(ShaderAst::BranchStatement& node) override; + void Visit(ShaderAst::CastExpression& node) override; + void Visit(ShaderAst::ConditionalExpression& node) override; + void Visit(ShaderAst::ConditionalStatement& node) override; + void Visit(ShaderAst::ConstantExpression& node) override; + void Visit(ShaderAst::DeclareVariableStatement& node) override; + void Visit(ShaderAst::DiscardStatement& node) override; + void Visit(ShaderAst::ExpressionStatement& node) override; + void Visit(ShaderAst::IdentifierExpression& node) override; + void Visit(ShaderAst::IntrinsicExpression& node) override; + void Visit(ShaderAst::MultiStatement& node) override; + void Visit(ShaderAst::NoOpStatement& node) override; + void Visit(ShaderAst::ReturnStatement& node) override; + void Visit(ShaderAst::SwizzleExpression& node) override; SpirvAstVisitor& operator=(const SpirvAstVisitor&) = delete; SpirvAstVisitor& operator=(SpirvAstVisitor&&) = delete; diff --git a/include/Nazara/Shader/SpirvConstantCache.hpp b/include/Nazara/Shader/SpirvConstantCache.hpp index 279f71b07..54a53584c 100644 --- a/include/Nazara/Shader/SpirvConstantCache.hpp +++ b/include/Nazara/Shader/SpirvConstantCache.hpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include @@ -20,7 +20,6 @@ namespace Nz { - class ShaderAst; class SpirvSection; class NAZARA_SHADER_API SpirvConstantCache @@ -173,10 +172,10 @@ namespace Nz SpirvConstantCache& operator=(SpirvConstantCache&& cache) noexcept; static ConstantPtr BuildConstant(const ShaderConstantValue& value); - static TypePtr BuildPointerType(const ShaderNodes::BasicType& type, SpirvStorageClass storageClass); - static TypePtr BuildPointerType(const ShaderAst& shader, const ShaderExpressionType& type, SpirvStorageClass storageClass); - static TypePtr BuildType(const ShaderNodes::BasicType& type); - static TypePtr BuildType(const ShaderAst& shader, const ShaderExpressionType& type); + static TypePtr BuildPointerType(const ShaderAst::BasicType& type, SpirvStorageClass storageClass); + static TypePtr BuildPointerType(const ShaderAst::ShaderExpressionType& type, SpirvStorageClass storageClass); + static TypePtr BuildType(const ShaderAst::BasicType& type); + static TypePtr BuildType(const ShaderAst::ShaderExpressionType& type); private: struct DepRegisterer; diff --git a/include/Nazara/Shader/SpirvExpressionLoad.hpp b/include/Nazara/Shader/SpirvExpressionLoad.hpp index f59369a52..ddc9551fd 100644 --- a/include/Nazara/Shader/SpirvExpressionLoad.hpp +++ b/include/Nazara/Shader/SpirvExpressionLoad.hpp @@ -9,8 +9,7 @@ #include #include -#include -#include +#include #include #include @@ -19,7 +18,7 @@ namespace Nz class SpirvBlock; class SpirvWriter; - class NAZARA_SHADER_API SpirvExpressionLoad : public ShaderAstVisitorExcept, public ShaderVarVisitorExcept + class NAZARA_SHADER_API SpirvExpressionLoad : public ShaderAst::ExpressionVisitorExcept { public: inline SpirvExpressionLoad(SpirvWriter& writer, SpirvBlock& block); @@ -27,17 +26,11 @@ namespace Nz SpirvExpressionLoad(SpirvExpressionLoad&&) = delete; ~SpirvExpressionLoad() = default; - UInt32 Evaluate(ShaderNodes::Expression& node); + UInt32 Evaluate(ShaderAst::Expression& node); - using ShaderAstVisitor::Visit; - void Visit(ShaderNodes::AccessMember& node) override; - void Visit(ShaderNodes::Identifier& node) override; - - using ShaderVarVisitor::Visit; - void Visit(ShaderNodes::InputVariable& var) override; - void Visit(ShaderNodes::LocalVariable& var) override; - void Visit(ShaderNodes::ParameterVariable& var) override; - void Visit(ShaderNodes::UniformVariable& var) override; + using ExpressionVisitorExcept::Visit; + //void Visit(ShaderAst::AccessMemberExpression& node) override; + void Visit(ShaderAst::IdentifierExpression& node) override; SpirvExpressionLoad& operator=(const SpirvExpressionLoad&) = delete; SpirvExpressionLoad& operator=(SpirvExpressionLoad&&) = delete; diff --git a/include/Nazara/Shader/SpirvExpressionStore.hpp b/include/Nazara/Shader/SpirvExpressionStore.hpp index 26c2b5f48..ee0d96f6a 100644 --- a/include/Nazara/Shader/SpirvExpressionStore.hpp +++ b/include/Nazara/Shader/SpirvExpressionStore.hpp @@ -9,8 +9,7 @@ #include #include -#include -#include +#include #include namespace Nz @@ -18,7 +17,7 @@ namespace Nz class SpirvBlock; class SpirvWriter; - class NAZARA_SHADER_API SpirvExpressionStore : public ShaderAstVisitorExcept, public ShaderVarVisitorExcept + class NAZARA_SHADER_API SpirvExpressionStore : public ShaderAst::ExpressionVisitorExcept { public: inline SpirvExpressionStore(SpirvWriter& writer, SpirvBlock& block); @@ -26,17 +25,12 @@ namespace Nz SpirvExpressionStore(SpirvExpressionStore&&) = delete; ~SpirvExpressionStore() = default; - void Store(const ShaderNodes::ExpressionPtr& node, UInt32 resultId); + void Store(ShaderAst::ExpressionPtr& node, UInt32 resultId); - using ShaderAstVisitorExcept::Visit; - void Visit(ShaderNodes::AccessMember& node) override; - void Visit(ShaderNodes::Identifier& node) override; - void Visit(ShaderNodes::SwizzleOp& node) override; - - using ShaderVarVisitorExcept::Visit; - void Visit(ShaderNodes::BuiltinVariable& var) override; - void Visit(ShaderNodes::LocalVariable& var) override; - void Visit(ShaderNodes::OutputVariable& var) override; + using ExpressionVisitorExcept::Visit; + //void Visit(ShaderAst::AccessMemberExpression& node) override; + void Visit(ShaderAst::IdentifierExpression& node) override; + void Visit(ShaderAst::SwizzleExpression& node) override; SpirvExpressionStore& operator=(const SpirvExpressionStore&) = delete; SpirvExpressionStore& operator=(SpirvExpressionStore&&) = delete; diff --git a/include/Nazara/Shader/SpirvWriter.hpp b/include/Nazara/Shader/SpirvWriter.hpp index eeaee1e60..a8af651cd 100644 --- a/include/Nazara/Shader/SpirvWriter.hpp +++ b/include/Nazara/Shader/SpirvWriter.hpp @@ -9,10 +9,8 @@ #include #include -#include -#include +#include #include -#include #include #include #include @@ -39,7 +37,7 @@ namespace Nz SpirvWriter(SpirvWriter&&) = delete; ~SpirvWriter() = default; - std::vector Generate(const ShaderAst& shader, const States& conditions = {}); + std::vector Generate(ShaderAst::StatementPtr& shader, const States& conditions = {}); void SetEnv(Environment environment); @@ -51,22 +49,23 @@ namespace Nz private: struct ExtVar; + struct FunctionParameter; struct OnlyCache {}; UInt32 AllocateResultId(); void AppendHeader(); - SpirvConstantCache::Function BuildFunctionType(ShaderExpressionType retType, const std::vector& parameters); + SpirvConstantCache::Function BuildFunctionType(ShaderAst::ShaderExpressionType retType, const std::vector& parameters); UInt32 GetConstantId(const ShaderConstantValue& value) const; - UInt32 GetFunctionTypeId(ShaderExpressionType retType, const std::vector& parameters); - const ExtVar& GetBuiltinVariable(ShaderNodes::BuiltinEntry builtin) const; + UInt32 GetFunctionTypeId(ShaderAst::ShaderExpressionType retType, const std::vector& parameters); + const ExtVar& GetBuiltinVariable(ShaderAst::BuiltinEntry builtin) const; const ExtVar& GetInputVariable(const std::string& name) const; const ExtVar& GetOutputVariable(const std::string& name) const; const ExtVar& GetUniformVariable(const std::string& name) const; - UInt32 GetPointerTypeId(const ShaderExpressionType& type, SpirvStorageClass storageClass) const; - UInt32 GetTypeId(const ShaderExpressionType& type) const; + UInt32 GetPointerTypeId(const ShaderAst::ShaderExpressionType& type, SpirvStorageClass storageClass) const; + UInt32 GetTypeId(const ShaderAst::ShaderExpressionType& type) const; inline bool IsConditionEnabled(const std::string& condition) const; @@ -82,9 +81,9 @@ namespace Nz std::optional ReadVariable(const ExtVar& var, OnlyCache); UInt32 RegisterConstant(const ShaderConstantValue& value); - UInt32 RegisterFunctionType(ShaderExpressionType retType, const std::vector& parameters); - UInt32 RegisterPointerType(ShaderExpressionType type, SpirvStorageClass storageClass); - UInt32 RegisterType(ShaderExpressionType type); + UInt32 RegisterFunctionType(ShaderAst::ShaderExpressionType retType, const std::vector& parameters); + UInt32 RegisterPointerType(ShaderAst::ShaderExpressionType type, SpirvStorageClass storageClass); + UInt32 RegisterType(ShaderAst::ShaderExpressionType type); void WriteLocalVariable(std::string name, UInt32 resultId); @@ -92,7 +91,7 @@ namespace Nz struct Context { - const ShaderAst* shader = nullptr; + ShaderAst::AstCache cache; const States* states = nullptr; std::vector functionBlocks; }; @@ -105,6 +104,12 @@ namespace Nz std::optional valueId; }; + struct FunctionParameter + { + std::string name; + ShaderAst::ShaderExpressionType type; + }; + struct State; Context m_context; diff --git a/include/Nazara/Shader/SpirvWriter.inl b/include/Nazara/Shader/SpirvWriter.inl index ed518e5f4..903d6265b 100644 --- a/include/Nazara/Shader/SpirvWriter.inl +++ b/include/Nazara/Shader/SpirvWriter.inl @@ -10,10 +10,11 @@ namespace Nz { inline bool SpirvWriter::IsConditionEnabled(const std::string& condition) const { - std::size_t conditionIndex = m_context.shader->FindConditionByName(condition); + /*std::size_t conditionIndex = m_context.shader->FindConditionByName(condition); assert(conditionIndex != ShaderAst::InvalidCondition); - return TestBit(m_context.states->enabledConditions, conditionIndex); + return TestBit(m_context.states->enabledConditions, conditionIndex);*/ + return false; } } diff --git a/src/Nazara/Graphics/BasicMaterial.cpp b/src/Nazara/Graphics/BasicMaterial.cpp index 089438336..220efd6bb 100644 --- a/src/Nazara/Graphics/BasicMaterial.cpp +++ b/src/Nazara/Graphics/BasicMaterial.cpp @@ -167,8 +167,8 @@ namespace Nz auto& fragmentShader = settings.shaders[UnderlyingCast(ShaderStageType::Fragment)]; auto& vertexShader = settings.shaders[UnderlyingCast(ShaderStageType::Vertex)]; - fragmentShader = std::make_shared(UnserializeShader(r_fragmentShader, sizeof(r_fragmentShader))); - vertexShader = std::make_shared(UnserializeShader(r_vertexShader, sizeof(r_vertexShader))); + fragmentShader = std::make_shared(ShaderAst::UnserializeShader(r_fragmentShader, sizeof(r_fragmentShader))); + vertexShader = std::make_shared(ShaderAst::UnserializeShader(r_vertexShader, sizeof(r_vertexShader))); // Conditions diff --git a/src/Nazara/Graphics/UberShader.cpp b/src/Nazara/Graphics/UberShader.cpp index 6fb0fcba0..fc2364a24 100644 --- a/src/Nazara/Graphics/UberShader.cpp +++ b/src/Nazara/Graphics/UberShader.cpp @@ -5,17 +5,17 @@ #include #include #include -#include #include #include #include namespace Nz { - UberShader::UberShader(ShaderAst shaderAst) : + UberShader::UberShader(ShaderAst::StatementPtr shaderAst) : m_shaderAst(std::move(shaderAst)) { - std::size_t conditionCount = m_shaderAst.GetConditionCount(); + //std::size_t conditionCount = m_shaderAst.GetConditionCount(); + std::size_t conditionCount = 0; if (conditionCount >= 64) throw std::runtime_error("Too many conditions"); @@ -27,10 +27,10 @@ namespace Nz UInt64 UberShader::GetConditionFlagByName(const std::string_view& condition) const { - std::size_t conditionIndex = m_shaderAst.FindConditionByName(condition); + /*std::size_t conditionIndex = m_shaderAst.FindConditionByName(condition); if (conditionIndex != ShaderAst::InvalidCondition) return SetBit(0, conditionIndex); - else + else*/ return 0; } diff --git a/src/Nazara/Shader/GlslWriter.cpp b/src/Nazara/Shader/GlslWriter.cpp index 1920bf291..bb9ce8433 100644 --- a/src/Nazara/Shader/GlslWriter.cpp +++ b/src/Nazara/Shader/GlslWriter.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -20,64 +21,67 @@ namespace Nz { static const char* flipYUniformName = "_NzFlipValue"; - struct AstAdapter : ShaderAstCloner + struct AstAdapter : ShaderAst::AstCloner { - void Visit(ShaderNodes::AssignOp& node) override + void Visit(ShaderAst::AssignExpression& node) override { if (!flipYPosition) + return AstCloner::Visit(node); + + if (node.left->GetType() != ShaderAst::NodeType::IdentifierExpression) + return AstCloner::Visit(node); + + /* + FIXME: + const auto& identifier = static_cast(*node.left); + if (identifier.var->GetType() != ShaderAst::VariableType::BuiltinVariable) return ShaderAstCloner::Visit(node); - if (node.left->GetType() != ShaderNodes::NodeType::Identifier) + const auto& builtinVar = static_cast(*identifier.var); + if (builtinVar.entry != ShaderAst::BuiltinEntry::VertexPosition) return ShaderAstCloner::Visit(node); - const auto& identifier = static_cast(*node.left); - if (identifier.var->GetType() != ShaderNodes::VariableType::BuiltinVariable) - return ShaderAstCloner::Visit(node); - - const auto& builtinVar = static_cast(*identifier.var); - if (builtinVar.entry != ShaderNodes::BuiltinEntry::VertexPosition) - return ShaderAstCloner::Visit(node); - - auto flipVar = ShaderBuilder::Uniform(flipYUniformName, ShaderNodes::BasicType::Float1); + auto flipVar = ShaderBuilder::Uniform(flipYUniformName, ShaderAst::BasicType::Float1); auto oneConstant = ShaderBuilder::Constant(1.f); - auto fixYValue = ShaderBuilder::Cast(oneConstant, ShaderBuilder::Identifier(flipVar), oneConstant, oneConstant); + auto fixYValue = ShaderBuilder::Cast(oneConstant, ShaderBuilder::Identifier(flipVar), oneConstant, oneConstant); auto mulFix = ShaderBuilder::Multiply(CloneExpression(node.right), fixYValue); - PushExpression(ShaderNodes::AssignOp::Build(node.op, CloneExpression(node.left), mulFix)); + PushExpression(ShaderAst::AssignOp::Build(node.op, CloneExpression(node.left), mulFix));*/ } bool flipYPosition = false; }; } + + struct GlslWriter::State + { + const States* states = nullptr; + ShaderAst::AstCache cache; + std::stringstream stream; + unsigned int indentLevel = 0; + }; + + GlslWriter::GlslWriter() : m_currentState(nullptr) { } - std::string GlslWriter::Generate(const ShaderAst& inputShader, const States& conditions) + std::string GlslWriter::Generate(ShaderAst::StatementPtr& shader, const States& conditions) { - const ShaderAst* selectedShader = &inputShader; + /*const ShaderAst* selectedShader = &inputShader; std::optional modifiedShader; if (inputShader.GetStage() == ShaderStageType::Vertex && m_environment.flipYPosition) { modifiedShader.emplace(inputShader); - modifiedShader->AddUniform(flipYUniformName, ShaderNodes::BasicType::Float1); + modifiedShader->AddUniform(flipYUniformName, ShaderAst::BasicType::Float1); selectedShader = &modifiedShader.value(); - } - - const ShaderAst& shader = *selectedShader; - - std::string error; - if (!ValidateShader(shader, &error)) - throw std::runtime_error("Invalid shader AST: " + error); - - m_context.states = &conditions; - m_context.shader = &shader; - + }*/ + State state; m_currentState = &state; CallOnExit onExit([this]() @@ -85,6 +89,10 @@ namespace Nz m_currentState = nullptr; }); + std::string error; + if (!ShaderAst::ValidateAst(shader, &error, &state.cache)) + throw std::runtime_error("Invalid shader AST: " + error); + unsigned int glslVersion; if (m_environment.glES) { @@ -165,52 +173,7 @@ namespace Nz AppendLine(); } - // Structures - /*if (shader.GetStructCount() > 0) - { - AppendCommentSection("Structures"); - for (const auto& s : shader.GetStructs()) - { - Append("struct "); - AppendLine(s.name); - AppendLine("{"); - for (const auto& m : s.members) - { - Append("\t"); - Append(m.type); - Append(" "); - Append(m.name); - AppendLine(";"); - } - AppendLine("};"); - AppendLine(); - } - }*/ - - // Global variables (uniforms, input and outputs) - const char* inKeyword = (glslVersion >= 130) ? "in" : "varying"; - const char* outKeyword = (glslVersion >= 130) ? "out" : "varying"; - - DeclareVariables(shader, shader.GetUniforms(), "uniform", "Uniforms"); - DeclareVariables(shader, shader.GetInputs(), inKeyword, "Inputs"); - DeclareVariables(shader, shader.GetOutputs(), outKeyword, "Outputs"); - - std::size_t functionCount = shader.GetFunctionCount(); - if (functionCount > 1) - { - AppendCommentSection("Prototypes"); - for (const auto& func : shader.GetFunctions()) - { - if (func.name != "main") - { - AppendFunctionPrototype(func); - AppendLine(";"); - } - } - } - - for (const auto& func : shader.GetFunctions()) - AppendFunction(func); + shader->Visit(*this); return state.stream.str(); } @@ -225,7 +188,7 @@ namespace Nz return flipYUniformName; } - void GlslWriter::Append(ShaderExpressionType type) + void GlslWriter::Append(ShaderAst::ShaderExpressionType type) { std::visit([&](auto&& arg) { @@ -233,49 +196,57 @@ namespace Nz }, type); } - void GlslWriter::Append(ShaderNodes::BuiltinEntry builtin) + void GlslWriter::Append(ShaderAst::BuiltinEntry builtin) { switch (builtin) { - case ShaderNodes::BuiltinEntry::VertexPosition: + case ShaderAst::BuiltinEntry::VertexPosition: Append("gl_Position"); break; } } - void GlslWriter::Append(ShaderNodes::BasicType type) + void GlslWriter::Append(ShaderAst::BasicType type) { switch (type) { - case ShaderNodes::BasicType::Boolean: return Append("bool"); - case ShaderNodes::BasicType::Float1: return Append("float"); - case ShaderNodes::BasicType::Float2: return Append("vec2"); - case ShaderNodes::BasicType::Float3: return Append("vec3"); - case ShaderNodes::BasicType::Float4: return Append("vec4"); - case ShaderNodes::BasicType::Int1: return Append("int"); - case ShaderNodes::BasicType::Int2: return Append("ivec2"); - case ShaderNodes::BasicType::Int3: return Append("ivec3"); - case ShaderNodes::BasicType::Int4: return Append("ivec4"); - case ShaderNodes::BasicType::Mat4x4: return Append("mat4"); - case ShaderNodes::BasicType::Sampler2D: return Append("sampler2D"); - case ShaderNodes::BasicType::UInt1: return Append("uint"); - case ShaderNodes::BasicType::UInt2: return Append("uvec2"); - case ShaderNodes::BasicType::UInt3: return Append("uvec3"); - case ShaderNodes::BasicType::UInt4: return Append("uvec4"); - case ShaderNodes::BasicType::Void: return Append("void"); + case ShaderAst::BasicType::Boolean: return Append("bool"); + case ShaderAst::BasicType::Float1: return Append("float"); + case ShaderAst::BasicType::Float2: return Append("vec2"); + case ShaderAst::BasicType::Float3: return Append("vec3"); + case ShaderAst::BasicType::Float4: return Append("vec4"); + case ShaderAst::BasicType::Int1: return Append("int"); + case ShaderAst::BasicType::Int2: return Append("ivec2"); + case ShaderAst::BasicType::Int3: return Append("ivec3"); + case ShaderAst::BasicType::Int4: return Append("ivec4"); + case ShaderAst::BasicType::Mat4x4: return Append("mat4"); + case ShaderAst::BasicType::Sampler2D: return Append("sampler2D"); + case ShaderAst::BasicType::UInt1: return Append("uint"); + case ShaderAst::BasicType::UInt2: return Append("uvec2"); + case ShaderAst::BasicType::UInt3: return Append("uvec3"); + case ShaderAst::BasicType::UInt4: return Append("uvec4"); + case ShaderAst::BasicType::Void: return Append("void"); } } - void GlslWriter::Append(ShaderNodes::MemoryLayout layout) + void GlslWriter::Append(ShaderAst::MemoryLayout layout) { switch (layout) { - case ShaderNodes::MemoryLayout::Std140: + case ShaderAst::MemoryLayout::Std140: Append("std140"); break; } } + template + void GlslWriter::Append(const T& param) + { + NazaraAssert(m_currentState, "This function should only be called while processing an AST"); + + m_currentState->stream << param; + } + void GlslWriter::AppendCommentSection(const std::string& section) { NazaraAssert(m_currentState, "This function should only be called while processing an AST"); @@ -285,67 +256,24 @@ namespace Nz AppendLine(); } - void GlslWriter::AppendField(const std::string& structName, std::size_t* memberIndex, std::size_t remainingMembers) + void GlslWriter::AppendField(std::size_t scopeId, const std::string& structName, const std::string* memberIdentifier, std::size_t remainingMembers) { - const auto& structs = m_context.shader->GetStructs(); - auto it = std::find_if(structs.begin(), structs.end(), [&](const auto& s) { return s.name == structName; }); - assert(it != structs.end()); - - const ShaderAst::Struct& s = *it; - assert(*memberIndex < s.members.size()); - - const auto& member = s.members[*memberIndex]; Append("."); - Append(member.name); + Append(memberIdentifier[0]); + + const ShaderAst::AstCache::Identifier* identifier = m_currentState->cache.FindIdentifier(scopeId, structName); + assert(identifier); + + assert(std::holds_alternative(identifier->value)); + const auto& s = std::get(identifier->value); + + auto memberIt = std::find_if(s.members.begin(), s.members.begin(), [&](const auto& field) { return field.name == memberIdentifier[0]; }); + assert(memberIt != s.members.end()); + + const auto& member = *memberIt; if (remainingMembers > 1) - { - assert(IsStructType(member.type)); - AppendField(std::get(member.type), memberIndex + 1, remainingMembers - 1); - } - } - - void GlslWriter::AppendFunction(const ShaderAst::Function& func) - { - NazaraAssert(!m_context.currentFunction, "A function is already being processed"); - NazaraAssert(m_currentState, "This function should only be called while processing an AST"); - - AppendFunctionPrototype(func); - - m_context.currentFunction = &func; - CallOnExit onExit([this] () - { - m_context.currentFunction = nullptr; - }); - - EnterScope(); - { - AstAdapter adapter; - adapter.flipYPosition = m_environment.flipYPosition; - - Visit(adapter.Clone(func.statement)); - } - LeaveScope(); - } - - void GlslWriter::AppendFunctionPrototype(const ShaderAst::Function& func) - { - Append(func.returnType); - - Append(" "); - Append(func.name); - - Append("("); - for (std::size_t i = 0; i < func.parameters.size(); ++i) - { - if (i != 0) - Append(", "); - - Append(func.parameters[i].type); - Append(" "); - Append(func.parameters[i].name); - } - Append(")\n"); + AppendField(scopeId, std::get(member.type), memberIdentifier + 1, remainingMembers - 1); } void GlslWriter::AppendLine(const std::string& txt) @@ -372,44 +300,46 @@ namespace Nz AppendLine("}"); } - void GlslWriter::Visit(ShaderNodes::ExpressionPtr& expr, bool encloseIfRequired) + void GlslWriter::Visit(ShaderAst::ExpressionPtr& expr, bool encloseIfRequired) { - bool enclose = encloseIfRequired && (GetExpressionCategory(expr) != ShaderNodes::ExpressionCategory::LValue); + bool enclose = encloseIfRequired && (GetExpressionCategory(*expr) != ShaderAst::ExpressionCategory::LValue); if (enclose) Append("("); - ShaderAstVisitor::Visit(expr); + expr->Visit(*this); if (enclose) Append(")"); } - void GlslWriter::Visit(ShaderNodes::AccessMember& node) + void GlslWriter::Visit(ShaderAst::AccessMemberExpression& node) { Visit(node.structExpr, true); - const ShaderExpressionType& exprType = node.structExpr->GetExpressionType(); + const ShaderAst::ShaderExpressionType& exprType = GetExpressionType(*node.structExpr, &m_currentState->cache); assert(IsStructType(exprType)); - AppendField(std::get(exprType), node.memberIndices.data(), node.memberIndices.size()); + std::size_t scopeId = m_currentState->cache.GetScopeId(&node); + + AppendField(scopeId, std::get(exprType), node.memberIdentifiers.data(), node.memberIdentifiers.size()); } - void GlslWriter::Visit(ShaderNodes::AssignOp& node) + void GlslWriter::Visit(ShaderAst::AssignExpression& node) { - Visit(node.left); + node.left->Visit(*this); switch (node.op) { - case ShaderNodes::AssignType::Simple: + case ShaderAst::AssignType::Simple: Append(" = "); break; } - Visit(node.right); + node.left->Visit(*this); } - void GlslWriter::Visit(ShaderNodes::Branch& node) + void GlslWriter::Visit(ShaderAst::BranchStatement& node) { bool first = true; for (const auto& statement : node.condStatements) @@ -418,11 +348,11 @@ namespace Nz Append("else "); Append("if ("); - Visit(statement.condition); + statement.condition->Visit(*this); AppendLine(")"); EnterScope(); - Visit(statement.statement); + statement.statement->Visit(*this); LeaveScope(); first = false; @@ -433,41 +363,36 @@ namespace Nz AppendLine("else"); EnterScope(); - Visit(node.elseStatement); + node.elseStatement->Visit(*this); LeaveScope(); } } - void GlslWriter::Visit(ShaderNodes::BinaryOp& node) + void GlslWriter::Visit(ShaderAst::BinaryExpression& node) { Visit(node.left, true); switch (node.op) { - case ShaderNodes::BinaryType::Add: Append(" + "); break; - case ShaderNodes::BinaryType::Subtract: Append(" - "); break; - case ShaderNodes::BinaryType::Multiply: Append(" * "); break; - case ShaderNodes::BinaryType::Divide: Append(" / "); break; + case ShaderAst::BinaryType::Add: Append(" + "); break; + case ShaderAst::BinaryType::Subtract: Append(" - "); break; + case ShaderAst::BinaryType::Multiply: Append(" * "); break; + case ShaderAst::BinaryType::Divide: Append(" / "); break; - case ShaderNodes::BinaryType::CompEq: Append(" == "); break; - case ShaderNodes::BinaryType::CompGe: Append(" >= "); break; - case ShaderNodes::BinaryType::CompGt: Append(" > "); break; - case ShaderNodes::BinaryType::CompLe: Append(" <= "); break; - case ShaderNodes::BinaryType::CompLt: Append(" < "); break; - case ShaderNodes::BinaryType::CompNe: Append(" != "); break; + case ShaderAst::BinaryType::CompEq: Append(" == "); break; + case ShaderAst::BinaryType::CompGe: Append(" >= "); break; + case ShaderAst::BinaryType::CompGt: Append(" > "); break; + case ShaderAst::BinaryType::CompLe: Append(" <= "); break; + case ShaderAst::BinaryType::CompLt: Append(" < "); break; + case ShaderAst::BinaryType::CompNe: Append(" != "); break; } Visit(node.right, true); } - void GlslWriter::Visit(ShaderNodes::BuiltinVariable& var) + void GlslWriter::Visit(ShaderAst::CastExpression& node) { - Append(var.entry); - } - - void GlslWriter::Visit(ShaderNodes::Cast& node) - { - Append(node.exprType); + Append(node.targetType); Append("("); bool first = true; @@ -479,34 +404,34 @@ namespace Nz if (!first) m_currentState->stream << ", "; - Visit(exprPtr); + exprPtr->Visit(*this); first = false; } Append(")"); } - void GlslWriter::Visit(ShaderNodes::ConditionalExpression& node) + void GlslWriter::Visit(ShaderAst::ConditionalExpression& node) { - std::size_t conditionIndex = m_context.shader->FindConditionByName(node.conditionName); + /*std::size_t conditionIndex = m_context.shader->FindConditionByName(node.conditionName); assert(conditionIndex != ShaderAst::InvalidCondition); if (TestBit(m_context.states->enabledConditions, conditionIndex)) Visit(node.truePath); else - Visit(node.falsePath); + Visit(node.falsePath);*/ } - void GlslWriter::Visit(ShaderNodes::ConditionalStatement& node) + void GlslWriter::Visit(ShaderAst::ConditionalStatement& node) { - std::size_t conditionIndex = m_context.shader->FindConditionByName(node.conditionName); + /*std::size_t conditionIndex = m_context.shader->FindConditionByName(node.conditionName); assert(conditionIndex != ShaderAst::InvalidCondition); if (TestBit(m_context.states->enabledConditions, conditionIndex)) - Visit(node.statement); + Visit(node.statement);*/ } - void GlslWriter::Visit(ShaderNodes::Constant& node) + void GlslWriter::Visit(ShaderAst::ConstantExpression& node) { std::visit([&](auto&& arg) { @@ -530,54 +455,74 @@ namespace Nz }, node.value); } - void GlslWriter::Visit(ShaderNodes::DeclareVariable& node) + void GlslWriter::Visit(ShaderAst::DeclareFunctionStatement& node) { - assert(node.variable->GetType() == ShaderNodes::VariableType::LocalVariable); + NazaraAssert(m_currentState, "This function should only be called while processing an AST"); - const auto& localVar = static_cast(*node.variable); - - Append(localVar.type); + Append(node.returnType); Append(" "); - Append(localVar.name); - if (node.expression) + Append(node.name); + Append("("); + for (std::size_t i = 0; i < node.parameters.size(); ++i) + { + if (i != 0) + Append(", "); + Append(node.parameters[i].type); + Append(" "); + Append(node.parameters[i].name); + } + Append(")\n"); + + EnterScope(); + { + AstAdapter adapter; + adapter.flipYPosition = m_environment.flipYPosition; + + for (auto& statement : node.statements) + adapter.Clone(statement)->Visit(*this); + } + LeaveScope(); + } + + void GlslWriter::Visit(ShaderAst::DeclareVariableStatement& node) + { + Append(node.varType); + Append(" "); + Append(node.varName); + if (node.initialExpression) { Append(" = "); - Visit(node.expression); + node.initialExpression->Visit(*this); } AppendLine(";"); } - void GlslWriter::Visit(ShaderNodes::Discard& /*node*/) + void GlslWriter::Visit(ShaderAst::DiscardStatement& /*node*/) { Append("discard;"); } - void GlslWriter::Visit(ShaderNodes::ExpressionStatement& node) + void GlslWriter::Visit(ShaderAst::ExpressionStatement& node) { - Visit(node.expression); + node.expression->Visit(*this); Append(";"); } - void GlslWriter::Visit(ShaderNodes::Identifier& node) + void GlslWriter::Visit(ShaderAst::IdentifierExpression& node) { - Visit(node.var); + Append(node.identifier); } - void GlslWriter::Visit(ShaderNodes::InputVariable& var) - { - Append(var.name); - } - - void GlslWriter::Visit(ShaderNodes::IntrinsicCall& node) + void GlslWriter::Visit(ShaderAst::IntrinsicExpression& node) { switch (node.intrinsic) { - case ShaderNodes::IntrinsicType::CrossProduct: + case ShaderAst::IntrinsicType::CrossProduct: Append("cross"); break; - case ShaderNodes::IntrinsicType::DotProduct: + case ShaderAst::IntrinsicType::DotProduct: Append("dot"); break; } @@ -588,67 +533,43 @@ namespace Nz if (i != 0) Append(", "); - Visit(node.parameters[i]); + node.parameters[i]->Visit(*this); } Append(")"); } - void GlslWriter::Visit(ShaderNodes::LocalVariable& var) + void GlslWriter::Visit(ShaderAst::MultiStatement& node) { - Append(var.name); + bool first = true; + for (const ShaderAst::StatementPtr& statement : node.statements) + { + if (!first && statement->GetType() != ShaderAst::NodeType::NoOpStatement) + AppendLine(); + + statement->Visit(*this); + + first = false; + } } - void GlslWriter::Visit(ShaderNodes::NoOp& /*node*/) + void GlslWriter::Visit(ShaderAst::NoOpStatement& /*node*/) { /* nothing to do */ } - void GlslWriter::Visit(ShaderNodes::ParameterVariable& var) - { - Append(var.name); - } - - void GlslWriter::Visit(ShaderNodes::ReturnStatement& node) + void GlslWriter::Visit(ShaderAst::ReturnStatement& node) { if (node.returnExpr) { Append("return "); - Visit(node.returnExpr); + node.returnExpr->Visit(*this); Append(";"); } else Append("return;"); } - void GlslWriter::Visit(ShaderNodes::OutputVariable& var) - { - Append(var.name); - } - - void GlslWriter::Visit(ShaderNodes::Sample2D& node) - { - Append("texture("); - Visit(node.sampler); - Append(", "); - Visit(node.coordinates); - Append(")"); - } - - void GlslWriter::Visit(ShaderNodes::StatementBlock& node) - { - bool first = true; - for (const ShaderNodes::StatementPtr& statement : node.statements) - { - if (!first && statement->GetType() != ShaderNodes::NodeType::NoOp) - AppendLine(); - - Visit(statement); - - first = false; - } - } - - void GlslWriter::Visit(ShaderNodes::SwizzleOp& node) + void GlslWriter::Visit(ShaderAst::SwizzleExpression& node) { Visit(node.expression, true); Append("."); @@ -657,44 +578,39 @@ namespace Nz { switch (node.components[i]) { - case ShaderNodes::SwizzleComponent::First: + case ShaderAst::SwizzleComponent::First: Append("x"); break; - case ShaderNodes::SwizzleComponent::Second: + case ShaderAst::SwizzleComponent::Second: Append("y"); break; - case ShaderNodes::SwizzleComponent::Third: + case ShaderAst::SwizzleComponent::Third: Append("z"); break; - case ShaderNodes::SwizzleComponent::Fourth: + case ShaderAst::SwizzleComponent::Fourth: Append("w"); break; } } } - void GlslWriter::Visit(ShaderNodes::UniformVariable& var) + bool GlslWriter::HasExplicitBinding(ShaderAst::StatementPtr& shader) { - Append(var.name); - } - - bool GlslWriter::HasExplicitBinding(const ShaderAst& shader) - { - for (const auto& uniform : shader.GetUniforms()) + /*for (const auto& uniform : shader.GetUniforms()) { if (uniform.bindingIndex.has_value()) return true; - } + }*/ return false; } - bool GlslWriter::HasExplicitLocation(const ShaderAst& shader) + bool GlslWriter::HasExplicitLocation(ShaderAst::StatementPtr& shader) { - for (const auto& input : shader.GetInputs()) + /*for (const auto& input : shader.GetInputs()) { if (input.locationIndex.has_value()) return true; @@ -704,7 +620,7 @@ namespace Nz { if (output.locationIndex.has_value()) return true; - } + }*/ return false; } diff --git a/src/Nazara/Shader/ShaderAst.cpp b/src/Nazara/Shader/ShaderAst.cpp deleted file mode 100644 index ff84cfa55..000000000 --- a/src/Nazara/Shader/ShaderAst.cpp +++ /dev/null @@ -1,56 +0,0 @@ -// 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 -#include - -namespace Nz -{ - void ShaderAst::AddCondition(std::string name) - { - auto& conditionEntry = m_conditions.emplace_back(); - conditionEntry.name = std::move(name); - } - - void ShaderAst::AddFunction(std::string name, ShaderNodes::StatementPtr statement, std::vector parameters, ShaderExpressionType returnType) - { - auto& functionEntry = m_functions.emplace_back(); - functionEntry.name = std::move(name); - functionEntry.parameters = std::move(parameters); - functionEntry.returnType = returnType; - functionEntry.statement = std::move(statement); - } - - void ShaderAst::AddInput(std::string name, ShaderExpressionType type, std::optional locationIndex) - { - auto& inputEntry = m_inputs.emplace_back(); - inputEntry.name = std::move(name); - inputEntry.locationIndex = std::move(locationIndex); - inputEntry.type = std::move(type); - } - - void ShaderAst::AddOutput(std::string name, ShaderExpressionType type, std::optional locationIndex) - { - auto& outputEntry = m_outputs.emplace_back(); - outputEntry.name = std::move(name); - outputEntry.locationIndex = std::move(locationIndex); - outputEntry.type = std::move(type); - } - - void ShaderAst::AddStruct(std::string name, std::vector members) - { - auto& structEntry = m_structs.emplace_back(); - structEntry.name = std::move(name); - structEntry.members = std::move(members); - } - - void ShaderAst::AddUniform(std::string name, ShaderExpressionType type, std::optional bindingIndex, std::optional memoryLayout) - { - auto& uniformEntry = m_uniforms.emplace_back(); - uniformEntry.bindingIndex = std::move(bindingIndex); - uniformEntry.memoryLayout = std::move(memoryLayout); - uniformEntry.name = std::move(name); - uniformEntry.type = std::move(type); - } -} diff --git a/src/Nazara/Shader/ShaderAstCloner.cpp b/src/Nazara/Shader/ShaderAstCloner.cpp index 1118029df..2948cd753 100644 --- a/src/Nazara/Shader/ShaderAstCloner.cpp +++ b/src/Nazara/Shader/ShaderAstCloner.cpp @@ -6,240 +6,257 @@ #include #include -namespace Nz +namespace Nz::ShaderAst { - ShaderNodes::StatementPtr ShaderAstCloner::Clone(const ShaderNodes::StatementPtr& statement) + ExpressionPtr AstCloner::Clone(ExpressionPtr& expr) { - ShaderAstVisitor::Visit(statement); + expr->Visit(*this); - if (!m_expressionStack.empty() || !m_variableStack.empty() || m_statementStack.size() != 1) - throw std::runtime_error("An error occurred during clone"); + assert(m_statementStack.empty() && m_expressionStack.size() == 1); + return PopExpression(); + } + StatementPtr AstCloner::Clone(StatementPtr& statement) + { + statement->Visit(*this); + + assert(m_expressionStack.empty() && m_statementStack.size() == 1); return PopStatement(); } - ShaderNodes::ExpressionPtr ShaderAstCloner::CloneExpression(const ShaderNodes::ExpressionPtr& expr) + ExpressionPtr AstCloner::CloneExpression(ExpressionPtr& expr) { if (!expr) return nullptr; - ShaderAstVisitor::Visit(expr); + expr->Visit(*this); return PopExpression(); } - ShaderNodes::StatementPtr ShaderAstCloner::CloneStatement(const ShaderNodes::StatementPtr& statement) + StatementPtr AstCloner::CloneStatement(StatementPtr& statement) { if (!statement) return nullptr; - ShaderAstVisitor::Visit(statement); + statement->Visit(*this); return PopStatement(); } - ShaderNodes::VariablePtr ShaderAstCloner::CloneVariable(const ShaderNodes::VariablePtr& variable) + void AstCloner::Visit(AccessMemberExpression& node) { - if (!variable) - return nullptr; + auto clone = std::make_unique(); + clone->memberIdentifiers = node.memberIdentifiers; + clone->structExpr = CloneExpression(node.structExpr); - ShaderVarVisitor::Visit(variable); - return PopVariable(); + PushExpression(std::move(clone)); } - void ShaderAstCloner::Visit(ShaderNodes::AccessMember& node) + void AstCloner::Visit(AssignExpression& node) { - PushExpression(ShaderNodes::AccessMember::Build(CloneExpression(node.structExpr), node.memberIndices, node.exprType)); + auto clone = std::make_unique(); + clone->op = node.op; + clone->left = CloneExpression(node.left); + clone->right = CloneExpression(node.right); + + PushExpression(std::move(clone)); } - void ShaderAstCloner::Visit(ShaderNodes::AssignOp& node) + void AstCloner::Visit(BinaryExpression& node) { - PushExpression(ShaderNodes::AssignOp::Build(node.op, CloneExpression(node.left), CloneExpression(node.right))); + auto clone = std::make_unique(); + clone->op = node.op; + clone->left = CloneExpression(node.left); + clone->right = CloneExpression(node.right); + + PushExpression(std::move(clone)); } - void ShaderAstCloner::Visit(ShaderNodes::BinaryOp& node) + void AstCloner::Visit(CastExpression& node) { - PushExpression(ShaderNodes::BinaryOp::Build(node.op, CloneExpression(node.left), CloneExpression(node.right))); - } + auto clone = std::make_unique(); + clone->targetType = node.targetType; - void ShaderAstCloner::Visit(ShaderNodes::Branch& node) - { - std::vector condStatements; - condStatements.reserve(node.condStatements.size()); - - for (auto& cond : node.condStatements) - { - auto& condStatement = condStatements.emplace_back(); - condStatement.condition = CloneExpression(cond.condition); - condStatement.statement = CloneStatement(cond.statement); - } - - PushStatement(ShaderNodes::Branch::Build(std::move(condStatements), CloneStatement(node.elseStatement))); - } - - void ShaderAstCloner::Visit(ShaderNodes::Cast& node) - { std::size_t expressionCount = 0; - std::array expressions; for (auto& expr : node.expressions) { if (!expr) break; - expressions[expressionCount] = CloneExpression(expr); - expressionCount++; + clone->expressions[expressionCount++] = CloneExpression(expr); } - PushExpression(ShaderNodes::Cast::Build(node.exprType, expressions.data(), expressionCount)); + PushExpression(std::move(clone)); } - void ShaderAstCloner::Visit(ShaderNodes::ConditionalExpression& node) + void AstCloner::Visit(ConditionalExpression& node) { - PushExpression(ShaderNodes::ConditionalExpression::Build(node.conditionName, CloneExpression(node.truePath), CloneExpression(node.falsePath))); + auto clone = std::make_unique(); + clone->conditionName = node.conditionName; + clone->falsePath = CloneExpression(node.falsePath); + clone->truePath = CloneExpression(node.truePath); + + PushExpression(std::move(clone)); } - void ShaderAstCloner::Visit(ShaderNodes::ConditionalStatement& node) + void AstCloner::Visit(ConstantExpression& node) { - PushStatement(ShaderNodes::ConditionalStatement::Build(node.conditionName, CloneStatement(node.statement))); + auto clone = std::make_unique(); + clone->value = node.value; + + PushExpression(std::move(clone)); } - void ShaderAstCloner::Visit(ShaderNodes::Constant& node) + void AstCloner::Visit(IdentifierExpression& node) { - PushExpression(ShaderNodes::Constant::Build(node.value)); + auto clone = std::make_unique(); + clone->identifier = node.identifier; + + PushExpression(std::move(clone)); } - void ShaderAstCloner::Visit(ShaderNodes::DeclareVariable& node) + void AstCloner::Visit(IntrinsicExpression& node) { - PushStatement(ShaderNodes::DeclareVariable::Build(CloneVariable(node.variable), CloneExpression(node.expression))); - } - - void ShaderAstCloner::Visit(ShaderNodes::Discard& /*node*/) - { - PushStatement(ShaderNodes::Discard::Build()); - } - - void ShaderAstCloner::Visit(ShaderNodes::ExpressionStatement& node) - { - PushStatement(ShaderNodes::ExpressionStatement::Build(CloneExpression(node.expression))); - } - - void ShaderAstCloner::Visit(ShaderNodes::Identifier& node) - { - PushExpression(ShaderNodes::Identifier::Build(CloneVariable(node.var))); - } - - void ShaderAstCloner::Visit(ShaderNodes::IntrinsicCall& node) - { - std::vector parameters; - parameters.reserve(node.parameters.size()); + auto clone = std::make_unique(); + clone->intrinsic = node.intrinsic; + clone->parameters.reserve(node.parameters.size()); for (auto& parameter : node.parameters) - parameters.push_back(CloneExpression(parameter)); + clone->parameters.push_back(CloneExpression(parameter)); - PushExpression(ShaderNodes::IntrinsicCall::Build(node.intrinsic, std::move(parameters))); + PushExpression(std::move(clone)); } - void ShaderAstCloner::Visit(ShaderNodes::NoOp& /*node*/) + void AstCloner::Visit(SwizzleExpression& node) { - PushStatement(ShaderNodes::NoOp::Build()); + auto clone = std::make_unique(); + clone->componentCount = node.componentCount; + clone->components = node.components; + clone->expression = CloneExpression(node.expression); + + PushExpression(std::move(clone)); } - void ShaderAstCloner::Visit(ShaderNodes::ReturnStatement& node) + void AstCloner::Visit(BranchStatement& node) { - PushStatement(ShaderNodes::ReturnStatement::Build(CloneExpression(node.returnExpr))); + auto clone = std::make_unique(); + clone->condStatements.reserve(node.condStatements.size()); + + for (auto& cond : node.condStatements) + { + auto& condStatement = clone->condStatements.emplace_back(); + condStatement.condition = CloneExpression(cond.condition); + condStatement.statement = CloneStatement(cond.statement); + } + + clone->elseStatement = CloneStatement(node.elseStatement); + + PushStatement(std::move(clone)); } - void ShaderAstCloner::Visit(ShaderNodes::Sample2D& node) + void AstCloner::Visit(ConditionalStatement& node) { - PushExpression(ShaderNodes::Sample2D::Build(CloneExpression(node.sampler), CloneExpression(node.coordinates))); + auto clone = std::make_unique(); + clone->conditionName = node.conditionName; + clone->statement = CloneStatement(node.statement); + + PushStatement(std::move(clone)); } - void ShaderAstCloner::Visit(ShaderNodes::StatementBlock& node) + void AstCloner::Visit(DeclareFunctionStatement& node) { - std::vector statements; - statements.reserve(node.statements.size()); + auto clone = std::make_unique(); + clone->name = node.name; + clone->parameters = node.parameters; + clone->returnType = node.returnType; + clone->statements.reserve(node.statements.size()); for (auto& statement : node.statements) - statements.push_back(CloneStatement(statement)); + clone->statements.push_back(CloneStatement(statement)); - PushStatement(ShaderNodes::StatementBlock::Build(std::move(statements))); + PushStatement(std::move(clone)); } - void ShaderAstCloner::Visit(ShaderNodes::SwizzleOp& node) + void AstCloner::Visit(DeclareStructStatement& node) { - PushExpression(ShaderNodes::SwizzleOp::Build(CloneExpression(node.expression), node.components.data(), node.componentCount)); + auto clone = std::make_unique(); + clone->description = node.description; + + PushStatement(std::move(clone)); } - void ShaderAstCloner::Visit(ShaderNodes::BuiltinVariable& var) + void AstCloner::Visit(DeclareVariableStatement& node) { - PushVariable(ShaderNodes::BuiltinVariable::Build(var.entry, var.type)); + auto clone = std::make_unique(); + clone->varName = node.varName; + clone->varType = node.varType; + clone->initialExpression = CloneExpression(node.initialExpression); + + PushStatement(std::move(clone)); } - void ShaderAstCloner::Visit(ShaderNodes::InputVariable& var) + void AstCloner::Visit(DiscardStatement& /*node*/) { - PushVariable(ShaderNodes::InputVariable::Build(var.name, var.type)); + PushStatement(std::make_unique()); } - void ShaderAstCloner::Visit(ShaderNodes::LocalVariable& var) + void AstCloner::Visit(ExpressionStatement& node) { - PushVariable(ShaderNodes::LocalVariable::Build(var.name, var.type)); + auto clone = std::make_unique(); + clone->expression = CloneExpression(node.expression); + + PushStatement(std::move(clone)); } - void ShaderAstCloner::Visit(ShaderNodes::OutputVariable& var) + void AstCloner::Visit(MultiStatement& node) { - PushVariable(ShaderNodes::OutputVariable::Build(var.name, var.type)); + auto clone = std::make_unique(); + clone->statements.reserve(node.statements.size()); + for (auto& statement : node.statements) + clone->statements.push_back(CloneStatement(statement)); + + PushStatement(std::move(clone)); } - void ShaderAstCloner::Visit(ShaderNodes::ParameterVariable& var) + void AstCloner::Visit(NoOpStatement& /*node*/) { - PushVariable(ShaderNodes::ParameterVariable::Build(var.name, var.type)); + PushStatement(std::make_unique()); } - void ShaderAstCloner::Visit(ShaderNodes::UniformVariable& var) + void AstCloner::Visit(ReturnStatement& node) { - PushVariable(ShaderNodes::UniformVariable::Build(var.name, var.type)); + auto clone = std::make_unique(); + clone->returnExpr = CloneExpression(node.returnExpr); + + PushStatement(std::move(clone)); } - void ShaderAstCloner::PushExpression(ShaderNodes::ExpressionPtr expression) + void AstCloner::PushExpression(ExpressionPtr expression) { m_expressionStack.emplace_back(std::move(expression)); } - void ShaderAstCloner::PushStatement(ShaderNodes::StatementPtr statement) + void AstCloner::PushStatement(StatementPtr statement) { m_statementStack.emplace_back(std::move(statement)); } - void ShaderAstCloner::PushVariable(ShaderNodes::VariablePtr variable) - { - m_variableStack.emplace_back(std::move(variable)); - } - - ShaderNodes::ExpressionPtr ShaderAstCloner::PopExpression() + ExpressionPtr AstCloner::PopExpression() { assert(!m_expressionStack.empty()); - ShaderNodes::ExpressionPtr expr = std::move(m_expressionStack.back()); + ExpressionPtr expr = std::move(m_expressionStack.back()); m_expressionStack.pop_back(); return expr; } - ShaderNodes::StatementPtr ShaderAstCloner::PopStatement() + StatementPtr AstCloner::PopStatement() { assert(!m_statementStack.empty()); - ShaderNodes::StatementPtr expr = std::move(m_statementStack.back()); + StatementPtr expr = std::move(m_statementStack.back()); m_statementStack.pop_back(); return expr; } - - ShaderNodes::VariablePtr ShaderAstCloner::PopVariable() - { - assert(!m_variableStack.empty()); - - ShaderNodes::VariablePtr var = std::move(m_variableStack.back()); - m_variableStack.pop_back(); - - return var; - } } diff --git a/src/Nazara/Shader/ShaderAstExpressionType.cpp b/src/Nazara/Shader/ShaderAstExpressionType.cpp new file mode 100644 index 000000000..be4f238e9 --- /dev/null +++ b/src/Nazara/Shader/ShaderAstExpressionType.cpp @@ -0,0 +1,198 @@ +// 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 +#include +#include +#include + +namespace Nz::ShaderAst +{ + ShaderExpressionType ExpressionTypeVisitor::GetExpressionType(Expression& expression, AstCache* cache = nullptr) + { + m_cache = cache; + ShaderExpressionType type = GetExpressionTypeInternal(expression); + m_cache = nullptr; + + return type; + } + + ShaderExpressionType ExpressionTypeVisitor::GetExpressionTypeInternal(Expression& expression) + { + m_lastExpressionType.reset(); + + Visit(expression); + + assert(m_lastExpressionType.has_value()); + return std::move(*m_lastExpressionType); + } + + void ExpressionTypeVisitor::Visit(Expression& expression) + { + if (m_cache) + { + auto it = m_cache->nodeExpressionType.find(&expression); + if (it != m_cache->nodeExpressionType.end()) + { + m_lastExpressionType = it->second; + return; + } + } + + expression.Visit(*this); + + if (m_cache) + { + assert(m_lastExpressionType.has_value()); + m_cache->nodeExpressionType.emplace(&expression, *m_lastExpressionType); + } + } + + void ExpressionTypeVisitor::Visit(AccessMemberExpression& node) + { + throw std::runtime_error("unhandled accessmember expression"); + } + + void ExpressionTypeVisitor::Visit(AssignExpression& node) + { + Visit(*node.left); + } + + void ExpressionTypeVisitor::Visit(BinaryExpression& node) + { + switch (node.op) + { + case BinaryType::Add: + case BinaryType::Subtract: + return Visit(*node.left); + + case BinaryType::Divide: + case BinaryType::Multiply: + { + ShaderExpressionType leftExprType = GetExpressionTypeInternal(*node.left); + assert(IsBasicType(leftExprType)); + + ShaderExpressionType rightExprType = GetExpressionTypeInternal(*node.right); + assert(IsBasicType(rightExprType)); + + switch (std::get(leftExprType)) + { + case BasicType::Boolean: + case BasicType::Float2: + case BasicType::Float3: + case BasicType::Float4: + case BasicType::Int2: + case BasicType::Int3: + case BasicType::Int4: + case BasicType::UInt2: + case BasicType::UInt3: + case BasicType::UInt4: + m_lastExpressionType = std::move(leftExprType); + break; + + case BasicType::Float1: + case BasicType::Int1: + case BasicType::Mat4x4: + case BasicType::UInt1: + m_lastExpressionType = std::move(rightExprType); + break; + + case BasicType::Sampler2D: + case BasicType::Void: + break; + } + + break; + } + + case BinaryType::CompEq: + case BinaryType::CompGe: + case BinaryType::CompGt: + case BinaryType::CompLe: + case BinaryType::CompLt: + case BinaryType::CompNe: + m_lastExpressionType = BasicType::Boolean; + break; + } + } + + void ExpressionTypeVisitor::Visit(CastExpression& node) + { + m_lastExpressionType = node.targetType; + } + + void ExpressionTypeVisitor::Visit(ConditionalExpression& node) + { + ShaderExpressionType leftExprType = GetExpressionTypeInternal(*node.truePath); + assert(leftExprType == GetExpressionTypeInternal(*node.falsePath)); + + m_lastExpressionType = std::move(leftExprType); + } + + void ExpressionTypeVisitor::Visit(ConstantExpression& node) + { + m_lastExpressionType = std::visit([&](auto&& arg) + { + using T = std::decay_t; + + if constexpr (std::is_same_v) + return BasicType::Boolean; + else if constexpr (std::is_same_v) + return BasicType::Float1; + else if constexpr (std::is_same_v) + return BasicType::Int1; + else if constexpr (std::is_same_v) + return BasicType::Int1; + else if constexpr (std::is_same_v) + return BasicType::Float2; + else if constexpr (std::is_same_v) + return BasicType::Float3; + else if constexpr (std::is_same_v) + return BasicType::Float4; + else if constexpr (std::is_same_v) + return BasicType::Int2; + else if constexpr (std::is_same_v) + return BasicType::Int3; + else if constexpr (std::is_same_v) + return BasicType::Int4; + else + static_assert(AlwaysFalse::value, "non-exhaustive visitor"); + }, node.value); + } + + void ExpressionTypeVisitor::Visit(IdentifierExpression& node) + { + auto scopeIt = m_cache->scopeIdByNode.find(&node); + if (scopeIt == m_cache->scopeIdByNode.end()) + throw std::runtime_error("internal error"); + + const AstCache::Identifier* identifier = m_cache->FindIdentifier(scopeIt->second, node.identifier); + if (!identifier || !std::holds_alternative(identifier->value)) + throw std::runtime_error("internal error"); + + m_lastExpressionType = std::get(identifier->value).type; + } + + void ExpressionTypeVisitor::Visit(IntrinsicExpression& node) + { + switch (node.intrinsic) + { + case IntrinsicType::CrossProduct: + Visit(*node.parameters.front()); + break; + + case IntrinsicType::DotProduct: + m_lastExpressionType = BasicType::Float1; + break; + } + } + + void ExpressionTypeVisitor::Visit(SwizzleExpression& node) + { + const ShaderExpressionType& exprType = GetExpressionTypeInternal(*node.expression); + assert(IsBasicType(exprType)); + + m_lastExpressionType = static_cast(UnderlyingCast(GetComponentType(std::get(exprType))) + node.componentCount - 1); + } +} diff --git a/src/Nazara/Shader/ShaderAstVisitor.cpp b/src/Nazara/Shader/ShaderAstExpressionVisitor.cpp similarity index 52% rename from src/Nazara/Shader/ShaderAstVisitor.cpp rename to src/Nazara/Shader/ShaderAstExpressionVisitor.cpp index 719e3ad99..44beed045 100644 --- a/src/Nazara/Shader/ShaderAstVisitor.cpp +++ b/src/Nazara/Shader/ShaderAstExpressionVisitor.cpp @@ -2,15 +2,10 @@ // This file is part of the "Nazara Engine - Shader generator" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include -namespace Nz +namespace Nz::ShaderAst { - ShaderAstVisitor::~ShaderAstVisitor() = default; - - void ShaderAstVisitor::Visit(const ShaderNodes::NodePtr& node) - { - node->Visit(*this); - } + AstExpressionVisitor::~AstExpressionVisitor() = default; } diff --git a/src/Nazara/Shader/ShaderAstExpressionVisitorExcept.cpp b/src/Nazara/Shader/ShaderAstExpressionVisitorExcept.cpp new file mode 100644 index 000000000..1fddc0e78 --- /dev/null +++ b/src/Nazara/Shader/ShaderAstExpressionVisitorExcept.cpp @@ -0,0 +1,15 @@ +// 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 +#include + +namespace Nz::ShaderAst +{ +#define NAZARA_SHADERAST_EXPRESSION(Node) void ExpressionVisitorExcept::Visit(ShaderAst::Node& /*node*/) \ + { \ + throw std::runtime_error("unexpected " #Node " node"); \ + } +#include +} diff --git a/src/Nazara/Shader/ShaderAstOptimizer.cpp b/src/Nazara/Shader/ShaderAstOptimizer.cpp index b2e5acf96..33c8d3f76 100644 --- a/src/Nazara/Shader/ShaderAstOptimizer.cpp +++ b/src/Nazara/Shader/ShaderAstOptimizer.cpp @@ -3,16 +3,22 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include #include +#include #include #include #include -namespace Nz +namespace Nz::ShaderAst { namespace { + template + std::unique_ptr static_unique_pointer_cast(std::unique_ptr&& ptr) + { + return std::unique_ptr(static_cast(ptr.release())); + } + template struct is_complete_helper { @@ -29,14 +35,14 @@ namespace Nz inline constexpr bool is_complete_v = is_complete::value; - template + template struct PropagateConstantType; // CompEq template struct CompEqBase { - ShaderNodes::ExpressionPtr operator()(const T1& lhs, const T2& rhs) + ExpressionPtr operator()(const T1& lhs, const T2& rhs) { return ShaderBuilder::Constant(lhs == rhs); } @@ -46,7 +52,7 @@ namespace Nz struct CompEq; template - struct PropagateConstantType + struct PropagateConstantType { using Op = typename CompEq; }; @@ -55,7 +61,7 @@ namespace Nz template struct CompGeBase { - ShaderNodes::ExpressionPtr operator()(const T1& lhs, const T2& rhs) + ExpressionPtr operator()(const T1& lhs, const T2& rhs) { return ShaderBuilder::Constant(lhs >= rhs); } @@ -65,7 +71,7 @@ namespace Nz struct CompGe; template - struct PropagateConstantType + struct PropagateConstantType { using Op = typename CompGe; }; @@ -74,7 +80,7 @@ namespace Nz template struct CompGtBase { - ShaderNodes::ExpressionPtr operator()(const T1& lhs, const T2& rhs) + ExpressionPtr operator()(const T1& lhs, const T2& rhs) { return ShaderBuilder::Constant(lhs > rhs); } @@ -84,7 +90,7 @@ namespace Nz struct CompGt; template - struct PropagateConstantType + struct PropagateConstantType { using Op = typename CompGt; }; @@ -93,7 +99,7 @@ namespace Nz template struct CompLeBase { - ShaderNodes::ExpressionPtr operator()(const T1& lhs, const T2& rhs) + ExpressionPtr operator()(const T1& lhs, const T2& rhs) { return ShaderBuilder::Constant(lhs <= rhs); } @@ -103,7 +109,7 @@ namespace Nz struct CompLe; template - struct PropagateConstantType + struct PropagateConstantType { using Op = typename CompLe; }; @@ -112,7 +118,7 @@ namespace Nz template struct CompLtBase { - ShaderNodes::ExpressionPtr operator()(const T1& lhs, const T2& rhs) + ExpressionPtr operator()(const T1& lhs, const T2& rhs) { return ShaderBuilder::Constant(lhs < rhs); } @@ -122,7 +128,7 @@ namespace Nz struct CompLt; template - struct PropagateConstantType + struct PropagateConstantType { using Op = typename CompLe; }; @@ -131,7 +137,7 @@ namespace Nz template struct CompNeBase { - ShaderNodes::ExpressionPtr operator()(const T1& lhs, const T2& rhs) + ExpressionPtr operator()(const T1& lhs, const T2& rhs) { return ShaderBuilder::Constant(lhs != rhs); } @@ -141,7 +147,7 @@ namespace Nz struct CompNe; template - struct PropagateConstantType + struct PropagateConstantType { using Op = typename CompNe; }; @@ -150,7 +156,7 @@ namespace Nz template struct AdditionBase { - ShaderNodes::ExpressionPtr operator()(const T1& lhs, const T2& rhs) + ExpressionPtr operator()(const T1& lhs, const T2& rhs) { return ShaderBuilder::Constant(lhs + rhs); } @@ -160,7 +166,7 @@ namespace Nz struct Addition; template - struct PropagateConstantType + struct PropagateConstantType { using Op = typename Addition; }; @@ -169,7 +175,7 @@ namespace Nz template struct DivisionBase { - ShaderNodes::ExpressionPtr operator()(const T1& lhs, const T2& rhs) + ExpressionPtr operator()(const T1& lhs, const T2& rhs) { return ShaderBuilder::Constant(lhs / rhs); } @@ -179,7 +185,7 @@ namespace Nz struct Division; template - struct PropagateConstantType + struct PropagateConstantType { using Op = typename Division; }; @@ -188,7 +194,7 @@ namespace Nz template struct MultiplicationBase { - ShaderNodes::ExpressionPtr operator()(const T1& lhs, const T2& rhs) + ExpressionPtr operator()(const T1& lhs, const T2& rhs) { return ShaderBuilder::Constant(lhs * rhs); } @@ -198,7 +204,7 @@ namespace Nz struct Multiplication; template - struct PropagateConstantType + struct PropagateConstantType { using Op = typename Multiplication; }; @@ -207,7 +213,7 @@ namespace Nz template struct SubtractionBase { - ShaderNodes::ExpressionPtr operator()(const T1& lhs, const T2& rhs) + ExpressionPtr operator()(const T1& lhs, const T2& rhs) { return ShaderBuilder::Constant(lhs - rhs); } @@ -217,7 +223,7 @@ namespace Nz struct Subtraction; template - struct PropagateConstantType + struct PropagateConstantType { using Op = typename Subtraction; }; @@ -375,92 +381,89 @@ namespace Nz #undef EnableOptimisation } - ShaderNodes::StatementPtr ShaderAstOptimizer::Optimise(const ShaderNodes::StatementPtr& statement) + StatementPtr AstOptimizer::Optimise(StatementPtr& statement) { - m_shaderAst = nullptr; - return CloneStatement(statement); } - ShaderNodes::StatementPtr ShaderAstOptimizer::Optimise(const ShaderNodes::StatementPtr& statement, const ShaderAst& shader, UInt64 enabledConditions) + StatementPtr AstOptimizer::Optimise(StatementPtr& statement, UInt64 enabledConditions) { - m_shaderAst = &shader; m_enabledConditions = enabledConditions; return CloneStatement(statement); } - void ShaderAstOptimizer::Visit(ShaderNodes::BinaryOp& node) + void AstOptimizer::Visit(BinaryExpression& node) { auto lhs = CloneExpression(node.left); auto rhs = CloneExpression(node.right); - if (lhs->GetType() == ShaderNodes::NodeType::Constant && rhs->GetType() == ShaderNodes::NodeType::Constant) + if (lhs->GetType() == NodeType::ConstantExpression && rhs->GetType() == NodeType::ConstantExpression) { - auto lhsConstant = std::static_pointer_cast(lhs); - auto rhsConstant = std::static_pointer_cast(rhs); + auto lhsConstant = static_unique_pointer_cast(std::move(lhs)); + auto rhsConstant = static_unique_pointer_cast(std::move(rhs)); switch (node.op) { - case ShaderNodes::BinaryType::Add: - return PropagateConstant(lhsConstant, rhsConstant); + case BinaryType::Add: + return PropagateConstant(std::move(lhsConstant), std::move(rhsConstant)); - case ShaderNodes::BinaryType::Subtract: - return PropagateConstant(lhsConstant, rhsConstant); + case BinaryType::Subtract: + return PropagateConstant(std::move(lhsConstant), std::move(rhsConstant)); - case ShaderNodes::BinaryType::Multiply: - return PropagateConstant(lhsConstant, rhsConstant); + case BinaryType::Multiply: + return PropagateConstant(std::move(lhsConstant), std::move(rhsConstant)); - case ShaderNodes::BinaryType::Divide: - return PropagateConstant(lhsConstant, rhsConstant); + case BinaryType::Divide: + return PropagateConstant(std::move(lhsConstant), std::move(rhsConstant)); - case ShaderNodes::BinaryType::CompEq: - return PropagateConstant(lhsConstant, rhsConstant); + case BinaryType::CompEq: + return PropagateConstant(std::move(lhsConstant), std::move(rhsConstant)); - case ShaderNodes::BinaryType::CompGe: - return PropagateConstant(lhsConstant, rhsConstant); + case BinaryType::CompGe: + return PropagateConstant(std::move(lhsConstant), std::move(rhsConstant)); - case ShaderNodes::BinaryType::CompGt: - return PropagateConstant(lhsConstant, rhsConstant); + case BinaryType::CompGt: + return PropagateConstant(std::move(lhsConstant), std::move(rhsConstant)); - case ShaderNodes::BinaryType::CompLe: - return PropagateConstant(lhsConstant, rhsConstant); + case BinaryType::CompLe: + return PropagateConstant(std::move(lhsConstant), std::move(rhsConstant)); - case ShaderNodes::BinaryType::CompLt: - return PropagateConstant(lhsConstant, rhsConstant); + case BinaryType::CompLt: + return PropagateConstant(std::move(lhsConstant), std::move(rhsConstant)); - case ShaderNodes::BinaryType::CompNe: - return PropagateConstant(lhsConstant, rhsConstant); + case BinaryType::CompNe: + return PropagateConstant(std::move(lhsConstant), std::move(rhsConstant)); } } - ShaderAstCloner::Visit(node); + AstCloner::Visit(node); } - void ShaderAstOptimizer::Visit(ShaderNodes::Branch& node) + void AstOptimizer::Visit(BranchStatement& node) { - std::vector statements; - ShaderNodes::StatementPtr elseStatement; + std::vector statements; + StatementPtr elseStatement; for (auto& condStatement : node.condStatements) { auto cond = CloneExpression(condStatement.condition); - if (cond->GetType() == ShaderNodes::NodeType::Constant) + if (cond->GetType() == NodeType::ConstantExpression) { - auto constant = std::static_pointer_cast(cond); + auto& constant = static_cast(*cond); - assert(IsBasicType(cond->GetExpressionType())); - assert(std::get(cond->GetExpressionType()) == ShaderNodes::BasicType::Boolean); + assert(IsBasicType(GetExpressionType(constant))); + assert(std::get(GetExpressionType(constant)) == BasicType::Boolean); - bool cValue = std::get(constant->value); + bool cValue = std::get(constant.value); if (!cValue) continue; if (statements.empty()) { // First condition is true, dismiss the branch - Visit(condStatement.statement); + condStatement.statement->Visit(*this); return; } else @@ -482,47 +485,54 @@ namespace Nz { // All conditions have been removed, replace by else statement or no-op if (node.elseStatement) - return Visit(node.elseStatement); + { + node.elseStatement->Visit(*this); + return; + } else - return PushStatement(ShaderNodes::NoOp::Build()); + return PushStatement(ShaderBuilder::NoOp()); } if (!elseStatement) elseStatement = CloneStatement(node.elseStatement); - PushStatement(ShaderNodes::Branch::Build(std::move(statements), std::move(elseStatement))); + PushStatement(ShaderBuilder::Branch(std::move(statements), std::move(elseStatement))); } - void ShaderAstOptimizer::Visit(ShaderNodes::ConditionalExpression& node) + void AstOptimizer::Visit(ConditionalExpression& node) { - if (!m_shaderAst) + return AstCloner::Visit(node); + + /*if (!m_shaderAst) return ShaderAstCloner::Visit(node); std::size_t conditionIndex = m_shaderAst->FindConditionByName(node.conditionName); - assert(conditionIndex != ShaderAst::InvalidCondition); + assert(conditionIndex != InvalidCondition); if (TestBit(m_enabledConditions, conditionIndex)) Visit(node.truePath); else - Visit(node.falsePath); + Visit(node.falsePath);*/ } - void ShaderAstOptimizer::Visit(ShaderNodes::ConditionalStatement& node) + void AstOptimizer::Visit(ConditionalStatement& node) { - if (!m_shaderAst) + return AstCloner::Visit(node); + + /*if (!m_shaderAst) return ShaderAstCloner::Visit(node); std::size_t conditionIndex = m_shaderAst->FindConditionByName(node.conditionName); - assert(conditionIndex != ShaderAst::InvalidCondition); + assert(conditionIndex != InvalidCondition); if (TestBit(m_enabledConditions, conditionIndex)) - Visit(node.statement); + Visit(node.statement);*/ } - template - void ShaderAstOptimizer::PropagateConstant(const std::shared_ptr& lhs, const std::shared_ptr& rhs) + template + void AstOptimizer::PropagateConstant(std::unique_ptr&& lhs, std::unique_ptr&& rhs) { - ShaderNodes::ExpressionPtr optimized; + ExpressionPtr optimized; std::visit([&](auto&& arg1) { using T1 = std::decay_t; @@ -543,8 +553,8 @@ namespace Nz }, lhs->value); if (optimized) - PushExpression(optimized); + PushExpression(std::move(optimized)); else - PushExpression(ShaderNodes::BinaryOp::Build(Type, lhs, rhs)); + PushExpression(ShaderBuilder::Binary(Type, std::move(lhs), std::move(rhs))); } } diff --git a/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp b/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp index f4d858d91..c0ef0d920 100644 --- a/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp +++ b/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp @@ -5,116 +5,121 @@ #include #include -namespace Nz +namespace Nz::ShaderAst { - void ShaderAstRecursiveVisitor::Visit(ShaderNodes::AccessMember& node) + void AstRecursiveVisitor::Visit(AccessMemberExpression& node) { - Visit(node.structExpr); + node.structExpr->Visit(*this); } - void ShaderAstRecursiveVisitor::Visit(ShaderNodes::AssignOp& node) + void AstRecursiveVisitor::Visit(AssignExpression& node) { - Visit(node.left); - Visit(node.right); + node.left->Visit(*this); + node.right->Visit(*this); } - void ShaderAstRecursiveVisitor::Visit(ShaderNodes::BinaryOp& node) + void AstRecursiveVisitor::Visit(BinaryExpression& node) { - Visit(node.left); - Visit(node.right); + node.left->Visit(*this); + node.right->Visit(*this); } - void ShaderAstRecursiveVisitor::Visit(ShaderNodes::Branch& node) - { - for (auto& cond : node.condStatements) - { - Visit(cond.condition); - Visit(cond.statement); - } - - if (node.elseStatement) - Visit(node.elseStatement); - } - - void ShaderAstRecursiveVisitor::Visit(ShaderNodes::Cast& node) + void AstRecursiveVisitor::Visit(CastExpression& node) { for (auto& expr : node.expressions) { if (!expr) break; - Visit(expr); + expr->Visit(*this); } } - void ShaderAstRecursiveVisitor::Visit(ShaderNodes::ConditionalExpression& node) + void AstRecursiveVisitor::Visit(ConditionalExpression& node) { - Visit(node.truePath); - Visit(node.falsePath); + node.truePath->Visit(*this); + node.falsePath->Visit(*this); } - void ShaderAstRecursiveVisitor::Visit(ShaderNodes::ConditionalStatement& node) - { - Visit(node.statement); - } - - void ShaderAstRecursiveVisitor::Visit(ShaderNodes::Constant& /*node*/) + void AstRecursiveVisitor::Visit(ConstantExpression& /*node*/) { /* Nothing to do */ } - void ShaderAstRecursiveVisitor::Visit(ShaderNodes::DeclareVariable& node) - { - if (node.expression) - Visit(node.expression); - } - - void ShaderAstRecursiveVisitor::Visit(ShaderNodes::Discard& /*node*/) + void AstRecursiveVisitor::Visit(IdentifierExpression& /*node*/) { /* Nothing to do */ } - void ShaderAstRecursiveVisitor::Visit(ShaderNodes::ExpressionStatement& node) - { - Visit(node.expression); - } - - void ShaderAstRecursiveVisitor::Visit(ShaderNodes::Identifier& /*node*/) - { - /* Nothing to do */ - } - - void ShaderAstRecursiveVisitor::Visit(ShaderNodes::IntrinsicCall& node) + void AstRecursiveVisitor::Visit(IntrinsicExpression& node) { for (auto& param : node.parameters) - Visit(param); + param->Visit(*this); } - void ShaderAstRecursiveVisitor::Visit(ShaderNodes::NoOp& /*node*/) + void AstRecursiveVisitor::Visit(SwizzleExpression& node) + { + node.expression->Visit(*this); + } + + void AstRecursiveVisitor::Visit(BranchStatement& node) + { + for (auto& cond : node.condStatements) + { + cond.condition->Visit(*this); + cond.statement->Visit(*this); + } + + if (node.elseStatement) + node.elseStatement->Visit(*this); + } + + void AstRecursiveVisitor::Visit(ConditionalStatement& node) + { + node.statement->Visit(*this); + } + + void AstRecursiveVisitor::Visit(DeclareFunctionStatement& node) + { + for (auto& statement : node.statements) + statement->Visit(*this); + } + + void AstRecursiveVisitor::Visit(DeclareStructStatement& /*node*/) { /* Nothing to do */ } - void ShaderAstRecursiveVisitor::Visit(ShaderNodes::ReturnStatement& node) + void AstRecursiveVisitor::Visit(DeclareVariableStatement& node) { - if (node.returnExpr) - Visit(node.returnExpr); + if (node.initialExpression) + node.initialExpression->Visit(*this); } - void ShaderAstRecursiveVisitor::Visit(ShaderNodes::Sample2D& node) + void AstRecursiveVisitor::Visit(DiscardStatement& /*node*/) { - Visit(node.sampler); - Visit(node.coordinates); + /* Nothing to do */ } - void ShaderAstRecursiveVisitor::Visit(ShaderNodes::StatementBlock& node) + void AstRecursiveVisitor::Visit(ExpressionStatement& node) + { + node.expression->Visit(*this); + } + + void AstRecursiveVisitor::Visit(MultiStatement& node) { for (auto& statement : node.statements) - Visit(statement); + statement->Visit(*this); } - void ShaderAstRecursiveVisitor::Visit(ShaderNodes::SwizzleOp& node) + void AstRecursiveVisitor::Visit(NoOpStatement& /*node*/) { - Visit(node.expression); + /* Nothing to do */ + } + + void AstRecursiveVisitor::Visit(ReturnStatement& node) + { + if (node.returnExpr) + node.returnExpr->Visit(*this); } } diff --git a/src/Nazara/Shader/ShaderAstSerializer.cpp b/src/Nazara/Shader/ShaderAstSerializer.cpp index 13780339b..4100a0204 100644 --- a/src/Nazara/Shader/ShaderAstSerializer.cpp +++ b/src/Nazara/Shader/ShaderAstSerializer.cpp @@ -3,221 +3,74 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include -#include +#include +#include #include -namespace Nz +namespace Nz::ShaderAst { namespace { constexpr UInt32 s_magicNumber = 0x4E534852; constexpr UInt32 s_currentVersion = 1; - class ShaderSerializerVisitor : public ShaderAstVisitor, public ShaderVarVisitor + class ShaderSerializerVisitor : public AstExpressionVisitor, public AstStatementVisitor { public: - ShaderSerializerVisitor(ShaderAstSerializerBase& serializer) : + ShaderSerializerVisitor(AstSerializerBase& serializer) : m_serializer(serializer) { } - void Visit(ShaderNodes::AccessMember& node) override - { - Serialize(node); - } - - void Visit(ShaderNodes::AssignOp& node) override - { - Serialize(node); - } - - void Visit(ShaderNodes::BinaryOp& node) override - { - Serialize(node); - } - - void Visit(ShaderNodes::Branch& node) override - { - Serialize(node); - } - - void Visit(ShaderNodes::Cast& node) override - { - Serialize(node); - } - - void Visit(ShaderNodes::ConditionalExpression& node) override - { - Serialize(node); - } - - void Visit(ShaderNodes::ConditionalStatement& node) override - { - Serialize(node); - } - - void Visit(ShaderNodes::Constant& node) override - { - Serialize(node); - } - - void Visit(ShaderNodes::DeclareVariable& node) override - { - Serialize(node); - } - - void Visit(ShaderNodes::Discard& node) override - { - Serialize(node); - } - - void Visit(ShaderNodes::ExpressionStatement& node) override - { - Serialize(node); - } - - void Visit(ShaderNodes::Identifier& node) override - { - Serialize(node); - } - - void Visit(ShaderNodes::IntrinsicCall& node) override - { - Serialize(node); - } - - void Visit(ShaderNodes::NoOp& node) override - { - Serialize(node); - } - - void Visit(ShaderNodes::ReturnStatement& node) override - { - Serialize(node); - } - - void Visit(ShaderNodes::Sample2D& node) override - { - Serialize(node); - } - - void Visit(ShaderNodes::StatementBlock& node) override - { - Serialize(node); - } - - void Visit(ShaderNodes::SwizzleOp& node) override - { - Serialize(node); - } - - - void Visit(ShaderNodes::BuiltinVariable& var) override - { - Serialize(var); - } - - void Visit(ShaderNodes::InputVariable& var) override - { - Serialize(var); - } - - void Visit(ShaderNodes::LocalVariable& var) override - { - Serialize(var); - } - - void Visit(ShaderNodes::OutputVariable& var) override - { - Serialize(var); - } - - void Visit(ShaderNodes::ParameterVariable& var) override - { - Serialize(var); - } - - void Visit(ShaderNodes::UniformVariable& var) override - { - Serialize(var); +#define NAZARA_SHADERAST_NODE(Node) void Visit(Node& node) override \ + { \ + m_serializer.Serialize(node); \ } +#include private: - template - void Serialize(const T& node) - { - // I know const_cast is evil but I don't have a better solution here (it's not used to write) - m_serializer.Serialize(const_cast(node)); - } - - ShaderAstSerializerBase& m_serializer; + AstSerializerBase& m_serializer; }; } - void ShaderAstSerializerBase::Serialize(ShaderNodes::AccessMember& node) + void AstSerializerBase::Serialize(AccessMemberExpression& node) { Node(node.structExpr); - Type(node.exprType); - Container(node.memberIndices); - for (std::size_t& index : node.memberIndices) - SizeT(index); + Container(node.memberIdentifiers); + for (std::string& identifier : node.memberIdentifiers) + Value(identifier); } - void ShaderAstSerializerBase::Serialize(ShaderNodes::AssignOp& node) + void AstSerializerBase::Serialize(AssignExpression& node) { Enum(node.op); Node(node.left); Node(node.right); } - void ShaderAstSerializerBase::Serialize(ShaderNodes::BinaryOp& node) + void AstSerializerBase::Serialize(BinaryExpression& node) { Enum(node.op); Node(node.left); Node(node.right); } - void ShaderAstSerializerBase::Serialize(ShaderNodes::Branch& node) + void AstSerializerBase::Serialize(CastExpression& node) { - Container(node.condStatements); - for (auto& condStatement : node.condStatements) - { - Node(condStatement.condition); - Node(condStatement.statement); - } - - Node(node.elseStatement); - } - - void ShaderAstSerializerBase::Serialize(ShaderNodes::BuiltinVariable& node) - { - Enum(node.entry); - Type(node.type); - } - - void ShaderAstSerializerBase::Serialize(ShaderNodes::Cast& node) - { - Enum(node.exprType); + Enum(node.targetType); for (auto& expr : node.expressions) Node(expr); } - void ShaderAstSerializerBase::Serialize(ShaderNodes::ConditionalExpression& node) + void AstSerializerBase::Serialize(ConditionalExpression& node) { Value(node.conditionName); Node(node.truePath); Node(node.falsePath); } - - void ShaderAstSerializerBase::Serialize(ShaderNodes::ConditionalStatement& node) - { - Value(node.conditionName); - Node(node.statement); - } - - void ShaderAstSerializerBase::Serialize(ShaderNodes::Constant& node) + + void AstSerializerBase::Serialize(ConstantExpression& node) { UInt32 typeIndex; if (IsWriting()) @@ -251,28 +104,19 @@ namespace Nz } } - void ShaderAstSerializerBase::Serialize(ShaderNodes::DeclareVariable& node) + void AstSerializerBase::Serialize(DeclareVariableStatement& node) { - Variable(node.variable); - Node(node.expression); + Value(node.varName); + Type(node.varType); + Node(node.initialExpression); } - void ShaderAstSerializerBase::Serialize(ShaderNodes::Discard& /*node*/) + void AstSerializerBase::Serialize(IdentifierExpression& node) { - /* Nothing to do */ + Value(node.identifier); } - void ShaderAstSerializerBase::Serialize(ShaderNodes::ExpressionStatement& node) - { - Node(node.expression); - } - - void ShaderAstSerializerBase::Serialize(ShaderNodes::Identifier& node) - { - Variable(node.var); - } - - void ShaderAstSerializerBase::Serialize(ShaderNodes::IntrinsicCall& node) + void AstSerializerBase::Serialize(IntrinsicExpression& node) { Enum(node.intrinsic); Container(node.parameters); @@ -280,36 +124,7 @@ namespace Nz Node(param); } - void ShaderAstSerializerBase::Serialize(ShaderNodes::NamedVariable& node) - { - Value(node.name); - Type(node.type); - } - - void ShaderAstSerializerBase::Serialize(ShaderNodes::NoOp& /*node*/) - { - /* Nothing to do */ - } - - void ShaderAstSerializerBase::Serialize(ShaderNodes::ReturnStatement& node) - { - Node(node.returnExpr); - } - - void ShaderAstSerializerBase::Serialize(ShaderNodes::Sample2D& node) - { - Node(node.sampler); - Node(node.coordinates); - } - - void ShaderAstSerializerBase::Serialize(ShaderNodes::StatementBlock& node) - { - Container(node.statements); - for (auto& statement : node.statements) - Node(statement); - } - - void ShaderAstSerializerBase::Serialize(ShaderNodes::SwizzleOp& node) + void AstSerializerBase::Serialize(SwizzleExpression& node) { SizeT(node.componentCount); Node(node.expression); @@ -319,100 +134,85 @@ namespace Nz } - void ShaderAstSerializer::Serialize(const ShaderAst& shader) + void AstSerializerBase::Serialize(BranchStatement& node) + { + Container(node.condStatements); + for (auto& condStatement : node.condStatements) + { + Node(condStatement.condition); + Node(condStatement.statement); + } + + Node(node.elseStatement); + } + + void AstSerializerBase::Serialize(ConditionalStatement& node) + { + Value(node.conditionName); + Node(node.statement); + } + + void AstSerializerBase::Serialize(DeclareFunctionStatement& node) + { + Value(node.name); + Type(node.returnType); + + Container(node.parameters); + for (auto& parameter : node.parameters) + { + Value(parameter.name); + Type(parameter.type); + } + + Container(node.statements); + for (auto& statement : node.statements) + Node(statement); + } + + void AstSerializerBase::Serialize(DeclareStructStatement& node) + { + Value(node.description.name); + + Container(node.description.members); + for (auto& member : node.description.members) + { + Value(member.name); + Type(member.type); + } + } + + void AstSerializerBase::Serialize(DiscardStatement& /*node*/) + { + /* Nothing to do */ + } + + void AstSerializerBase::Serialize(ExpressionStatement& node) + { + Node(node.expression); + } + + void AstSerializerBase::Serialize(MultiStatement& node) + { + Container(node.statements); + for (auto& statement : node.statements) + Node(statement); + } + + void AstSerializerBase::Serialize(NoOpStatement& /*node*/) + { + /* Nothing to do */ + } + + void AstSerializerBase::Serialize(ReturnStatement& node) + { + Node(node.returnExpr); + } + + void ShaderAstSerializer::Serialize(StatementPtr& shader) { m_stream << s_magicNumber << s_currentVersion; - m_stream << UInt32(shader.GetStage()); - - auto SerializeType = [&](const ShaderExpressionType& type) - { - std::visit([&](auto&& arg) - { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - m_stream << UInt8(0); - m_stream << UInt32(arg); - } - else if constexpr (std::is_same_v) - { - m_stream << UInt8(1); - m_stream << arg; - } - else - static_assert(AlwaysFalse::value, "non-exhaustive visitor"); - }, type); - }; - - auto SerializeInputOutput = [&](auto& inout) - { - m_stream << UInt32(inout.size()); - for (const auto& data : inout) - { - m_stream << data.name; - SerializeType(data.type); - - m_stream << data.locationIndex.has_value(); - if (data.locationIndex) - m_stream << UInt32(data.locationIndex.value()); - } - }; - - // Conditions - m_stream << UInt32(shader.GetConditionCount()); - for (const auto& cond : shader.GetConditions()) - m_stream << cond.name; - - // Structs - m_stream << UInt32(shader.GetStructCount()); - for (const auto& s : shader.GetStructs()) - { - m_stream << s.name; - m_stream << UInt32(s.members.size()); - for (const auto& member : s.members) - { - m_stream << member.name; - SerializeType(member.type); - } - } - - // Inputs / Outputs - SerializeInputOutput(shader.GetInputs()); - SerializeInputOutput(shader.GetOutputs()); - - // Uniforms - m_stream << UInt32(shader.GetUniformCount()); - for (const auto& uniform : shader.GetUniforms()) - { - m_stream << uniform.name; - SerializeType(uniform.type); - - m_stream << uniform.bindingIndex.has_value(); - if (uniform.bindingIndex) - m_stream << UInt32(uniform.bindingIndex.value()); - - m_stream << uniform.memoryLayout.has_value(); - if (uniform.memoryLayout) - m_stream << UInt32(uniform.memoryLayout.value()); - } - - // Functions - m_stream << UInt32(shader.GetFunctionCount()); - for (const auto& func : shader.GetFunctions()) - { - m_stream << func.name; - SerializeType(func.returnType); - - m_stream << UInt32(func.parameters.size()); - for (const auto& param : func.parameters) - { - m_stream << param.name; - SerializeType(param.type); - } - - Node(func.statement); - } + Node(shader); m_stream.FlushBits(); } @@ -422,9 +222,21 @@ namespace Nz return true; } - void ShaderAstSerializer::Node(ShaderNodes::NodePtr& node) + void ShaderAstSerializer::Node(ExpressionPtr& node) { - ShaderNodes::NodeType nodeType = (node) ? node->GetType() : ShaderNodes::NodeType::None; + NodeType nodeType = (node) ? node->GetType() : NodeType::None; + m_stream << static_cast(nodeType); + + if (node) + { + ShaderSerializerVisitor visitor(*this); + node->Visit(visitor); + } + } + + void ShaderAstSerializer::Node(StatementPtr& node) + { + NodeType nodeType = (node) ? node->GetType() : NodeType::None; m_stream << static_cast(nodeType); if (node) @@ -439,7 +251,7 @@ namespace Nz std::visit([&](auto&& arg) { using T = std::decay_t; - if constexpr (std::is_same_v) + if constexpr (std::is_same_v) { m_stream << UInt8(0); m_stream << UInt32(arg); @@ -454,11 +266,6 @@ namespace Nz }, type); } - void ShaderAstSerializer::Node(const ShaderNodes::NodePtr& node) - { - Node(const_cast(node)); //< Yes const_cast is ugly but it won't be used for writing - } - void ShaderAstSerializer::Value(bool& val) { m_stream << val; @@ -529,19 +336,7 @@ namespace Nz m_stream << val; } - void ShaderAstSerializer::Variable(ShaderNodes::VariablePtr& var) - { - ShaderNodes::VariableType nodeType = (var) ? var->GetType() : ShaderNodes::VariableType::None; - m_stream << static_cast(nodeType); - - if (var) - { - ShaderSerializerVisitor visitor(*this); - var->Visit(visitor); - } - } - - ShaderAst ShaderAstUnserializer::Unserialize() + StatementPtr ShaderAstUnserializer::Unserialize() { UInt32 magicNumber; UInt32 version; @@ -553,122 +348,13 @@ namespace Nz if (version > s_currentVersion) throw std::runtime_error("unsupported version"); - UInt32 shaderStage; - m_stream >> shaderStage; + StatementPtr node; - ShaderAst shader(static_cast(shaderStage)); + Node(node); + if (!node) + throw std::runtime_error("functions can only have statements"); - // Conditions - UInt32 conditionCount; - m_stream >> conditionCount; - for (UInt32 i = 0; i < conditionCount; ++i) - { - std::string conditionName; - Value(conditionName); - - shader.AddCondition(std::move(conditionName)); - } - - // Structs - UInt32 structCount; - m_stream >> structCount; - for (UInt32 i = 0; i < structCount; ++i) - { - std::string structName; - std::vector members; - - Value(structName); - Container(members); - - for (auto& member : members) - { - Value(member.name); - Type(member.type); - } - - shader.AddStruct(std::move(structName), std::move(members)); - } - - // Inputs - UInt32 inputCount; - m_stream >> inputCount; - for (UInt32 i = 0; i < inputCount; ++i) - { - std::string inputName; - ShaderExpressionType inputType; - std::optional location; - - Value(inputName); - Type(inputType); - OptVal(location); - - shader.AddInput(std::move(inputName), std::move(inputType), location); - } - - // Outputs - UInt32 outputCount; - m_stream >> outputCount; - for (UInt32 i = 0; i < outputCount; ++i) - { - std::string outputName; - ShaderExpressionType outputType; - std::optional location; - - Value(outputName); - Type(outputType); - OptVal(location); - - shader.AddOutput(std::move(outputName), std::move(outputType), location); - } - - // Uniforms - UInt32 uniformCount; - m_stream >> uniformCount; - for (UInt32 i = 0; i < uniformCount; ++i) - { - std::string name; - ShaderExpressionType type; - std::optional binding; - std::optional memLayout; - - Value(name); - Type(type); - OptVal(binding); - OptEnum(memLayout); - - shader.AddUniform(std::move(name), std::move(type), std::move(binding), std::move(memLayout)); - } - - // Functions - UInt32 funcCount; - m_stream >> funcCount; - for (UInt32 i = 0; i < funcCount; ++i) - { - std::string name; - ShaderExpressionType retType; - std::vector parameters; - - Value(name); - Type(retType); - - Container(parameters); - for (auto& param : parameters) - { - Value(param.name); - Type(param.type); - } - - ShaderNodes::NodePtr node; - Node(node); - if (!node || !node->IsStatement()) - throw std::runtime_error("functions can only have statements"); - - ShaderNodes::StatementPtr statement = std::static_pointer_cast(node); - - shader.AddFunction(std::move(name), std::move(statement), std::move(parameters), std::move(retType)); - } - - return shader; + return node; } bool ShaderAstUnserializer::IsWriting() const @@ -676,41 +362,50 @@ namespace Nz return false; } - void ShaderAstUnserializer::Node(ShaderNodes::NodePtr& node) + void ShaderAstUnserializer::Node(ExpressionPtr& node) { Int32 nodeTypeInt; m_stream >> nodeTypeInt; - if (nodeTypeInt < static_cast(ShaderNodes::NodeType::None) || nodeTypeInt > static_cast(ShaderNodes::NodeType::Max)) + if (nodeTypeInt < static_cast(NodeType::None) || nodeTypeInt > static_cast(NodeType::Max)) throw std::runtime_error("invalid node type"); - ShaderNodes::NodeType nodeType = static_cast(nodeTypeInt); - -#define HandleType(Type) case ShaderNodes::NodeType:: Type : node = std::make_shared(); break + NodeType nodeType = static_cast(nodeTypeInt); switch (nodeType) { - case ShaderNodes::NodeType::None: break; + case NodeType::None: break; - HandleType(AccessMember); - HandleType(AssignOp); - HandleType(BinaryOp); - HandleType(Branch); - HandleType(Cast); - HandleType(Constant); - HandleType(ConditionalExpression); - HandleType(ConditionalStatement); - HandleType(DeclareVariable); - HandleType(Discard); - HandleType(ExpressionStatement); - HandleType(Identifier); - HandleType(IntrinsicCall); - HandleType(NoOp); - HandleType(ReturnStatement); - HandleType(Sample2D); - HandleType(SwizzleOp); - HandleType(StatementBlock); +#define NAZARA_SHADERAST_EXPRESSION(Node) case NodeType:: Node : node = std::make_unique(); break; +#include + + default: throw std::runtime_error("unexpected node type"); + } + + if (node) + { + ShaderSerializerVisitor visitor(*this); + node->Visit(visitor); + } + } + + void ShaderAstUnserializer::Node(StatementPtr& node) + { + Int32 nodeTypeInt; + m_stream >> nodeTypeInt; + + if (nodeTypeInt < static_cast(NodeType::None) || nodeTypeInt > static_cast(NodeType::Max)) + throw std::runtime_error("invalid node type"); + + NodeType nodeType = static_cast(nodeTypeInt); + switch (nodeType) + { + case NodeType::None: break; + +#define NAZARA_SHADERAST_STATEMENT(Node) case NodeType:: Node : node = std::make_unique(); break; +#include + + default: throw std::runtime_error("unexpected node type"); } -#undef HandleType if (node) { @@ -728,7 +423,7 @@ namespace Nz { case 0: //< Primitive { - ShaderNodes::BasicType exprType; + BasicType exprType; Enum(exprType); type = exprType; @@ -819,36 +514,8 @@ namespace Nz m_stream >> val; } - void ShaderAstUnserializer::Variable(ShaderNodes::VariablePtr& var) - { - Int32 nodeTypeInt; - m_stream >> nodeTypeInt; - ShaderNodes::VariableType nodeType = static_cast(nodeTypeInt); - -#define HandleType(Type) case ShaderNodes::VariableType:: Type : var = std::make_shared(); break - switch (nodeType) - { - case ShaderNodes::VariableType::None: break; - - HandleType(BuiltinVariable); - HandleType(InputVariable); - HandleType(LocalVariable); - HandleType(ParameterVariable); - HandleType(OutputVariable); - HandleType(UniformVariable); - } -#undef HandleType - - if (var) - { - ShaderSerializerVisitor visitor(*this); - var->Visit(visitor); - } - } - - - ByteArray SerializeShader(const ShaderAst& shader) + ByteArray SerializeShader(StatementPtr& shader) { ByteArray byteArray; ByteStream stream(&byteArray, OpenModeFlags(OpenMode_WriteOnly)); @@ -859,7 +526,7 @@ namespace Nz return byteArray; } - ShaderAst UnserializeShader(ByteStream& stream) + StatementPtr UnserializeShader(ByteStream& stream) { ShaderAstUnserializer unserializer(stream); return unserializer.Unserialize(); diff --git a/src/Nazara/Shader/ShaderVarVisitor.cpp b/src/Nazara/Shader/ShaderAstStatementVisitor.cpp similarity index 51% rename from src/Nazara/Shader/ShaderVarVisitor.cpp rename to src/Nazara/Shader/ShaderAstStatementVisitor.cpp index 108d5c69a..6ee90504e 100644 --- a/src/Nazara/Shader/ShaderVarVisitor.cpp +++ b/src/Nazara/Shader/ShaderAstStatementVisitor.cpp @@ -2,15 +2,10 @@ // This file is part of the "Nazara Engine - Shader generator" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include -namespace Nz +namespace Nz::ShaderAst { - ShaderVarVisitor::~ShaderVarVisitor() = default; - - void ShaderVarVisitor::Visit(const ShaderNodes::VariablePtr& node) - { - node->Visit(*this); - } + AstStatementVisitor::~AstStatementVisitor() = default; } diff --git a/src/Nazara/Shader/ShaderAstStatementVisitorExcept.cpp b/src/Nazara/Shader/ShaderAstStatementVisitorExcept.cpp new file mode 100644 index 000000000..ef4204ce6 --- /dev/null +++ b/src/Nazara/Shader/ShaderAstStatementVisitorExcept.cpp @@ -0,0 +1,15 @@ +// 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 +#include + +namespace Nz::ShaderAst +{ +#define NAZARA_SHADERAST_STATEMENT(Node) void StatementVisitorExcept::Visit(ShaderAst::Node& /*node*/) \ + { \ + throw std::runtime_error("unexpected " #Node " node"); \ + } +#include +} diff --git a/src/Nazara/Shader/ShaderAstUtils.cpp b/src/Nazara/Shader/ShaderAstUtils.cpp index d13571ded..c26d38ae5 100644 --- a/src/Nazara/Shader/ShaderAstUtils.cpp +++ b/src/Nazara/Shader/ShaderAstUtils.cpp @@ -5,69 +5,65 @@ #include #include -namespace Nz +namespace Nz::ShaderAst { - ShaderNodes::ExpressionCategory ShaderAstValueCategory::GetExpressionCategory(const ShaderNodes::ExpressionPtr& expression) + ExpressionCategory ShaderAstValueCategory::GetExpressionCategory(Expression& expression) { - Visit(expression); + expression.Visit(*this); return m_expressionCategory; } - void ShaderAstValueCategory::Visit(ShaderNodes::AccessMember& node) + void ShaderAstValueCategory::Visit(AccessMemberExpression& node) { - Visit(node.structExpr); + node.structExpr->Visit(*this); } - void ShaderAstValueCategory::Visit(ShaderNodes::AssignOp& node) + void ShaderAstValueCategory::Visit(AssignExpression& /*node*/) { - m_expressionCategory = ShaderNodes::ExpressionCategory::RValue; + m_expressionCategory = ExpressionCategory::RValue; } - void ShaderAstValueCategory::Visit(ShaderNodes::BinaryOp& node) + void ShaderAstValueCategory::Visit(BinaryExpression& /*node*/) { - m_expressionCategory = ShaderNodes::ExpressionCategory::RValue; + m_expressionCategory = ExpressionCategory::RValue; } - void ShaderAstValueCategory::Visit(ShaderNodes::Cast& node) + void ShaderAstValueCategory::Visit(CastExpression& /*node*/) { - m_expressionCategory = ShaderNodes::ExpressionCategory::RValue; + m_expressionCategory = ExpressionCategory::RValue; } - void ShaderAstValueCategory::Visit(ShaderNodes::ConditionalExpression& node) + void ShaderAstValueCategory::Visit(ConditionalExpression& node) { - Visit(node.truePath); - ShaderNodes::ExpressionCategory trueExprCategory = m_expressionCategory; - Visit(node.falsePath); - ShaderNodes::ExpressionCategory falseExprCategory = m_expressionCategory; + node.truePath->Visit(*this); + ExpressionCategory trueExprCategory = m_expressionCategory; - if (trueExprCategory == ShaderNodes::ExpressionCategory::RValue || falseExprCategory == ShaderNodes::ExpressionCategory::RValue) - m_expressionCategory = ShaderNodes::ExpressionCategory::RValue; + node.falsePath->Visit(*this); + ExpressionCategory falseExprCategory = m_expressionCategory; + + if (trueExprCategory == ExpressionCategory::RValue || falseExprCategory == ExpressionCategory::RValue) + m_expressionCategory = ExpressionCategory::RValue; else - m_expressionCategory = ShaderNodes::ExpressionCategory::LValue; + m_expressionCategory = ExpressionCategory::LValue; } - void ShaderAstValueCategory::Visit(ShaderNodes::Constant& node) + void ShaderAstValueCategory::Visit(ConstantExpression& /*node*/) { - m_expressionCategory = ShaderNodes::ExpressionCategory::RValue; + m_expressionCategory = ExpressionCategory::RValue; } - void ShaderAstValueCategory::Visit(ShaderNodes::Identifier& node) + void ShaderAstValueCategory::Visit(IdentifierExpression& /*node*/) { - m_expressionCategory = ShaderNodes::ExpressionCategory::LValue; + m_expressionCategory = ExpressionCategory::LValue; } - void ShaderAstValueCategory::Visit(ShaderNodes::IntrinsicCall& node) + void ShaderAstValueCategory::Visit(IntrinsicExpression& /*node*/) { - m_expressionCategory = ShaderNodes::ExpressionCategory::RValue; + m_expressionCategory = ExpressionCategory::RValue; } - void ShaderAstValueCategory::Visit(ShaderNodes::Sample2D& node) + void ShaderAstValueCategory::Visit(SwizzleExpression& node) { - m_expressionCategory = ShaderNodes::ExpressionCategory::RValue; - } - - void ShaderAstValueCategory::Visit(ShaderNodes::SwizzleOp& node) - { - Visit(node.expression); + node.expression->Visit(*this); } } diff --git a/src/Nazara/Shader/ShaderAstValidator.cpp b/src/Nazara/Shader/ShaderAstValidator.cpp index f081d7481..0e5d8f52f 100644 --- a/src/Nazara/Shader/ShaderAstValidator.cpp +++ b/src/Nazara/Shader/ShaderAstValidator.cpp @@ -4,48 +4,40 @@ #include #include -#include #include -#include +#include #include #include -namespace Nz +namespace Nz::ShaderAst { struct AstError { std::string errMsg; }; - struct ShaderAstValidator::Context + struct AstValidator::Context { - struct Local - { - std::string name; - ShaderExpressionType type; - }; - - const ShaderAst::Function* currentFunction; - std::vector declaredLocals; - std::vector blockLocalIndex; + //const ShaderAst::Function* currentFunction; + std::optional activeScopeId; + AstCache* cache; }; - bool ShaderAstValidator::Validate(std::string* error) + bool AstValidator::Validate(StatementPtr& node, std::string* error, AstCache* cache) { try { - for (std::size_t i = 0; i < m_shader.GetFunctionCount(); ++i) - { - const auto& func = m_shader.GetFunction(i); + AstCache dummy; - Context currentContext; - currentContext.currentFunction = &func; + Context currentContext; + currentContext.cache = (cache) ? cache : &dummy; - m_context = ¤tContext; - CallOnExit resetContext([&] { m_context = nullptr; }); + m_context = ¤tContext; + CallOnExit resetContext([&] { m_context = nullptr; }); - func.statement->Visit(*this); - } + EnterScope(); + node->Visit(*this); + ExitScope(); return true; } @@ -58,148 +50,183 @@ namespace Nz } } - const ShaderNodes::ExpressionPtr& ShaderAstValidator::MandatoryExpr(const ShaderNodes::ExpressionPtr& node) - { - MandatoryNode(node); - - return node; - } - - const ShaderNodes::NodePtr& ShaderAstValidator::MandatoryNode(const ShaderNodes::NodePtr& node) + Expression& AstValidator::MandatoryExpr(ExpressionPtr& node) { if (!node) - throw AstError{ "Invalid node" }; + throw AstError{ "Invalid expression" }; - return node; + return *node; } - void ShaderAstValidator::TypeMustMatch(const ShaderNodes::ExpressionPtr& left, const ShaderNodes::ExpressionPtr& right) + Statement& AstValidator::MandatoryStatement(StatementPtr& node) { - return TypeMustMatch(left->GetExpressionType(), right->GetExpressionType()); + if (!node) + throw AstError{ "Invalid statement" }; + + return *node; } - void ShaderAstValidator::TypeMustMatch(const ShaderExpressionType& left, const ShaderExpressionType& right) + void AstValidator::TypeMustMatch(ExpressionPtr& left, ExpressionPtr& right) + { + return TypeMustMatch(GetExpressionType(*left, m_context->cache), GetExpressionType(*right, m_context->cache)); + } + + void AstValidator::TypeMustMatch(const ShaderExpressionType& left, const ShaderExpressionType& right) { if (left != right) throw AstError{ "Left expression type must match right expression type" }; } - const ShaderAst::StructMember& ShaderAstValidator::CheckField(const std::string& structName, std::size_t* memberIndex, std::size_t remainingMembers) + ShaderExpressionType AstValidator::CheckField(const std::string& structName, const std::string* memberIdentifier, std::size_t remainingMembers) { - const auto& structs = m_shader.GetStructs(); - auto it = std::find_if(structs.begin(), structs.end(), [&](const auto& s) { return s.name == structName; }); - if (it == structs.end()) - throw AstError{ "invalid structure" }; + const AstCache::Identifier* identifier = m_context->cache->FindIdentifier(*m_context->activeScopeId, structName); + if (!identifier) + throw AstError{ "unknown identifier " + structName }; - const ShaderAst::Struct& s = *it; - if (*memberIndex >= s.members.size()) - throw AstError{ "member index out of bounds" }; + if (std::holds_alternative(identifier->value)) + throw AstError{ "identifier is not a struct" }; - const auto& member = s.members[*memberIndex]; + const StructDescription& s = std::get(identifier->value); + + auto memberIt = std::find_if(s.members.begin(), s.members.begin(), [&](const auto& field) { return field.name == memberIdentifier[0]; }); + if (memberIt == s.members.end()) + throw AstError{ "unknown field " + memberIdentifier[0]}; + + const auto& member = *memberIt; if (remainingMembers > 1) - { - if (!IsStructType(member.type)) - throw AstError{ "member type does not match node type" }; - - return CheckField(std::get(member.type), memberIndex + 1, remainingMembers - 1); - } + return CheckField(std::get(member.type), memberIdentifier + 1, remainingMembers - 1); else - return member; + return member.type; } - void ShaderAstValidator::Visit(ShaderNodes::AccessMember& node) + AstCache::Scope& AstValidator::EnterScope() { - const ShaderExpressionType& exprType = MandatoryExpr(node.structExpr)->GetExpressionType(); + std::size_t newScopeId = m_context->cache->scopes.size(); + + std::optional previousScope = m_context->activeScopeId; + + auto& newScope = m_context->cache->scopes.emplace_back(); + newScope.parentScopeIndex = previousScope; + + m_context->activeScopeId = newScopeId; + return m_context->cache->scopes[newScopeId]; + } + + void AstValidator::ExitScope() + { + assert(m_context->activeScopeId); + auto& previousScope = m_context->cache->scopes[*m_context->activeScopeId]; + m_context->activeScopeId = previousScope.parentScopeIndex; + } + + void AstValidator::RegisterExpressionType(Expression& node, ShaderExpressionType expressionType) + { + m_context->cache->nodeExpressionType[&node] = std::move(expressionType); + } + + void AstValidator::RegisterScope(Node& node) + { + if (m_context->activeScopeId) + m_context->cache->scopeIdByNode[&node] = *m_context->activeScopeId; + } + + void AstValidator::Visit(AccessMemberExpression& node) + { + RegisterScope(node); + + const ShaderExpressionType& exprType = GetExpressionType(MandatoryExpr(node.structExpr), m_context->cache); if (!IsStructType(exprType)) throw AstError{ "expression is not a structure" }; const std::string& structName = std::get(exprType); - const auto& member = CheckField(structName, node.memberIndices.data(), node.memberIndices.size()); - if (member.type != node.exprType) - throw AstError{ "member type does not match node type" }; + RegisterExpressionType(node, CheckField(structName, node.memberIdentifiers.data(), node.memberIdentifiers.size())); } - void ShaderAstValidator::Visit(ShaderNodes::AssignOp& node) + void AstValidator::Visit(AssignExpression& node) { - MandatoryNode(node.left); - MandatoryNode(node.right); + RegisterScope(node); + + MandatoryExpr(node.left); + MandatoryExpr(node.right); TypeMustMatch(node.left, node.right); - if (GetExpressionCategory(node.left) != ShaderNodes::ExpressionCategory::LValue) + if (GetExpressionCategory(*node.left) != ExpressionCategory::LValue) throw AstError { "Assignation is only possible with a l-value" }; - ShaderAstRecursiveVisitor::Visit(node); + AstRecursiveVisitor::Visit(node); } - void ShaderAstValidator::Visit(ShaderNodes::BinaryOp& node) + void AstValidator::Visit(BinaryExpression& node) { - MandatoryNode(node.left); - MandatoryNode(node.right); + RegisterScope(node); - const ShaderExpressionType& leftExprType = MandatoryExpr(node.left)->GetExpressionType(); + // Register expression type + AstRecursiveVisitor::Visit(node); + + const ShaderExpressionType& leftExprType = GetExpressionType(MandatoryExpr(node.left), m_context->cache); if (!IsBasicType(leftExprType)) throw AstError{ "left expression type does not support binary operation" }; - const ShaderExpressionType& rightExprType = MandatoryExpr(node.right)->GetExpressionType(); + const ShaderExpressionType& rightExprType = GetExpressionType(MandatoryExpr(node.right), m_context->cache); if (!IsBasicType(rightExprType)) throw AstError{ "right expression type does not support binary operation" }; - ShaderNodes::BasicType leftType = std::get(leftExprType); - ShaderNodes::BasicType rightType = std::get(rightExprType); + BasicType leftType = std::get(leftExprType); + BasicType rightType = std::get(rightExprType); switch (node.op) { - case ShaderNodes::BinaryType::CompGe: - case ShaderNodes::BinaryType::CompGt: - case ShaderNodes::BinaryType::CompLe: - case ShaderNodes::BinaryType::CompLt: - if (leftType == ShaderNodes::BasicType::Boolean) + case BinaryType::CompGe: + case BinaryType::CompGt: + case BinaryType::CompLe: + case BinaryType::CompLt: + if (leftType == BasicType::Boolean) throw AstError{ "this operation is not supported for booleans" }; [[fallthrough]]; - case ShaderNodes::BinaryType::Add: - case ShaderNodes::BinaryType::CompEq: - case ShaderNodes::BinaryType::CompNe: - case ShaderNodes::BinaryType::Subtract: + case BinaryType::Add: + case BinaryType::CompEq: + case BinaryType::CompNe: + case BinaryType::Subtract: TypeMustMatch(node.left, node.right); break; - case ShaderNodes::BinaryType::Multiply: - case ShaderNodes::BinaryType::Divide: + case BinaryType::Multiply: + case BinaryType::Divide: { switch (leftType) { - case ShaderNodes::BasicType::Float1: - case ShaderNodes::BasicType::Int1: + case BasicType::Float1: + case BasicType::Int1: { - if (ShaderNodes::Node::GetComponentType(rightType) != leftType) + if (GetComponentType(rightType) != leftType) throw AstError{ "Left expression type is not compatible with right expression type" }; break; } - case ShaderNodes::BasicType::Float2: - case ShaderNodes::BasicType::Float3: - case ShaderNodes::BasicType::Float4: - case ShaderNodes::BasicType::Int2: - case ShaderNodes::BasicType::Int3: - case ShaderNodes::BasicType::Int4: + case BasicType::Float2: + case BasicType::Float3: + case BasicType::Float4: + case BasicType::Int2: + case BasicType::Int3: + case BasicType::Int4: { - if (leftType != rightType && rightType != ShaderNodes::Node::GetComponentType(leftType)) + if (leftType != rightType && rightType != GetComponentType(leftType)) throw AstError{ "Left expression type is not compatible with right expression type" }; break; } - case ShaderNodes::BasicType::Mat4x4: + case BasicType::Mat4x4: { switch (rightType) { - case ShaderNodes::BasicType::Float1: - case ShaderNodes::BasicType::Float4: - case ShaderNodes::BasicType::Mat4x4: + case BasicType::Float1: + case BasicType::Float4: + case BasicType::Mat4x4: break; default: @@ -211,120 +238,86 @@ namespace Nz default: TypeMustMatch(node.left, node.right); + break; } } } - - ShaderAstRecursiveVisitor::Visit(node); } - void ShaderAstValidator::Visit(ShaderNodes::Branch& node) + void AstValidator::Visit(CastExpression& node) { - for (const auto& condStatement : node.condStatements) - { - const ShaderExpressionType& condType = MandatoryExpr(condStatement.condition)->GetExpressionType(); - if (!IsBasicType(condType) || std::get(condType) != ShaderNodes::BasicType::Boolean) - throw AstError{ "if expression must resolve to boolean type" }; + RegisterScope(node); - MandatoryNode(condStatement.statement); - } - - ShaderAstRecursiveVisitor::Visit(node); - } - - void ShaderAstValidator::Visit(ShaderNodes::Cast& node) - { unsigned int componentCount = 0; - unsigned int requiredComponents = node.GetComponentCount(node.exprType); - for (const auto& exprPtr : node.expressions) + unsigned int requiredComponents = GetComponentCount(node.targetType); + for (auto& exprPtr : node.expressions) { if (!exprPtr) break; - const ShaderExpressionType& exprType = exprPtr->GetExpressionType(); + ShaderExpressionType exprType = GetExpressionType(*exprPtr, m_context->cache); if (!IsBasicType(exprType)) throw AstError{ "incompatible type" }; - componentCount += node.GetComponentCount(std::get(exprType)); + componentCount += GetComponentCount(std::get(exprType)); } if (componentCount != requiredComponents) throw AstError{ "component count doesn't match required component count" }; - ShaderAstRecursiveVisitor::Visit(node); + AstRecursiveVisitor::Visit(node); } - void ShaderAstValidator::Visit(ShaderNodes::ConditionalExpression& node) + void AstValidator::Visit(ConditionalExpression& node) { - MandatoryNode(node.truePath); - MandatoryNode(node.falsePath); + MandatoryExpr(node.truePath); + MandatoryExpr(node.falsePath); - if (m_shader.FindConditionByName(node.conditionName) == ShaderAst::InvalidCondition) - throw AstError{ "condition not found" }; + RegisterScope(node); + + AstRecursiveVisitor::Visit(node); + //if (m_shader.FindConditionByName(node.conditionName) == ShaderAst::InvalidCondition) + // throw AstError{ "condition not found" }; } - void ShaderAstValidator::Visit(ShaderNodes::ConditionalStatement& node) + void AstValidator::Visit(ConstantExpression& node) { - MandatoryNode(node.statement); - - if (m_shader.FindConditionByName(node.conditionName) == ShaderAst::InvalidCondition) - throw AstError{ "condition not found" }; + RegisterScope(node); } - void ShaderAstValidator::Visit(ShaderNodes::Constant& /*node*/) - { - } - - void ShaderAstValidator::Visit(ShaderNodes::DeclareVariable& node) + void AstValidator::Visit(IdentifierExpression& node) { assert(m_context); - if (node.variable->GetType() != ShaderNodes::VariableType::LocalVariable) - throw AstError{ "Only local variables can be declared in a statement" }; + if (!m_context->activeScopeId) + throw AstError{ "no scope" }; - const auto& localVar = static_cast(*node.variable); + RegisterScope(node); - auto& local = m_context->declaredLocals.emplace_back(); - local.name = localVar.name; - local.type = localVar.type; - - ShaderAstRecursiveVisitor::Visit(node); + const AstCache::Identifier* identifier = m_context->cache->FindIdentifier(*m_context->activeScopeId, node.identifier); + if (!identifier) + throw AstError{ "Unknown variable " + node.identifier }; } - - void ShaderAstValidator::Visit(ShaderNodes::ExpressionStatement& node) + + void AstValidator::Visit(IntrinsicExpression& node) { - MandatoryNode(node.expression); + RegisterScope(node); - ShaderAstRecursiveVisitor::Visit(node); - } - - void ShaderAstValidator::Visit(ShaderNodes::Identifier& node) - { - assert(m_context); - - if (!node.var) - throw AstError{ "Invalid variable" }; - - Visit(node.var); - } - - void ShaderAstValidator::Visit(ShaderNodes::IntrinsicCall& node) - { switch (node.intrinsic) { - case ShaderNodes::IntrinsicType::CrossProduct: - case ShaderNodes::IntrinsicType::DotProduct: + case IntrinsicType::CrossProduct: + case IntrinsicType::DotProduct: { if (node.parameters.size() != 2) throw AstError { "Expected 2 parameters" }; for (auto& param : node.parameters) - MandatoryNode(param); + MandatoryExpr(param); - ShaderExpressionType type = node.parameters.front()->GetExpressionType(); + ShaderExpressionType type = GetExpressionType(*node.parameters.front(), m_context->cache); for (std::size_t i = 1; i < node.parameters.size(); ++i) { - if (type != node.parameters[i]->GetExpressionType()) + if (type != GetExpressionType(MandatoryExpr(node.parameters[i])), m_context->cache) throw AstError{ "All type must match" }; } @@ -334,180 +327,176 @@ namespace Nz switch (node.intrinsic) { - case ShaderNodes::IntrinsicType::CrossProduct: + case IntrinsicType::CrossProduct: { - if (node.parameters[0]->GetExpressionType() != ShaderExpressionType{ ShaderNodes::BasicType::Float3 }) + if (GetExpressionType(*node.parameters[0]) != ShaderExpressionType{ BasicType::Float3 }, m_context->cache) throw AstError{ "CrossProduct only works with Float3 expressions" }; break; } - case ShaderNodes::IntrinsicType::DotProduct: + case IntrinsicType::DotProduct: break; } - ShaderAstRecursiveVisitor::Visit(node); + AstRecursiveVisitor::Visit(node); } - void ShaderAstValidator::Visit(ShaderNodes::ReturnStatement& node) + void AstValidator::Visit(SwizzleExpression& node) { - if (m_context->currentFunction->returnType != ShaderExpressionType(ShaderNodes::BasicType::Void)) - { - if (MandatoryExpr(node.returnExpr)->GetExpressionType() != m_context->currentFunction->returnType) - throw AstError{ "Return type doesn't match function return type" }; - } - else - { - if (node.returnExpr) - throw AstError{ "Unexpected expression for return (function doesn't return)" }; - } + RegisterScope(node); - ShaderAstRecursiveVisitor::Visit(node); - } - - void ShaderAstValidator::Visit(ShaderNodes::Sample2D& node) - { - if (MandatoryExpr(node.sampler)->GetExpressionType() != ShaderExpressionType{ ShaderNodes::BasicType::Sampler2D }) - throw AstError{ "Sampler must be a Sampler2D" }; - - if (MandatoryExpr(node.coordinates)->GetExpressionType() != ShaderExpressionType{ ShaderNodes::BasicType::Float2 }) - throw AstError{ "Coordinates must be a Float2" }; - - ShaderAstRecursiveVisitor::Visit(node); - } - - void ShaderAstValidator::Visit(ShaderNodes::StatementBlock& node) - { - assert(m_context); - - m_context->blockLocalIndex.push_back(m_context->declaredLocals.size()); - - for (const auto& statement : node.statements) - MandatoryNode(statement); - - assert(m_context->declaredLocals.size() >= m_context->blockLocalIndex.back()); - m_context->declaredLocals.resize(m_context->blockLocalIndex.back()); - m_context->blockLocalIndex.pop_back(); - - ShaderAstRecursiveVisitor::Visit(node); - } - - void ShaderAstValidator::Visit(ShaderNodes::SwizzleOp& node) - { if (node.componentCount > 4) throw AstError{ "Cannot swizzle more than four elements" }; - const ShaderExpressionType& exprType = MandatoryExpr(node.expression)->GetExpressionType(); + const ShaderExpressionType& exprType = GetExpressionType(MandatoryExpr(node.expression), m_context->cache); if (!IsBasicType(exprType)) throw AstError{ "Cannot swizzle this type" }; - switch (std::get(exprType)) + switch (std::get(exprType)) { - case ShaderNodes::BasicType::Float1: - case ShaderNodes::BasicType::Float2: - case ShaderNodes::BasicType::Float3: - case ShaderNodes::BasicType::Float4: - case ShaderNodes::BasicType::Int1: - case ShaderNodes::BasicType::Int2: - case ShaderNodes::BasicType::Int3: - case ShaderNodes::BasicType::Int4: + case BasicType::Float1: + case BasicType::Float2: + case BasicType::Float3: + case BasicType::Float4: + case BasicType::Int1: + case BasicType::Int2: + case BasicType::Int3: + case BasicType::Int4: break; default: throw AstError{ "Cannot swizzle this type" }; } - ShaderAstRecursiveVisitor::Visit(node); + AstRecursiveVisitor::Visit(node); } - void ShaderAstValidator::Visit(ShaderNodes::BuiltinVariable& var) + void AstValidator::Visit(BranchStatement& node) { - switch (var.entry) + RegisterScope(node); + + for (auto& condStatement : node.condStatements) { - case ShaderNodes::BuiltinEntry::VertexPosition: - if (!IsBasicType(var.type) || - std::get(var.type) != ShaderNodes::BasicType::Float4) - throw AstError{ "Builtin is not of the expected type" }; + const ShaderExpressionType& condType = GetExpressionType(MandatoryExpr(condStatement.condition), m_context->cache); + if (!IsBasicType(condType) || std::get(condType) != BasicType::Boolean) + throw AstError{ "if expression must resolve to boolean type" }; - break; - - default: - break; - } - } - - void ShaderAstValidator::Visit(ShaderNodes::InputVariable& var) - { - for (std::size_t i = 0; i < m_shader.GetInputCount(); ++i) - { - const auto& input = m_shader.GetInput(i); - if (input.name == var.name) - { - TypeMustMatch(input.type, var.type); - return; - } + MandatoryStatement(condStatement.statement); } - throw AstError{ "Input not found" }; + AstRecursiveVisitor::Visit(node); } - void ShaderAstValidator::Visit(ShaderNodes::LocalVariable& var) + void AstValidator::Visit(ConditionalStatement& node) { - const auto& vars = m_context->declaredLocals; + MandatoryStatement(node.statement); - auto it = std::find_if(vars.begin(), vars.end(), [&](const auto& v) { return v.name == var.name; }); - if (it == vars.end()) - throw AstError{ "Local variable not found in this block" }; + RegisterScope(node); - TypeMustMatch(it->type, var.type); + AstRecursiveVisitor::Visit(node); + //if (m_shader.FindConditionByName(node.conditionName) == ShaderAst::InvalidCondition) + // throw AstError{ "condition not found" }; } - void ShaderAstValidator::Visit(ShaderNodes::OutputVariable& var) + void AstValidator::Visit(DeclareFunctionStatement& node) { - for (std::size_t i = 0; i < m_shader.GetOutputCount(); ++i) + auto& scope = EnterScope(); + + RegisterScope(node); + + for (auto& parameter : node.parameters) { - const auto& input = m_shader.GetOutput(i); - if (input.name == var.name) - { - TypeMustMatch(input.type, var.type); - return; - } + auto& identifier = scope.identifiers.emplace_back(); + identifier = AstCache::Identifier{ parameter.name, AstCache::Variable { parameter.type } }; } - throw AstError{ "Output not found" }; + for (auto& statement : node.statements) + MandatoryStatement(statement).Visit(*this); + + ExitScope(); } - void ShaderAstValidator::Visit(ShaderNodes::ParameterVariable& var) + void AstValidator::Visit(DeclareStructStatement& node) { - assert(m_context->currentFunction); + assert(m_context); - const auto& parameters = m_context->currentFunction->parameters; + if (!m_context->activeScopeId) + throw AstError{ "cannot declare variable without scope" }; - auto it = std::find_if(parameters.begin(), parameters.end(), [&](const auto& parameter) { return parameter.name == var.name; }); - if (it == parameters.end()) - throw AstError{ "Parameter not found in function" }; + RegisterScope(node); - TypeMustMatch(it->type, var.type); + auto& scope = m_context->cache->scopes[*m_context->activeScopeId]; + + auto& identifier = scope.identifiers.emplace_back(); + identifier = AstCache::Identifier{ node.description.name, node.description }; + + AstRecursiveVisitor::Visit(node); } - void ShaderAstValidator::Visit(ShaderNodes::UniformVariable& var) + void AstValidator::Visit(DeclareVariableStatement& node) { - for (std::size_t i = 0; i < m_shader.GetUniformCount(); ++i) + assert(m_context); + + if (!m_context->activeScopeId) + throw AstError{ "cannot declare variable without scope" }; + + RegisterScope(node); + + auto& scope = m_context->cache->scopes[*m_context->activeScopeId]; + + auto& identifier = scope.identifiers.emplace_back(); + identifier = AstCache::Identifier{ node.varName, AstCache::Variable { node.varType } }; + + AstRecursiveVisitor::Visit(node); + } + + void AstValidator::Visit(ExpressionStatement& node) + { + RegisterScope(node); + + MandatoryExpr(node.expression); + + AstRecursiveVisitor::Visit(node); + } + + void AstValidator::Visit(MultiStatement& node) + { + assert(m_context); + + EnterScope(); + + RegisterScope(node); + + for (auto& statement : node.statements) + MandatoryStatement(statement); + + ExitScope(); + + AstRecursiveVisitor::Visit(node); + } + + void AstValidator::Visit(ReturnStatement& node) + { + RegisterScope(node); + + /*if (m_context->currentFunction->returnType != ShaderExpressionType(BasicType::Void)) { - const auto& uniform = m_shader.GetUniform(i); - if (uniform.name == var.name) - { - TypeMustMatch(uniform.type, var.type); - return; - } + if (GetExpressionType(MandatoryExpr(node.returnExpr)) != m_context->currentFunction->returnType) + throw AstError{ "Return type doesn't match function return type" }; } + else + { + if (node.returnExpr) + throw AstError{ "Unexpected expression for return (function doesn't return)" }; + }*/ - throw AstError{ "Uniform not found" }; + AstRecursiveVisitor::Visit(node); } - bool ValidateShader(const ShaderAst& shader, std::string* error) + bool ValidateAst(StatementPtr& node, std::string* error, AstCache* cache) { - ShaderAstValidator validator(shader); - return validator.Validate(error); + AstValidator validator; + return validator.Validate(node, error, cache); } } diff --git a/src/Nazara/Shader/ShaderAstVisitorExcept.cpp b/src/Nazara/Shader/ShaderAstVisitorExcept.cpp deleted file mode 100644 index b8f8c7d16..000000000 --- a/src/Nazara/Shader/ShaderAstVisitorExcept.cpp +++ /dev/null @@ -1,100 +0,0 @@ -// 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 -#include -#include - -namespace Nz -{ - void ShaderAstVisitorExcept::Visit(ShaderNodes::AccessMember& /*node*/) - { - throw std::runtime_error("unhandled AccessMember node"); - } - - void ShaderAstVisitorExcept::Visit(ShaderNodes::AssignOp& /*node*/) - { - throw std::runtime_error("unhandled AssignOp node"); - } - - void ShaderAstVisitorExcept::Visit(ShaderNodes::BinaryOp& /*node*/) - { - throw std::runtime_error("unhandled AccessMember node"); - } - - void ShaderAstVisitorExcept::Visit(ShaderNodes::Branch& /*node*/) - { - throw std::runtime_error("unhandled Branch node"); - } - - void ShaderAstVisitorExcept::Visit(ShaderNodes::Cast& /*node*/) - { - throw std::runtime_error("unhandled Cast node"); - } - - void ShaderAstVisitorExcept::Visit(ShaderNodes::ConditionalExpression& /*node*/) - { - throw std::runtime_error("unhandled ConditionalExpression node"); - } - - void ShaderAstVisitorExcept::Visit(ShaderNodes::ConditionalStatement& /*node*/) - { - throw std::runtime_error("unhandled ConditionalStatement node"); - } - - void ShaderAstVisitorExcept::Visit(ShaderNodes::Constant& /*node*/) - { - throw std::runtime_error("unhandled Constant node"); - } - - void ShaderAstVisitorExcept::Visit(ShaderNodes::DeclareVariable& /*node*/) - { - throw std::runtime_error("unhandled DeclareVariable node"); - } - - void ShaderAstVisitorExcept::Visit(ShaderNodes::Discard& /*node*/) - { - throw std::runtime_error("unhandled Discard node"); - } - - void ShaderAstVisitorExcept::Visit(ShaderNodes::ExpressionStatement& /*node*/) - { - throw std::runtime_error("unhandled ExpressionStatement node"); - } - - void ShaderAstVisitorExcept::Visit(ShaderNodes::Identifier& /*node*/) - { - throw std::runtime_error("unhandled Identifier node"); - } - - void ShaderAstVisitorExcept::Visit(ShaderNodes::IntrinsicCall& /*node*/) - { - throw std::runtime_error("unhandled IntrinsicCall node"); - } - - void ShaderAstVisitorExcept::Visit(ShaderNodes::NoOp& node) - { - throw std::runtime_error("unhandled NoOp node"); - } - - void ShaderAstVisitorExcept::Visit(ShaderNodes::ReturnStatement& node) - { - throw std::runtime_error("unhandled ReturnStatement node"); - } - - void ShaderAstVisitorExcept::Visit(ShaderNodes::Sample2D& /*node*/) - { - throw std::runtime_error("unhandled Sample2D node"); - } - - void ShaderAstVisitorExcept::Visit(ShaderNodes::StatementBlock& /*node*/) - { - throw std::runtime_error("unhandled StatementBlock node"); - } - - void ShaderAstVisitorExcept::Visit(ShaderNodes::SwizzleOp& /*node*/) - { - throw std::runtime_error("unhandled SwizzleOp node"); - } -} diff --git a/src/Nazara/Shader/ShaderLangLexer.cpp b/src/Nazara/Shader/ShaderLangLexer.cpp index 8782a54fb..13b21b0c4 100644 --- a/src/Nazara/Shader/ShaderLangLexer.cpp +++ b/src/Nazara/Shader/ShaderLangLexer.cpp @@ -42,6 +42,7 @@ namespace Nz::ShaderLang std::unordered_map reservedKeywords = { { "false", TokenType::BoolFalse }, { "fn", TokenType::FunctionDeclaration }, + { "let", TokenType::Let }, { "return", TokenType::Return }, { "true", TokenType::BoolTrue } }; @@ -143,7 +144,7 @@ namespace Nz::ShaderLang while (next != -1); } else - tokenType == TokenType::Divide; + tokenType = TokenType::Divide; break; } @@ -191,9 +192,11 @@ namespace Nz::ShaderLang std::string valueStr(str.substr(start, currentPos - start + 1)); + const char* ptr = valueStr.c_str(); + char* end; - double value = std::strtod(valueStr.c_str(), &end); - if (end != &str[currentPos + 1]) + double value = std::strtod(ptr, &end); + if (end != &ptr[valueStr.size()]) throw BadNumber{}; token.data = value; @@ -218,6 +221,7 @@ namespace Nz::ShaderLang break; } + case '=': tokenType = TokenType::Assign; break; case '+': tokenType = TokenType::Plus; break; case '*': tokenType = TokenType::Multiply; break; case ':': tokenType = TokenType::Colon; break; diff --git a/src/Nazara/Shader/ShaderLangParser.cpp b/src/Nazara/Shader/ShaderLangParser.cpp index cea55ee2e..050d88f6d 100644 --- a/src/Nazara/Shader/ShaderLangParser.cpp +++ b/src/Nazara/Shader/ShaderLangParser.cpp @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include #include @@ -10,36 +11,38 @@ namespace Nz::ShaderLang { namespace { - std::unordered_map identifierToBasicType = { - { "bool", ShaderNodes::BasicType::Boolean }, + std::unordered_map identifierToBasicType = { + { "bool", ShaderAst::BasicType::Boolean }, - { "i32", ShaderNodes::BasicType::Int1 }, - { "vec2i32", ShaderNodes::BasicType::Int2 }, - { "vec3i32", ShaderNodes::BasicType::Int3 }, - { "vec4i32", ShaderNodes::BasicType::Int4 }, + { "i32", ShaderAst::BasicType::Int1 }, + { "vec2i32", ShaderAst::BasicType::Int2 }, + { "vec3i32", ShaderAst::BasicType::Int3 }, + { "vec4i32", ShaderAst::BasicType::Int4 }, - { "f32", ShaderNodes::BasicType::Float1 }, - { "vec2f32", ShaderNodes::BasicType::Float2 }, - { "vec3f32", ShaderNodes::BasicType::Float3 }, - { "vec4f32", ShaderNodes::BasicType::Float4 }, + { "f32", ShaderAst::BasicType::Float1 }, + { "vec2f32", ShaderAst::BasicType::Float2 }, + { "vec3f32", ShaderAst::BasicType::Float3 }, + { "vec4f32", ShaderAst::BasicType::Float4 }, - { "mat4x4f32", ShaderNodes::BasicType::Mat4x4 }, - { "sampler2D", ShaderNodes::BasicType::Sampler2D }, - { "void", ShaderNodes::BasicType::Void }, + { "mat4x4f32", ShaderAst::BasicType::Mat4x4 }, + { "sampler2D", ShaderAst::BasicType::Sampler2D }, + { "void", ShaderAst::BasicType::Void }, - { "u32", ShaderNodes::BasicType::UInt1 }, - { "vec2u32", ShaderNodes::BasicType::UInt3 }, - { "vec3u32", ShaderNodes::BasicType::UInt3 }, - { "vec4u32", ShaderNodes::BasicType::UInt4 }, + { "u32", ShaderAst::BasicType::UInt1 }, + { "vec2u32", ShaderAst::BasicType::UInt3 }, + { "vec3u32", ShaderAst::BasicType::UInt3 }, + { "vec4u32", ShaderAst::BasicType::UInt4 }, }; } - ShaderAst Parser::Parse(const std::vector& tokens) + ShaderAst::StatementPtr Parser::Parse(const std::vector& tokens) { Context context; context.tokenCount = tokens.size(); context.tokens = tokens.data(); + context.root = std::make_unique(); + m_context = &context; m_context->tokenIndex = -1; @@ -51,7 +54,7 @@ namespace Nz::ShaderLang switch (nextToken.type) { case TokenType::FunctionDeclaration: - ParseFunctionDeclaration(); + context.root->statements.push_back(ParseFunctionDeclaration()); break; case TokenType::EndOfStream: @@ -63,7 +66,7 @@ namespace Nz::ShaderLang } } - return std::move(context.result); + return std::move(context.root); } const Token& Parser::Advance() @@ -92,12 +95,12 @@ namespace Nz::ShaderLang return m_context->tokens[m_context->tokenIndex + 1]; } - ShaderNodes::StatementPtr Parser::ParseFunctionBody() + std::vector Parser::ParseFunctionBody() { return ParseStatementList(); } - void Parser::ParseFunctionDeclaration() + ShaderAst::StatementPtr Parser::ParseFunctionDeclaration() { ExpectNext(TokenType::FunctionDeclaration); @@ -105,7 +108,7 @@ namespace Nz::ShaderLang ExpectNext(TokenType::OpenParenthesis); - std::vector parameters; + std::vector parameters; bool firstParameter = true; for (;;) @@ -126,7 +129,7 @@ namespace Nz::ShaderLang ExpectNext(TokenType::ClosingParenthesis); - ShaderExpressionType returnType = ShaderNodes::BasicType::Void; + ShaderAst::ShaderExpressionType returnType = ShaderAst::BasicType::Void; if (PeekNext().type == TokenType::FunctionReturn) { Advance(); //< Consume -> @@ -136,42 +139,46 @@ namespace Nz::ShaderLang ExpectNext(TokenType::OpenCurlyBracket); - ShaderNodes::StatementPtr functionBody = ParseFunctionBody(); + std::vector functionBody = ParseFunctionBody(); ExpectNext(TokenType::ClosingCurlyBracket); - m_context->result.AddFunction(functionName, functionBody, std::move(parameters), returnType); + return ShaderBuilder::DeclareFunction(std::move(functionName), std::move(parameters), std::move(functionBody), std::move(returnType)); } - ShaderAst::FunctionParameter Parser::ParseFunctionParameter() + ShaderAst::DeclareFunctionStatement::Parameter Parser::ParseFunctionParameter() { std::string parameterName = ParseIdentifierAsName(); ExpectNext(TokenType::Colon); - ShaderExpressionType parameterType = ParseIdentifierAsType(); + ShaderAst::ShaderExpressionType parameterType = ParseIdentifierAsType(); return { parameterName, parameterType }; } - ShaderNodes::StatementPtr Parser::ParseReturnStatement() + ShaderAst::StatementPtr Parser::ParseReturnStatement() { ExpectNext(TokenType::Return); - ShaderNodes::ExpressionPtr expr; + ShaderAst::ExpressionPtr expr; if (PeekNext().type != TokenType::Semicolon) expr = ParseExpression(); - return ShaderNodes::ReturnStatement::Build(std::move(expr)); + return ShaderBuilder::Return(std::move(expr)); } - ShaderNodes::StatementPtr Parser::ParseStatement() + ShaderAst::StatementPtr Parser::ParseStatement() { const Token& token = PeekNext(); - ShaderNodes::StatementPtr statement; + ShaderAst::StatementPtr statement; switch (token.type) { + case TokenType::Let: + statement = ParseVariableDeclaration(); + break; + case TokenType::Return: statement = ParseReturnStatement(); break; @@ -185,18 +192,38 @@ namespace Nz::ShaderLang return statement; } - ShaderNodes::StatementPtr Parser::ParseStatementList() + std::vector Parser::ParseStatementList() { - std::vector statements; + std::vector statements; while (PeekNext().type != TokenType::ClosingCurlyBracket) { statements.push_back(ParseStatement()); } - return ShaderNodes::StatementBlock::Build(std::move(statements)); + return statements; } - ShaderNodes::ExpressionPtr Parser::ParseBinOpRhs(int exprPrecedence, ShaderNodes::ExpressionPtr lhs) + ShaderAst::StatementPtr Parser::ParseVariableDeclaration() + { + ExpectNext(TokenType::Let); + + std::string variableName = ParseIdentifierAsName(); + + ExpectNext(TokenType::Colon); + + ShaderAst::ShaderExpressionType variableType = ParseIdentifierAsType(); + + ShaderAst::ExpressionPtr expression; + if (PeekNext().type == TokenType::Assign) + { + Advance(); + expression = ParseExpression(); + } + + return ShaderBuilder::DeclareVariable(std::move(variableName), std::move(variableType), std::move(expression)); + } + + ShaderAst::ExpressionPtr Parser::ParseBinOpRhs(int exprPrecedence, ShaderAst::ExpressionPtr lhs) { for (;;) { @@ -207,7 +234,7 @@ namespace Nz::ShaderLang return lhs; Advance(); - ShaderNodes::ExpressionPtr rhs = ParsePrimaryExpression(); + ShaderAst::ExpressionPtr rhs = ParsePrimaryExpression(); const Token& nextOp = PeekNext(); @@ -215,57 +242,58 @@ namespace Nz::ShaderLang if (tokenPrecedence < nextTokenPrecedence) rhs = ParseBinOpRhs(tokenPrecedence + 1, std::move(rhs)); - ShaderNodes::BinaryType binaryType; + ShaderAst::BinaryType binaryType; { switch (currentOp.type) { - case TokenType::Plus: binaryType = ShaderNodes::BinaryType::Add; break; - case TokenType::Minus: binaryType = ShaderNodes::BinaryType::Subtract; break; - case TokenType::Multiply: binaryType = ShaderNodes::BinaryType::Multiply; break; - case TokenType::Divide: binaryType = ShaderNodes::BinaryType::Divide; break; + case TokenType::Plus: binaryType = ShaderAst::BinaryType::Add; break; + case TokenType::Minus: binaryType = ShaderAst::BinaryType::Subtract; break; + case TokenType::Multiply: binaryType = ShaderAst::BinaryType::Multiply; break; + case TokenType::Divide: binaryType = ShaderAst::BinaryType::Divide; break; default: throw UnexpectedToken{}; } } - lhs = ShaderNodes::BinaryOp::Build(binaryType, std::move(lhs), std::move(rhs)); + lhs = ShaderBuilder::Binary(binaryType, std::move(lhs), std::move(rhs)); } } - ShaderNodes::ExpressionPtr Parser::ParseExpression() + ShaderAst::ExpressionPtr Parser::ParseExpression() { return ParseBinOpRhs(0, ParsePrimaryExpression()); } - ShaderNodes::ExpressionPtr Parser::ParseIdentifier() + ShaderAst::ExpressionPtr Parser::ParseIdentifier() { const Token& identifier = ExpectNext(TokenType::Identifier); - return ShaderNodes::Identifier::Build(ShaderNodes::ParameterVariable::Build(std::get(identifier.data), ShaderNodes::BasicType::Float3)); + return ShaderBuilder::Identifier(std::get(identifier.data)); } - ShaderNodes::ExpressionPtr Parser::ParseIntegerExpression() + ShaderAst::ExpressionPtr Parser::ParseIntegerExpression() { const Token& integer = ExpectNext(TokenType::IntegerValue); - return ShaderNodes::Constant::Build(static_cast(std::get(integer.data))); + return ShaderBuilder::Constant(static_cast(std::get(integer.data))); } - ShaderNodes::ExpressionPtr Parser::ParseParenthesisExpression() + ShaderAst::ExpressionPtr Parser::ParseParenthesisExpression() { ExpectNext(TokenType::OpenParenthesis); - ShaderNodes::ExpressionPtr expression = ParseExpression(); + ShaderAst::ExpressionPtr expression = ParseExpression(); ExpectNext(TokenType::ClosingParenthesis); return expression; } - ShaderNodes::ExpressionPtr Parser::ParsePrimaryExpression() + ShaderAst::ExpressionPtr Parser::ParsePrimaryExpression() { const Token& token = PeekNext(); switch (token.type) { - case TokenType::BoolFalse: return ShaderNodes::Constant::Build(false); - case TokenType::BoolTrue: return ShaderNodes::Constant::Build(true); + case TokenType::BoolFalse: return ShaderBuilder::Constant(false); + case TokenType::BoolTrue: return ShaderBuilder::Constant(true); + case TokenType::FloatingPointValue: return ShaderBuilder::Constant(float(std::get(Advance().data))); //< FIXME case TokenType::Identifier: return ParseIdentifier(); case TokenType::IntegerValue: return ParseIntegerExpression(); case TokenType::OpenParenthesis: return ParseParenthesisExpression(); @@ -286,7 +314,7 @@ namespace Nz::ShaderLang return identifier; } - ShaderExpressionType Parser::ParseIdentifierAsType() + ShaderAst::ShaderExpressionType Parser::ParseIdentifierAsType() { const Token& identifier = ExpectNext(TokenType::Identifier); diff --git a/src/Nazara/Shader/ShaderNodes.cpp b/src/Nazara/Shader/ShaderNodes.cpp index 97a21506b..d4510fcfc 100644 --- a/src/Nazara/Shader/ShaderNodes.cpp +++ b/src/Nazara/Shader/ShaderNodes.cpp @@ -4,265 +4,29 @@ #include #include -#include -#include -#include +#include +#include #include -namespace Nz::ShaderNodes +namespace Nz::ShaderAst { Node::~Node() = default; - void ExpressionStatement::Visit(ShaderAstVisitor& visitor) - { - visitor.Visit(*this); +#define NAZARA_SHADERAST_NODE(Node) NodeType Node::GetType() const \ + { \ + return NodeType:: Node; \ + } +#include + +#define NAZARA_SHADERAST_EXPRESSION(Node) void Node::Visit(AstExpressionVisitor& visitor) \ + {\ + visitor.Visit(*this); \ } - - void ConditionalStatement::Visit(ShaderAstVisitor& visitor) - { - visitor.Visit(*this); +#define NAZARA_SHADERAST_STATEMENT(Node) void Node::Visit(AstStatementVisitor& visitor) \ + {\ + visitor.Visit(*this); \ } - - void StatementBlock::Visit(ShaderAstVisitor& visitor) - { - visitor.Visit(*this); - } - - - void DeclareVariable::Visit(ShaderAstVisitor& visitor) - { - visitor.Visit(*this); - } - - - void Discard::Visit(ShaderAstVisitor& visitor) - { - visitor.Visit(*this); - } - - - ShaderExpressionType Identifier::GetExpressionType() const - { - assert(var); - return var->type; - } - - void Identifier::Visit(ShaderAstVisitor& visitor) - { - visitor.Visit(*this); - } - - ShaderExpressionType AccessMember::GetExpressionType() const - { - return exprType; - } - - void AccessMember::Visit(ShaderAstVisitor& visitor) - { - visitor.Visit(*this); - } - - void NoOp::Visit(ShaderAstVisitor& visitor) - { - visitor.Visit(*this); - } - - void ReturnStatement::Visit(ShaderAstVisitor& visitor) - { - visitor.Visit(*this); - } - - ShaderExpressionType AssignOp::GetExpressionType() const - { - return left->GetExpressionType(); - } - - void AssignOp::Visit(ShaderAstVisitor& visitor) - { - visitor.Visit(*this); - } - - - ShaderExpressionType BinaryOp::GetExpressionType() const - { - std::optional exprType; - - switch (op) - { - case BinaryType::Add: - case BinaryType::Subtract: - exprType = left->GetExpressionType(); - break; - - case BinaryType::Divide: - case BinaryType::Multiply: - { - const ShaderExpressionType& leftExprType = left->GetExpressionType(); - assert(IsBasicType(leftExprType)); - - const ShaderExpressionType& rightExprType = right->GetExpressionType(); - assert(IsBasicType(rightExprType)); - - switch (std::get(leftExprType)) - { - case BasicType::Boolean: - case BasicType::Float2: - case BasicType::Float3: - case BasicType::Float4: - case BasicType::Int2: - case BasicType::Int3: - case BasicType::Int4: - case BasicType::UInt2: - case BasicType::UInt3: - case BasicType::UInt4: - exprType = leftExprType; - break; - - case BasicType::Float1: - case BasicType::Int1: - case BasicType::Mat4x4: - case BasicType::UInt1: - exprType = rightExprType; - break; - - case BasicType::Sampler2D: - case BasicType::Void: - break; - } - - break; - } - - case BinaryType::CompEq: - case BinaryType::CompGe: - case BinaryType::CompGt: - case BinaryType::CompLe: - case BinaryType::CompLt: - case BinaryType::CompNe: - exprType = BasicType::Boolean; - break; - } - - NazaraAssert(exprType.has_value(), "Unhandled builtin"); - - return *exprType; - } - - void BinaryOp::Visit(ShaderAstVisitor& visitor) - { - visitor.Visit(*this); - } - - - void Branch::Visit(ShaderAstVisitor& visitor) - { - visitor.Visit(*this); - } - - - ShaderExpressionType Constant::GetExpressionType() const - { - return std::visit([&](auto&& arg) - { - using T = std::decay_t; - - if constexpr (std::is_same_v) - return ShaderNodes::BasicType::Boolean; - else if constexpr (std::is_same_v) - return ShaderNodes::BasicType::Float1; - else if constexpr (std::is_same_v) - return ShaderNodes::BasicType::Int1; - else if constexpr (std::is_same_v) - return ShaderNodes::BasicType::Int1; - else if constexpr (std::is_same_v) - return ShaderNodes::BasicType::Float2; - else if constexpr (std::is_same_v) - return ShaderNodes::BasicType::Float3; - else if constexpr (std::is_same_v) - return ShaderNodes::BasicType::Float4; - else if constexpr (std::is_same_v) - return ShaderNodes::BasicType::Int2; - else if constexpr (std::is_same_v) - return ShaderNodes::BasicType::Int3; - else if constexpr (std::is_same_v) - return ShaderNodes::BasicType::Int4; - else - static_assert(AlwaysFalse::value, "non-exhaustive visitor"); - }, value); - } - - void Constant::Visit(ShaderAstVisitor& visitor) - { - visitor.Visit(*this); - } - - ShaderExpressionType Cast::GetExpressionType() const - { - return exprType; - } - - void Cast::Visit(ShaderAstVisitor& visitor) - { - visitor.Visit(*this); - } - - - ShaderExpressionType ConditionalExpression::GetExpressionType() const - { - assert(truePath->GetExpressionType() == falsePath->GetExpressionType()); - return truePath->GetExpressionType(); - } - - void ConditionalExpression::Visit(ShaderAstVisitor& visitor) - { - visitor.Visit(*this); - } - - - ShaderExpressionType SwizzleOp::GetExpressionType() const - { - const ShaderExpressionType& exprType = expression->GetExpressionType(); - assert(IsBasicType(exprType)); - - return static_cast(UnderlyingCast(GetComponentType(std::get(exprType))) + componentCount - 1); - } - - void SwizzleOp::Visit(ShaderAstVisitor& visitor) - { - visitor.Visit(*this); - } - - - ShaderExpressionType Sample2D::GetExpressionType() const - { - return BasicType::Float4; - } - - void Sample2D::Visit(ShaderAstVisitor& visitor) - { - visitor.Visit(*this); - } - - - ShaderExpressionType IntrinsicCall::GetExpressionType() const - { - switch (intrinsic) - { - case IntrinsicType::CrossProduct: - return parameters.front()->GetExpressionType(); - - case IntrinsicType::DotProduct: - return BasicType::Float1; - } - - NazaraAssert(false, "Unhandled builtin"); - return BasicType::Void; - } - - void IntrinsicCall::Visit(ShaderAstVisitor& visitor) - { - visitor.Visit(*this); - } +#include } diff --git a/src/Nazara/Shader/ShaderVarVisitorExcept.cpp b/src/Nazara/Shader/ShaderVarVisitorExcept.cpp deleted file mode 100644 index 3629f86d1..000000000 --- a/src/Nazara/Shader/ShaderVarVisitorExcept.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// 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 -#include -#include - -namespace Nz -{ - void ShaderVarVisitorExcept::Visit(ShaderNodes::BuiltinVariable& /*var*/) - { - throw std::runtime_error("unhandled BuiltinVariable"); - } - - void ShaderVarVisitorExcept::Visit(ShaderNodes::InputVariable& /*var*/) - { - throw std::runtime_error("unhandled InputVariable"); - } - - void ShaderVarVisitorExcept::Visit(ShaderNodes::LocalVariable& /*var*/) - { - throw std::runtime_error("unhandled LocalVariable"); - } - - void ShaderVarVisitorExcept::Visit(ShaderNodes::OutputVariable& /*var*/) - { - throw std::runtime_error("unhandled OutputVariable"); - } - - void ShaderVarVisitorExcept::Visit(ShaderNodes::ParameterVariable& /*var*/) - { - throw std::runtime_error("unhandled ParameterVariable"); - } - - void ShaderVarVisitorExcept::Visit(ShaderNodes::UniformVariable& /*var*/) - { - throw std::runtime_error("unhandled UniformVariable"); - } -} diff --git a/src/Nazara/Shader/ShaderVariables.cpp b/src/Nazara/Shader/ShaderVariables.cpp deleted file mode 100644 index ebe520a0c..000000000 --- a/src/Nazara/Shader/ShaderVariables.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// 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 -#include -#include - -namespace Nz::ShaderNodes -{ - ShaderNodes::Variable::~Variable() = default; - - VariableType BuiltinVariable::GetType() const - { - return VariableType::BuiltinVariable; - } - - void BuiltinVariable::Visit(ShaderVarVisitor& visitor) - { - visitor.Visit(*this); - } - - - VariableType InputVariable::GetType() const - { - return VariableType::InputVariable; - } - - void InputVariable::Visit(ShaderVarVisitor& visitor) - { - visitor.Visit(*this); - } - - - VariableType LocalVariable::GetType() const - { - return VariableType::LocalVariable; - } - - void LocalVariable::Visit(ShaderVarVisitor& visitor) - { - visitor.Visit(*this); - } - - - VariableType OutputVariable::GetType() const - { - return VariableType::OutputVariable; - } - - void OutputVariable::Visit(ShaderVarVisitor& visitor) - { - visitor.Visit(*this); - } - - - VariableType ParameterVariable::GetType() const - { - return VariableType::ParameterVariable; - } - - void ParameterVariable::Visit(ShaderVarVisitor& visitor) - { - visitor.Visit(*this); - } - - - VariableType UniformVariable::GetType() const - { - return VariableType::UniformVariable; - } - - void UniformVariable::Visit(ShaderVarVisitor& visitor) - { - visitor.Visit(*this); - } -} diff --git a/src/Nazara/Shader/SpirvAstVisitor.cpp b/src/Nazara/Shader/SpirvAstVisitor.cpp index 688648e70..96a099a21 100644 --- a/src/Nazara/Shader/SpirvAstVisitor.cpp +++ b/src/Nazara/Shader/SpirvAstVisitor.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -12,21 +13,21 @@ namespace Nz { - UInt32 SpirvAstVisitor::EvaluateExpression(const ShaderNodes::ExpressionPtr& expr) + UInt32 SpirvAstVisitor::EvaluateExpression(ShaderAst::ExpressionPtr& expr) { - Visit(expr); + expr->Visit(*this); assert(m_resultIds.size() == 1); return PopResultId(); } - void SpirvAstVisitor::Visit(ShaderNodes::AccessMember& node) + void SpirvAstVisitor::Visit(ShaderAst::AccessMemberExpression& node) { SpirvExpressionLoad accessMemberVisitor(m_writer, *m_currentBlock); PushResultId(accessMemberVisitor.Evaluate(node)); } - void SpirvAstVisitor::Visit(ShaderNodes::AssignOp& node) + void SpirvAstVisitor::Visit(ShaderAst::AssignExpression& node) { UInt32 resultId = EvaluateExpression(node.right); @@ -36,20 +37,20 @@ namespace Nz PushResultId(resultId); } - void SpirvAstVisitor::Visit(ShaderNodes::BinaryOp& node) + void SpirvAstVisitor::Visit(ShaderAst::BinaryExpression& node) { - ShaderExpressionType resultExprType = node.GetExpressionType(); + ShaderAst::ShaderExpressionType resultExprType = ShaderAst::GetExpressionType(node); assert(IsBasicType(resultExprType)); - const ShaderExpressionType& leftExprType = node.left->GetExpressionType(); + ShaderAst::ShaderExpressionType leftExprType = ShaderAst::GetExpressionType(*node.left); assert(IsBasicType(leftExprType)); - const ShaderExpressionType& rightExprType = node.right->GetExpressionType(); + ShaderAst::ShaderExpressionType rightExprType = ShaderAst::GetExpressionType(*node.right); assert(IsBasicType(rightExprType)); - ShaderNodes::BasicType resultType = std::get(resultExprType); - ShaderNodes::BasicType leftType = std::get(leftExprType); - ShaderNodes::BasicType rightType = std::get(rightExprType); + ShaderAst::BasicType resultType = std::get(resultExprType); + ShaderAst::BasicType leftType = std::get(leftExprType); + ShaderAst::BasicType rightType = std::get(rightExprType); UInt32 leftOperand = EvaluateExpression(node.left); @@ -62,308 +63,308 @@ namespace Nz { switch (node.op) { - case ShaderNodes::BinaryType::Add: + case ShaderAst::BinaryType::Add: { switch (leftType) { - case ShaderNodes::BasicType::Float1: - case ShaderNodes::BasicType::Float2: - case ShaderNodes::BasicType::Float3: - case ShaderNodes::BasicType::Float4: - case ShaderNodes::BasicType::Mat4x4: + case ShaderAst::BasicType::Float1: + case ShaderAst::BasicType::Float2: + case ShaderAst::BasicType::Float3: + case ShaderAst::BasicType::Float4: + case ShaderAst::BasicType::Mat4x4: return SpirvOp::OpFAdd; - case ShaderNodes::BasicType::Int1: - case ShaderNodes::BasicType::Int2: - case ShaderNodes::BasicType::Int3: - case ShaderNodes::BasicType::Int4: - case ShaderNodes::BasicType::UInt1: - case ShaderNodes::BasicType::UInt2: - case ShaderNodes::BasicType::UInt3: - case ShaderNodes::BasicType::UInt4: + case ShaderAst::BasicType::Int1: + case ShaderAst::BasicType::Int2: + case ShaderAst::BasicType::Int3: + case ShaderAst::BasicType::Int4: + case ShaderAst::BasicType::UInt1: + case ShaderAst::BasicType::UInt2: + case ShaderAst::BasicType::UInt3: + case ShaderAst::BasicType::UInt4: return SpirvOp::OpIAdd; - case ShaderNodes::BasicType::Boolean: - case ShaderNodes::BasicType::Sampler2D: - case ShaderNodes::BasicType::Void: + case ShaderAst::BasicType::Boolean: + case ShaderAst::BasicType::Sampler2D: + case ShaderAst::BasicType::Void: break; } break; } - case ShaderNodes::BinaryType::Subtract: + case ShaderAst::BinaryType::Subtract: { switch (leftType) { - case ShaderNodes::BasicType::Float1: - case ShaderNodes::BasicType::Float2: - case ShaderNodes::BasicType::Float3: - case ShaderNodes::BasicType::Float4: - case ShaderNodes::BasicType::Mat4x4: + case ShaderAst::BasicType::Float1: + case ShaderAst::BasicType::Float2: + case ShaderAst::BasicType::Float3: + case ShaderAst::BasicType::Float4: + case ShaderAst::BasicType::Mat4x4: return SpirvOp::OpFSub; - case ShaderNodes::BasicType::Int1: - case ShaderNodes::BasicType::Int2: - case ShaderNodes::BasicType::Int3: - case ShaderNodes::BasicType::Int4: - case ShaderNodes::BasicType::UInt1: - case ShaderNodes::BasicType::UInt2: - case ShaderNodes::BasicType::UInt3: - case ShaderNodes::BasicType::UInt4: + case ShaderAst::BasicType::Int1: + case ShaderAst::BasicType::Int2: + case ShaderAst::BasicType::Int3: + case ShaderAst::BasicType::Int4: + case ShaderAst::BasicType::UInt1: + case ShaderAst::BasicType::UInt2: + case ShaderAst::BasicType::UInt3: + case ShaderAst::BasicType::UInt4: return SpirvOp::OpISub; - case ShaderNodes::BasicType::Boolean: - case ShaderNodes::BasicType::Sampler2D: - case ShaderNodes::BasicType::Void: + case ShaderAst::BasicType::Boolean: + case ShaderAst::BasicType::Sampler2D: + case ShaderAst::BasicType::Void: break; } break; } - case ShaderNodes::BinaryType::Divide: + case ShaderAst::BinaryType::Divide: { switch (leftType) { - case ShaderNodes::BasicType::Float1: - case ShaderNodes::BasicType::Float2: - case ShaderNodes::BasicType::Float3: - case ShaderNodes::BasicType::Float4: - case ShaderNodes::BasicType::Mat4x4: + case ShaderAst::BasicType::Float1: + case ShaderAst::BasicType::Float2: + case ShaderAst::BasicType::Float3: + case ShaderAst::BasicType::Float4: + case ShaderAst::BasicType::Mat4x4: return SpirvOp::OpFDiv; - case ShaderNodes::BasicType::Int1: - case ShaderNodes::BasicType::Int2: - case ShaderNodes::BasicType::Int3: - case ShaderNodes::BasicType::Int4: + case ShaderAst::BasicType::Int1: + case ShaderAst::BasicType::Int2: + case ShaderAst::BasicType::Int3: + case ShaderAst::BasicType::Int4: return SpirvOp::OpSDiv; - case ShaderNodes::BasicType::UInt1: - case ShaderNodes::BasicType::UInt2: - case ShaderNodes::BasicType::UInt3: - case ShaderNodes::BasicType::UInt4: + case ShaderAst::BasicType::UInt1: + case ShaderAst::BasicType::UInt2: + case ShaderAst::BasicType::UInt3: + case ShaderAst::BasicType::UInt4: return SpirvOp::OpUDiv; - case ShaderNodes::BasicType::Boolean: - case ShaderNodes::BasicType::Sampler2D: - case ShaderNodes::BasicType::Void: + case ShaderAst::BasicType::Boolean: + case ShaderAst::BasicType::Sampler2D: + case ShaderAst::BasicType::Void: break; } break; } - case ShaderNodes::BinaryType::CompEq: + case ShaderAst::BinaryType::CompEq: { switch (leftType) { - case ShaderNodes::BasicType::Boolean: + case ShaderAst::BasicType::Boolean: return SpirvOp::OpLogicalEqual; - case ShaderNodes::BasicType::Float1: - case ShaderNodes::BasicType::Float2: - case ShaderNodes::BasicType::Float3: - case ShaderNodes::BasicType::Float4: - case ShaderNodes::BasicType::Mat4x4: + case ShaderAst::BasicType::Float1: + case ShaderAst::BasicType::Float2: + case ShaderAst::BasicType::Float3: + case ShaderAst::BasicType::Float4: + case ShaderAst::BasicType::Mat4x4: return SpirvOp::OpFOrdEqual; - case ShaderNodes::BasicType::Int1: - case ShaderNodes::BasicType::Int2: - case ShaderNodes::BasicType::Int3: - case ShaderNodes::BasicType::Int4: - case ShaderNodes::BasicType::UInt1: - case ShaderNodes::BasicType::UInt2: - case ShaderNodes::BasicType::UInt3: - case ShaderNodes::BasicType::UInt4: + case ShaderAst::BasicType::Int1: + case ShaderAst::BasicType::Int2: + case ShaderAst::BasicType::Int3: + case ShaderAst::BasicType::Int4: + case ShaderAst::BasicType::UInt1: + case ShaderAst::BasicType::UInt2: + case ShaderAst::BasicType::UInt3: + case ShaderAst::BasicType::UInt4: return SpirvOp::OpIEqual; - case ShaderNodes::BasicType::Sampler2D: - case ShaderNodes::BasicType::Void: + case ShaderAst::BasicType::Sampler2D: + case ShaderAst::BasicType::Void: break; } break; } - case ShaderNodes::BinaryType::CompGe: + case ShaderAst::BinaryType::CompGe: { switch (leftType) { - case ShaderNodes::BasicType::Float1: - case ShaderNodes::BasicType::Float2: - case ShaderNodes::BasicType::Float3: - case ShaderNodes::BasicType::Float4: - case ShaderNodes::BasicType::Mat4x4: + case ShaderAst::BasicType::Float1: + case ShaderAst::BasicType::Float2: + case ShaderAst::BasicType::Float3: + case ShaderAst::BasicType::Float4: + case ShaderAst::BasicType::Mat4x4: return SpirvOp::OpFOrdGreaterThan; - case ShaderNodes::BasicType::Int1: - case ShaderNodes::BasicType::Int2: - case ShaderNodes::BasicType::Int3: - case ShaderNodes::BasicType::Int4: + case ShaderAst::BasicType::Int1: + case ShaderAst::BasicType::Int2: + case ShaderAst::BasicType::Int3: + case ShaderAst::BasicType::Int4: return SpirvOp::OpSGreaterThan; - case ShaderNodes::BasicType::UInt1: - case ShaderNodes::BasicType::UInt2: - case ShaderNodes::BasicType::UInt3: - case ShaderNodes::BasicType::UInt4: + case ShaderAst::BasicType::UInt1: + case ShaderAst::BasicType::UInt2: + case ShaderAst::BasicType::UInt3: + case ShaderAst::BasicType::UInt4: return SpirvOp::OpUGreaterThan; - case ShaderNodes::BasicType::Boolean: - case ShaderNodes::BasicType::Sampler2D: - case ShaderNodes::BasicType::Void: + case ShaderAst::BasicType::Boolean: + case ShaderAst::BasicType::Sampler2D: + case ShaderAst::BasicType::Void: break; } break; } - case ShaderNodes::BinaryType::CompGt: + case ShaderAst::BinaryType::CompGt: { switch (leftType) { - case ShaderNodes::BasicType::Float1: - case ShaderNodes::BasicType::Float2: - case ShaderNodes::BasicType::Float3: - case ShaderNodes::BasicType::Float4: - case ShaderNodes::BasicType::Mat4x4: + case ShaderAst::BasicType::Float1: + case ShaderAst::BasicType::Float2: + case ShaderAst::BasicType::Float3: + case ShaderAst::BasicType::Float4: + case ShaderAst::BasicType::Mat4x4: return SpirvOp::OpFOrdGreaterThanEqual; - case ShaderNodes::BasicType::Int1: - case ShaderNodes::BasicType::Int2: - case ShaderNodes::BasicType::Int3: - case ShaderNodes::BasicType::Int4: + case ShaderAst::BasicType::Int1: + case ShaderAst::BasicType::Int2: + case ShaderAst::BasicType::Int3: + case ShaderAst::BasicType::Int4: return SpirvOp::OpSGreaterThanEqual; - case ShaderNodes::BasicType::UInt1: - case ShaderNodes::BasicType::UInt2: - case ShaderNodes::BasicType::UInt3: - case ShaderNodes::BasicType::UInt4: + case ShaderAst::BasicType::UInt1: + case ShaderAst::BasicType::UInt2: + case ShaderAst::BasicType::UInt3: + case ShaderAst::BasicType::UInt4: return SpirvOp::OpUGreaterThanEqual; - case ShaderNodes::BasicType::Boolean: - case ShaderNodes::BasicType::Sampler2D: - case ShaderNodes::BasicType::Void: + case ShaderAst::BasicType::Boolean: + case ShaderAst::BasicType::Sampler2D: + case ShaderAst::BasicType::Void: break; } break; } - case ShaderNodes::BinaryType::CompLe: + case ShaderAst::BinaryType::CompLe: { switch (leftType) { - case ShaderNodes::BasicType::Float1: - case ShaderNodes::BasicType::Float2: - case ShaderNodes::BasicType::Float3: - case ShaderNodes::BasicType::Float4: - case ShaderNodes::BasicType::Mat4x4: + case ShaderAst::BasicType::Float1: + case ShaderAst::BasicType::Float2: + case ShaderAst::BasicType::Float3: + case ShaderAst::BasicType::Float4: + case ShaderAst::BasicType::Mat4x4: return SpirvOp::OpFOrdLessThanEqual; - case ShaderNodes::BasicType::Int1: - case ShaderNodes::BasicType::Int2: - case ShaderNodes::BasicType::Int3: - case ShaderNodes::BasicType::Int4: + case ShaderAst::BasicType::Int1: + case ShaderAst::BasicType::Int2: + case ShaderAst::BasicType::Int3: + case ShaderAst::BasicType::Int4: return SpirvOp::OpSLessThanEqual; - case ShaderNodes::BasicType::UInt1: - case ShaderNodes::BasicType::UInt2: - case ShaderNodes::BasicType::UInt3: - case ShaderNodes::BasicType::UInt4: + case ShaderAst::BasicType::UInt1: + case ShaderAst::BasicType::UInt2: + case ShaderAst::BasicType::UInt3: + case ShaderAst::BasicType::UInt4: return SpirvOp::OpULessThanEqual; - case ShaderNodes::BasicType::Boolean: - case ShaderNodes::BasicType::Sampler2D: - case ShaderNodes::BasicType::Void: + case ShaderAst::BasicType::Boolean: + case ShaderAst::BasicType::Sampler2D: + case ShaderAst::BasicType::Void: break; } break; } - case ShaderNodes::BinaryType::CompLt: + case ShaderAst::BinaryType::CompLt: { switch (leftType) { - case ShaderNodes::BasicType::Float1: - case ShaderNodes::BasicType::Float2: - case ShaderNodes::BasicType::Float3: - case ShaderNodes::BasicType::Float4: - case ShaderNodes::BasicType::Mat4x4: + case ShaderAst::BasicType::Float1: + case ShaderAst::BasicType::Float2: + case ShaderAst::BasicType::Float3: + case ShaderAst::BasicType::Float4: + case ShaderAst::BasicType::Mat4x4: return SpirvOp::OpFOrdLessThan; - case ShaderNodes::BasicType::Int1: - case ShaderNodes::BasicType::Int2: - case ShaderNodes::BasicType::Int3: - case ShaderNodes::BasicType::Int4: + case ShaderAst::BasicType::Int1: + case ShaderAst::BasicType::Int2: + case ShaderAst::BasicType::Int3: + case ShaderAst::BasicType::Int4: return SpirvOp::OpSLessThan; - case ShaderNodes::BasicType::UInt1: - case ShaderNodes::BasicType::UInt2: - case ShaderNodes::BasicType::UInt3: - case ShaderNodes::BasicType::UInt4: + case ShaderAst::BasicType::UInt1: + case ShaderAst::BasicType::UInt2: + case ShaderAst::BasicType::UInt3: + case ShaderAst::BasicType::UInt4: return SpirvOp::OpULessThan; - case ShaderNodes::BasicType::Boolean: - case ShaderNodes::BasicType::Sampler2D: - case ShaderNodes::BasicType::Void: + case ShaderAst::BasicType::Boolean: + case ShaderAst::BasicType::Sampler2D: + case ShaderAst::BasicType::Void: break; } break; } - case ShaderNodes::BinaryType::CompNe: + case ShaderAst::BinaryType::CompNe: { switch (leftType) { - case ShaderNodes::BasicType::Boolean: + case ShaderAst::BasicType::Boolean: return SpirvOp::OpLogicalNotEqual; - case ShaderNodes::BasicType::Float1: - case ShaderNodes::BasicType::Float2: - case ShaderNodes::BasicType::Float3: - case ShaderNodes::BasicType::Float4: - case ShaderNodes::BasicType::Mat4x4: + case ShaderAst::BasicType::Float1: + case ShaderAst::BasicType::Float2: + case ShaderAst::BasicType::Float3: + case ShaderAst::BasicType::Float4: + case ShaderAst::BasicType::Mat4x4: return SpirvOp::OpFOrdNotEqual; - case ShaderNodes::BasicType::Int1: - case ShaderNodes::BasicType::Int2: - case ShaderNodes::BasicType::Int3: - case ShaderNodes::BasicType::Int4: - case ShaderNodes::BasicType::UInt1: - case ShaderNodes::BasicType::UInt2: - case ShaderNodes::BasicType::UInt3: - case ShaderNodes::BasicType::UInt4: + case ShaderAst::BasicType::Int1: + case ShaderAst::BasicType::Int2: + case ShaderAst::BasicType::Int3: + case ShaderAst::BasicType::Int4: + case ShaderAst::BasicType::UInt1: + case ShaderAst::BasicType::UInt2: + case ShaderAst::BasicType::UInt3: + case ShaderAst::BasicType::UInt4: return SpirvOp::OpINotEqual; - case ShaderNodes::BasicType::Sampler2D: - case ShaderNodes::BasicType::Void: + case ShaderAst::BasicType::Sampler2D: + case ShaderAst::BasicType::Void: break; } break; } - case ShaderNodes::BinaryType::Multiply: + case ShaderAst::BinaryType::Multiply: { switch (leftType) { - case ShaderNodes::BasicType::Float1: + case ShaderAst::BasicType::Float1: { switch (rightType) { - case ShaderNodes::BasicType::Float1: + case ShaderAst::BasicType::Float1: return SpirvOp::OpFMul; - case ShaderNodes::BasicType::Float2: - case ShaderNodes::BasicType::Float3: - case ShaderNodes::BasicType::Float4: + case ShaderAst::BasicType::Float2: + case ShaderAst::BasicType::Float3: + case ShaderAst::BasicType::Float4: swapOperands = true; return SpirvOp::OpVectorTimesScalar; - case ShaderNodes::BasicType::Mat4x4: + case ShaderAst::BasicType::Mat4x4: swapOperands = true; return SpirvOp::OpMatrixTimesScalar; @@ -374,21 +375,21 @@ namespace Nz break; } - case ShaderNodes::BasicType::Float2: - case ShaderNodes::BasicType::Float3: - case ShaderNodes::BasicType::Float4: + case ShaderAst::BasicType::Float2: + case ShaderAst::BasicType::Float3: + case ShaderAst::BasicType::Float4: { switch (rightType) { - case ShaderNodes::BasicType::Float1: + case ShaderAst::BasicType::Float1: return SpirvOp::OpVectorTimesScalar; - case ShaderNodes::BasicType::Float2: - case ShaderNodes::BasicType::Float3: - case ShaderNodes::BasicType::Float4: + case ShaderAst::BasicType::Float2: + case ShaderAst::BasicType::Float3: + case ShaderAst::BasicType::Float4: return SpirvOp::OpFMul; - case ShaderNodes::BasicType::Mat4x4: + case ShaderAst::BasicType::Mat4x4: return SpirvOp::OpVectorTimesMatrix; default: @@ -398,23 +399,23 @@ namespace Nz break; } - case ShaderNodes::BasicType::Int1: - case ShaderNodes::BasicType::Int2: - case ShaderNodes::BasicType::Int3: - case ShaderNodes::BasicType::Int4: - case ShaderNodes::BasicType::UInt1: - case ShaderNodes::BasicType::UInt2: - case ShaderNodes::BasicType::UInt3: - case ShaderNodes::BasicType::UInt4: + case ShaderAst::BasicType::Int1: + case ShaderAst::BasicType::Int2: + case ShaderAst::BasicType::Int3: + case ShaderAst::BasicType::Int4: + case ShaderAst::BasicType::UInt1: + case ShaderAst::BasicType::UInt2: + case ShaderAst::BasicType::UInt3: + case ShaderAst::BasicType::UInt4: return SpirvOp::OpIMul; - case ShaderNodes::BasicType::Mat4x4: + case ShaderAst::BasicType::Mat4x4: { switch (rightType) { - case ShaderNodes::BasicType::Float1: return SpirvOp::OpMatrixTimesScalar; - case ShaderNodes::BasicType::Float4: return SpirvOp::OpMatrixTimesVector; - case ShaderNodes::BasicType::Mat4x4: return SpirvOp::OpMatrixTimesMatrix; + case ShaderAst::BasicType::Float1: return SpirvOp::OpMatrixTimesScalar; + case ShaderAst::BasicType::Float4: return SpirvOp::OpMatrixTimesVector; + case ShaderAst::BasicType::Mat4x4: return SpirvOp::OpMatrixTimesMatrix; default: break; @@ -442,7 +443,7 @@ namespace Nz PushResultId(resultId); } - void SpirvAstVisitor::Visit(ShaderNodes::Branch& node) + void SpirvAstVisitor::Visit(ShaderAst::BranchStatement& node) { assert(!node.condStatements.empty()); auto& firstCond = node.condStatements.front(); @@ -450,7 +451,8 @@ namespace Nz UInt32 previousConditionId = EvaluateExpression(firstCond.condition); SpirvBlock previousContentBlock(m_writer); m_currentBlock = &previousContentBlock; - Visit(firstCond.statement); + + firstCond.statement->Visit(*this); SpirvBlock mergeBlock(m_writer); m_blocks.back().Append(SpirvOp::OpSelectionMerge, mergeBlock.GetLabelId(), SpirvSelectionControl::None); @@ -458,7 +460,7 @@ namespace Nz std::optional nextBlock; for (std::size_t statementIndex = 1; statementIndex < node.condStatements.size(); ++statementIndex) { - const auto& statement = node.condStatements[statementIndex]; + auto& statement = node.condStatements[statementIndex]; SpirvBlock contentBlock(m_writer); @@ -469,7 +471,8 @@ namespace Nz previousContentBlock = std::move(contentBlock); m_currentBlock = &previousContentBlock; - Visit(statement.statement); + + statement.statement->Visit(*this); } if (node.elseStatement) @@ -477,7 +480,7 @@ namespace Nz SpirvBlock elseBlock(m_writer); m_currentBlock = &elseBlock; - Visit(node.elseStatement); + node.elseStatement->Visit(*this); elseBlock.Append(SpirvOp::OpBranch, mergeBlock.GetLabelId()); //< FIXME: Shouldn't terminate twice @@ -496,16 +499,16 @@ namespace Nz m_currentBlock = &m_blocks.back(); } - void SpirvAstVisitor::Visit(ShaderNodes::Cast& node) + void SpirvAstVisitor::Visit(ShaderAst::CastExpression& node) { - const ShaderExpressionType& targetExprType = node.exprType; + const ShaderAst::ShaderExpressionType& targetExprType = node.targetType; assert(IsBasicType(targetExprType)); - ShaderNodes::BasicType targetType = std::get(targetExprType); + ShaderAst::BasicType targetType = std::get(targetExprType); StackVector exprResults = NazaraStackVector(UInt32, node.expressions.size()); - for (const auto& exprPtr : node.expressions) + for (auto& exprPtr : node.expressions) { if (!exprPtr) break; @@ -527,21 +530,21 @@ namespace Nz PushResultId(resultId); } - void SpirvAstVisitor::Visit(ShaderNodes::ConditionalExpression& node) + void SpirvAstVisitor::Visit(ShaderAst::ConditionalExpression& node) { if (m_writer.IsConditionEnabled(node.conditionName)) - Visit(node.truePath); + node.truePath->Visit(*this); else - Visit(node.falsePath); + node.falsePath->Visit(*this); } - void SpirvAstVisitor::Visit(ShaderNodes::ConditionalStatement& node) + void SpirvAstVisitor::Visit(ShaderAst::ConditionalStatement& node) { if (m_writer.IsConditionEnabled(node.conditionName)) - Visit(node.statement); + node.statement->Visit(*this); } - void SpirvAstVisitor::Visit(ShaderNodes::Constant& node) + void SpirvAstVisitor::Visit(ShaderAst::ConstantExpression& node) { std::visit([&] (const auto& value) { @@ -549,46 +552,42 @@ namespace Nz }, node.value); } - void SpirvAstVisitor::Visit(ShaderNodes::DeclareVariable& node) + void SpirvAstVisitor::Visit(ShaderAst::DeclareVariableStatement& node) { - if (node.expression) - { - assert(node.variable->GetType() == ShaderNodes::VariableType::LocalVariable); - - const auto& localVar = static_cast(*node.variable); - m_writer.WriteLocalVariable(localVar.name, EvaluateExpression(node.expression)); - } + if (node.initialExpression) + m_writer.WriteLocalVariable(node.varName, EvaluateExpression(node.initialExpression)); } - void SpirvAstVisitor::Visit(ShaderNodes::Discard& /*node*/) + void SpirvAstVisitor::Visit(ShaderAst::DiscardStatement& /*node*/) { m_currentBlock->Append(SpirvOp::OpKill); } - void SpirvAstVisitor::Visit(ShaderNodes::ExpressionStatement& node) + void SpirvAstVisitor::Visit(ShaderAst::ExpressionStatement& node) { - Visit(node.expression); + node.expression->Visit(*this); + PopResultId(); } - void SpirvAstVisitor::Visit(ShaderNodes::Identifier& node) + void SpirvAstVisitor::Visit(ShaderAst::IdentifierExpression& node) { SpirvExpressionLoad loadVisitor(m_writer, *m_currentBlock); PushResultId(loadVisitor.Evaluate(node)); } - void SpirvAstVisitor::Visit(ShaderNodes::IntrinsicCall& node) + void SpirvAstVisitor::Visit(ShaderAst::IntrinsicExpression& node) { switch (node.intrinsic) { - case ShaderNodes::IntrinsicType::DotProduct: + case ShaderAst::IntrinsicType::DotProduct: { - const ShaderExpressionType& vecExprType = node.parameters[0]->GetExpressionType(); + const ShaderAst::ShaderExpressionType& vecExprType = GetExpressionType(*node.parameters[0]); assert(IsBasicType(vecExprType)); - ShaderNodes::BasicType vecType = std::get(vecExprType); + ShaderAst::BasicType vecType = std::get(vecExprType); - UInt32 typeId = m_writer.GetTypeId(node.GetComponentType(vecType)); + UInt32 typeId = m_writer.GetTypeId(ShaderAst::GetComponentType(vecType)); UInt32 vec1 = EvaluateExpression(node.parameters[0]); UInt32 vec2 = EvaluateExpression(node.parameters[1]); @@ -600,18 +599,18 @@ namespace Nz break; } - case ShaderNodes::IntrinsicType::CrossProduct: + case ShaderAst::IntrinsicType::CrossProduct: default: throw std::runtime_error("not yet implemented"); } } - void SpirvAstVisitor::Visit(ShaderNodes::NoOp& /*node*/) + void SpirvAstVisitor::Visit(ShaderAst::NoOpStatement& /*node*/) { // nothing to do } - void SpirvAstVisitor::Visit(ShaderNodes::ReturnStatement& node) + void SpirvAstVisitor::Visit(ShaderAst::ReturnStatement& node) { if (node.returnExpr) m_currentBlock->Append(SpirvOp::OpReturnValue, EvaluateExpression(node.returnExpr)); @@ -619,30 +618,18 @@ namespace Nz m_currentBlock->Append(SpirvOp::OpReturn); } - void SpirvAstVisitor::Visit(ShaderNodes::Sample2D& node) - { - UInt32 typeId = m_writer.GetTypeId(ShaderNodes::BasicType::Float4); - - UInt32 samplerId = EvaluateExpression(node.sampler); - UInt32 coordinatesId = EvaluateExpression(node.coordinates); - UInt32 resultId = m_writer.AllocateResultId(); - - m_currentBlock->Append(SpirvOp::OpImageSampleImplicitLod, typeId, resultId, samplerId, coordinatesId); - PushResultId(resultId); - } - - void SpirvAstVisitor::Visit(ShaderNodes::StatementBlock& node) + void SpirvAstVisitor::Visit(ShaderAst::MultiStatement& node) { for (auto& statement : node.statements) - Visit(statement); + statement->Visit(*this); } - void SpirvAstVisitor::Visit(ShaderNodes::SwizzleOp& node) + void SpirvAstVisitor::Visit(ShaderAst::SwizzleExpression& node) { - const ShaderExpressionType& targetExprType = node.GetExpressionType(); + const ShaderAst::ShaderExpressionType& targetExprType = ShaderAst::GetExpressionType(node); assert(IsBasicType(targetExprType)); - ShaderNodes::BasicType targetType = std::get(targetExprType); + ShaderAst::BasicType targetType = std::get(targetExprType); UInt32 exprResultId = EvaluateExpression(node.expression); UInt32 resultId = m_writer.AllocateResultId(); @@ -666,7 +653,7 @@ namespace Nz // Extract a single component from the vector assert(node.componentCount == 1); - m_currentBlock->Append(SpirvOp::OpCompositeExtract, m_writer.GetTypeId(targetType), resultId, exprResultId, UInt32(node.components[0]) - UInt32(ShaderNodes::SwizzleComponent::First) ); + m_currentBlock->Append(SpirvOp::OpCompositeExtract, m_writer.GetTypeId(targetType), resultId, exprResultId, UInt32(node.components[0]) - UInt32(ShaderAst::SwizzleComponent::First) ); } PushResultId(resultId); diff --git a/src/Nazara/Shader/SpirvConstantCache.cpp b/src/Nazara/Shader/SpirvConstantCache.cpp index fd27b2dc6..05108f1f6 100644 --- a/src/Nazara/Shader/SpirvConstantCache.cpp +++ b/src/Nazara/Shader/SpirvConstantCache.cpp @@ -3,7 +3,6 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include #include #include #include @@ -536,7 +535,7 @@ namespace Nz else if constexpr (std::is_same_v || std::is_same_v) { return ConstantComposite{ - BuildType((std::is_same_v) ? ShaderNodes::BasicType::Float2 : ShaderNodes::BasicType::Int2), + BuildType((std::is_same_v) ? ShaderAst::BasicType::Float2 : ShaderAst::BasicType::Int2), { BuildConstant(arg.x), BuildConstant(arg.y) @@ -546,7 +545,7 @@ namespace Nz else if constexpr (std::is_same_v || std::is_same_v) { return ConstantComposite{ - BuildType((std::is_same_v) ? ShaderNodes::BasicType::Float3 : ShaderNodes::BasicType::Int3), + BuildType((std::is_same_v) ? ShaderAst::BasicType::Float3 : ShaderAst::BasicType::Int3), { BuildConstant(arg.x), BuildConstant(arg.y), @@ -557,7 +556,7 @@ namespace Nz else if constexpr (std::is_same_v || std::is_same_v) { return ConstantComposite{ - BuildType((std::is_same_v) ? ShaderNodes::BasicType::Float4 : ShaderNodes::BasicType::Int4), + BuildType((std::is_same_v) ? ShaderAst::BasicType::Float4 : ShaderAst::BasicType::Int4), { BuildConstant(arg.x), BuildConstant(arg.y), @@ -571,7 +570,7 @@ namespace Nz }, value)); } - auto SpirvConstantCache::BuildPointerType(const ShaderNodes::BasicType& type, SpirvStorageClass storageClass) -> TypePtr + auto SpirvConstantCache::BuildPointerType(const ShaderAst::BasicType& type, SpirvStorageClass storageClass) -> TypePtr { return std::make_shared(SpirvConstantCache::Pointer{ SpirvConstantCache::BuildType(type), @@ -579,55 +578,55 @@ namespace Nz }); } - auto SpirvConstantCache::BuildPointerType(const ShaderAst& shader, const ShaderExpressionType& type, SpirvStorageClass storageClass) -> TypePtr + auto SpirvConstantCache::BuildPointerType(const ShaderAst::ShaderExpressionType& type, SpirvStorageClass storageClass) -> TypePtr { return std::make_shared(SpirvConstantCache::Pointer{ - SpirvConstantCache::BuildType(shader, type), + SpirvConstantCache::BuildType(type), storageClass }); } - auto SpirvConstantCache::BuildType(const ShaderNodes::BasicType& type) -> TypePtr + auto SpirvConstantCache::BuildType(const ShaderAst::BasicType& type) -> TypePtr { return std::make_shared([&]() -> AnyType { switch (type) { - case ShaderNodes::BasicType::Boolean: + case ShaderAst::BasicType::Boolean: return Bool{}; - case ShaderNodes::BasicType::Float1: + case ShaderAst::BasicType::Float1: return Float{ 32 }; - case ShaderNodes::BasicType::Int1: + case ShaderAst::BasicType::Int1: return Integer{ 32, true }; - case ShaderNodes::BasicType::Float2: - case ShaderNodes::BasicType::Float3: - case ShaderNodes::BasicType::Float4: - case ShaderNodes::BasicType::Int2: - case ShaderNodes::BasicType::Int3: - case ShaderNodes::BasicType::Int4: - case ShaderNodes::BasicType::UInt2: - case ShaderNodes::BasicType::UInt3: - case ShaderNodes::BasicType::UInt4: + case ShaderAst::BasicType::Float2: + case ShaderAst::BasicType::Float3: + case ShaderAst::BasicType::Float4: + case ShaderAst::BasicType::Int2: + case ShaderAst::BasicType::Int3: + case ShaderAst::BasicType::Int4: + case ShaderAst::BasicType::UInt2: + case ShaderAst::BasicType::UInt3: + case ShaderAst::BasicType::UInt4: { - auto vecType = BuildType(ShaderNodes::Node::GetComponentType(type)); - UInt32 componentCount = ShaderNodes::Node::GetComponentCount(type); + auto vecType = BuildType(ShaderAst::GetComponentType(type)); + UInt32 componentCount = ShaderAst::GetComponentCount(type); return Vector{ vecType, componentCount }; } - case ShaderNodes::BasicType::Mat4x4: - return Matrix{ BuildType(ShaderNodes::BasicType::Float4), 4u }; + case ShaderAst::BasicType::Mat4x4: + return Matrix{ BuildType(ShaderAst::BasicType::Float4), 4u }; - case ShaderNodes::BasicType::UInt1: + case ShaderAst::BasicType::UInt1: return Integer{ 32, false }; - case ShaderNodes::BasicType::Void: + case ShaderAst::BasicType::Void: return Void{}; - case ShaderNodes::BasicType::Sampler2D: + case ShaderAst::BasicType::Sampler2D: { auto imageType = Image{ {}, //< qualifier @@ -635,7 +634,7 @@ namespace Nz {}, //< sampled SpirvDim::Dim2D, //< dim SpirvImageFormat::Unknown, //< format - BuildType(ShaderNodes::BasicType::Float1), //< sampledType + BuildType(ShaderAst::BasicType::Float1), //< sampledType false, //< arrayed, false //< multisampled }; @@ -648,16 +647,16 @@ namespace Nz }()); } - auto SpirvConstantCache::BuildType(const ShaderAst& shader, const ShaderExpressionType& type) -> TypePtr + auto SpirvConstantCache::BuildType(const ShaderAst::ShaderExpressionType& type) -> TypePtr { return std::visit([&](auto&& arg) -> TypePtr { using T = std::decay_t; - if constexpr (std::is_same_v) + if constexpr (std::is_same_v) return BuildType(arg); else if constexpr (std::is_same_v) { - // Register struct members type + /*// Register struct members type const auto& structs = shader.GetStructs(); auto it = std::find_if(structs.begin(), structs.end(), [&](const auto& s) { return s.name == arg; }); if (it == structs.end()) @@ -675,7 +674,8 @@ namespace Nz sMembers.type = BuildType(shader, member.type); } - return std::make_shared(std::move(sType)); + return std::make_shared(std::move(sType));*/ + return nullptr; } else static_assert(AlwaysFalse::value, "non-exhaustive visitor"); diff --git a/src/Nazara/Shader/SpirvExpressionLoad.cpp b/src/Nazara/Shader/SpirvExpressionLoad.cpp index caddbec43..068280bd1 100644 --- a/src/Nazara/Shader/SpirvExpressionLoad.cpp +++ b/src/Nazara/Shader/SpirvExpressionLoad.cpp @@ -16,7 +16,7 @@ namespace Nz template overloaded(Ts...) -> overloaded; } - UInt32 SpirvExpressionLoad::Evaluate(ShaderNodes::Expression& node) + UInt32 SpirvExpressionLoad::Evaluate(ShaderAst::Expression& node) { node.Visit(*this); @@ -41,7 +41,7 @@ namespace Nz }, m_value); } - void SpirvExpressionLoad::Visit(ShaderNodes::AccessMember& node) + /*void SpirvExpressionLoad::Visit(ShaderAst::AccessMemberExpression& node) { Visit(node.structExpr); @@ -49,6 +49,8 @@ namespace Nz { [&](const Pointer& pointer) { + ShaderAst::ShaderExpressionType exprType = GetExpressionType(node.structExpr); + UInt32 resultId = m_writer.AllocateResultId(); UInt32 pointerType = m_writer.RegisterPointerType(node.exprType, pointer.storage); //< FIXME UInt32 typeId = m_writer.GetTypeId(node.exprType); @@ -87,40 +89,15 @@ namespace Nz throw std::runtime_error("an internal error occurred"); } }, m_value); - } + }*/ - void SpirvExpressionLoad::Visit(ShaderNodes::Identifier& node) + void SpirvExpressionLoad::Visit(ShaderAst::IdentifierExpression& node) { - Visit(node.var); - } - - void SpirvExpressionLoad::Visit(ShaderNodes::InputVariable& var) - { - auto inputVar = m_writer.GetInputVariable(var.name); - - if (auto resultIdOpt = m_writer.ReadVariable(inputVar, SpirvWriter::OnlyCache{})) - m_value = Value{ *resultIdOpt }; + if (node.identifier == "d") + m_value = Value{ m_writer.ReadLocalVariable(node.identifier) }; else - m_value = Pointer{ SpirvStorageClass::Input, inputVar.varId, inputVar.typeId }; - } + m_value = Value{ m_writer.ReadParameterVariable(node.identifier) }; - void SpirvExpressionLoad::Visit(ShaderNodes::LocalVariable& var) - { - m_value = Value{ m_writer.ReadLocalVariable(var.name) }; - } - - void SpirvExpressionLoad::Visit(ShaderNodes::ParameterVariable& var) - { - m_value = Value{ m_writer.ReadParameterVariable(var.name) }; - } - - void SpirvExpressionLoad::Visit(ShaderNodes::UniformVariable& var) - { - auto uniformVar = m_writer.GetUniformVariable(var.name); - - if (auto resultIdOpt = m_writer.ReadVariable(uniformVar, SpirvWriter::OnlyCache{})) - m_value = Value{ *resultIdOpt }; - else - m_value = Pointer{ SpirvStorageClass::Uniform, uniformVar.varId, uniformVar.typeId }; + //Visit(node.var); } } diff --git a/src/Nazara/Shader/SpirvExpressionStore.cpp b/src/Nazara/Shader/SpirvExpressionStore.cpp index a0c5511d1..8655b3a94 100644 --- a/src/Nazara/Shader/SpirvExpressionStore.cpp +++ b/src/Nazara/Shader/SpirvExpressionStore.cpp @@ -15,9 +15,9 @@ namespace Nz template overloaded(Ts...)->overloaded; } - void SpirvExpressionStore::Store(const ShaderNodes::ExpressionPtr& node, UInt32 resultId) + void SpirvExpressionStore::Store(ShaderAst::ExpressionPtr& node, UInt32 resultId) { - Visit(node); + node->Visit(*this); std::visit(overloaded { @@ -36,7 +36,7 @@ namespace Nz }, m_value); } - void SpirvExpressionStore::Visit(ShaderNodes::AccessMember& node) + /*void SpirvExpressionStore::Visit(ShaderAst::AccessMemberExpression& node) { Visit(node.structExpr); @@ -70,34 +70,15 @@ namespace Nz throw std::runtime_error("an internal error occurred"); } }, m_value); - } + }*/ - void SpirvExpressionStore::Visit(ShaderNodes::Identifier& node) + void SpirvExpressionStore::Visit(ShaderAst::IdentifierExpression& node) { - Visit(node.var); + m_value = LocalVar{ node.identifier }; } - void SpirvExpressionStore::Visit(ShaderNodes::SwizzleOp& node) + void SpirvExpressionStore::Visit(ShaderAst::SwizzleExpression& node) { throw std::runtime_error("not yet implemented"); } - - void SpirvExpressionStore::Visit(ShaderNodes::BuiltinVariable& var) - { - const auto& outputVar = m_writer.GetBuiltinVariable(var.entry); - - m_value = Pointer{ SpirvStorageClass::Output, outputVar.varId }; - } - - void SpirvExpressionStore::Visit(ShaderNodes::LocalVariable& var) - { - m_value = LocalVar{ var.name }; - } - - void SpirvExpressionStore::Visit(ShaderNodes::OutputVariable& var) - { - const auto& outputVar = m_writer.GetOutputVariable(var.name); - - m_value = Pointer{ SpirvStorageClass::Output, outputVar.varId }; - } } diff --git a/src/Nazara/Shader/SpirvWriter.cpp b/src/Nazara/Shader/SpirvWriter.cpp index 6316e42ee..d108d7efb 100644 --- a/src/Nazara/Shader/SpirvWriter.cpp +++ b/src/Nazara/Shader/SpirvWriter.cpp @@ -26,155 +26,131 @@ namespace Nz { namespace { - class PreVisitor : public ShaderAstRecursiveVisitor, public ShaderVarVisitor + class PreVisitor : public ShaderAst::AstRecursiveVisitor { public: - using BuiltinContainer = std::unordered_set>; using ExtInstList = std::unordered_set; - using LocalContainer = std::unordered_set>; - using ParameterContainer = std::unordered_set< std::shared_ptr>; + using LocalContainer = std::unordered_set; - PreVisitor(const ShaderAst& shader, const SpirvWriter::States& conditions, SpirvConstantCache& constantCache) : - m_shader(shader), + PreVisitor(ShaderAst::AstCache* cache, const SpirvWriter::States& conditions, SpirvConstantCache& constantCache) : + m_cache(cache), m_conditions(conditions), m_constantCache(constantCache) { } - using ShaderAstRecursiveVisitor::Visit; - using ShaderVarVisitor::Visit; - - void Visit(ShaderNodes::AccessMember& node) override + void Visit(ShaderAst::AccessMemberExpression& node) override { - for (std::size_t index : node.memberIndices) - m_constantCache.Register(*SpirvConstantCache::BuildConstant(Int32(index))); + /*for (std::size_t index : node.memberIdentifiers) + m_constantCache.Register(*SpirvConstantCache::BuildConstant(Int32(index)));*/ - ShaderAstRecursiveVisitor::Visit(node); + AstRecursiveVisitor::Visit(node); } - void Visit(ShaderNodes::ConditionalExpression& node) override + void Visit(ShaderAst::ConditionalExpression& node) override { - std::size_t conditionIndex = m_shader.FindConditionByName(node.conditionName); + /*std::size_t conditionIndex = m_shader.FindConditionByName(node.conditionName); assert(conditionIndex != ShaderAst::InvalidCondition); if (TestBit(m_conditions.enabledConditions, conditionIndex)) Visit(node.truePath); else - Visit(node.falsePath); + Visit(node.falsePath);*/ } - void Visit(ShaderNodes::ConditionalStatement& node) override + void Visit(ShaderAst::ConditionalStatement& node) override { - std::size_t conditionIndex = m_shader.FindConditionByName(node.conditionName); + /*std::size_t conditionIndex = m_shader.FindConditionByName(node.conditionName); assert(conditionIndex != ShaderAst::InvalidCondition); if (TestBit(m_conditions.enabledConditions, conditionIndex)) - Visit(node.statement); + Visit(node.statement);*/ } - void Visit(ShaderNodes::Constant& node) override + void Visit(ShaderAst::ConstantExpression& node) override { std::visit([&](auto&& arg) { m_constantCache.Register(*SpirvConstantCache::BuildConstant(arg)); }, node.value); - ShaderAstRecursiveVisitor::Visit(node); + AstRecursiveVisitor::Visit(node); } - void Visit(ShaderNodes::DeclareVariable& node) override + void Visit(ShaderAst::DeclareFunctionStatement& node) override { - Visit(node.variable); - - ShaderAstRecursiveVisitor::Visit(node); + m_constantCache.Register(*SpirvConstantCache::BuildType(node.returnType)); + for (auto& parameter : node.parameters) + m_constantCache.Register(*SpirvConstantCache::BuildType(parameter.type)); } - void Visit(ShaderNodes::Identifier& node) override + void Visit(ShaderAst::DeclareStructStatement& node) override { - Visit(node.var); - - ShaderAstRecursiveVisitor::Visit(node); + for (auto& field : node.description.members) + m_constantCache.Register(*SpirvConstantCache::BuildType(field.type)); } - void Visit(ShaderNodes::IntrinsicCall& node) override + void Visit(ShaderAst::DeclareVariableStatement& node) override { - ShaderAstRecursiveVisitor::Visit(node); + variableTypes.insert(node.varType); + + AstRecursiveVisitor::Visit(node); + } + + void Visit(ShaderAst::IdentifierExpression& node) override + { + variableTypes.insert(GetExpressionType(node, m_cache)); + + AstRecursiveVisitor::Visit(node); + } + + void Visit(ShaderAst::IntrinsicExpression& node) override + { + AstRecursiveVisitor::Visit(node); switch (node.intrinsic) { // Require GLSL.std.450 - case ShaderNodes::IntrinsicType::CrossProduct: + case ShaderAst::IntrinsicType::CrossProduct: extInsts.emplace("GLSL.std.450"); break; // Part of SPIR-V core - case ShaderNodes::IntrinsicType::DotProduct: + case ShaderAst::IntrinsicType::DotProduct: break; } } - void Visit(ShaderNodes::BuiltinVariable& var) override - { - builtinVars.insert(std::static_pointer_cast(var.shared_from_this())); - } - - void Visit(ShaderNodes::InputVariable& /*var*/) override - { - /* Handled by ShaderAst */ - } - - void Visit(ShaderNodes::LocalVariable& var) override - { - localVars.insert(std::static_pointer_cast(var.shared_from_this())); - } - - void Visit(ShaderNodes::OutputVariable& /*var*/) override - { - /* Handled by ShaderAst */ - } - - void Visit(ShaderNodes::ParameterVariable& var) override - { - paramVars.insert(std::static_pointer_cast(var.shared_from_this())); - } - - void Visit(ShaderNodes::UniformVariable& /*var*/) override - { - /* Handled by ShaderAst */ - } - - BuiltinContainer builtinVars; ExtInstList extInsts; - LocalContainer localVars; - ParameterContainer paramVars; + LocalContainer variableTypes; private: - const ShaderAst& m_shader; + ShaderAst::AstCache* m_cache; const SpirvWriter::States& m_conditions; SpirvConstantCache& m_constantCache; }; template - constexpr ShaderNodes::BasicType GetBasicType() + constexpr ShaderAst::BasicType GetBasicType() { if constexpr (std::is_same_v) - return ShaderNodes::BasicType::Boolean; + return ShaderAst::BasicType::Boolean; else if constexpr (std::is_same_v) - return(ShaderNodes::BasicType::Float1); + return(ShaderAst::BasicType::Float1); else if constexpr (std::is_same_v) - return(ShaderNodes::BasicType::Int1); + return(ShaderAst::BasicType::Int1); else if constexpr (std::is_same_v) - return(ShaderNodes::BasicType::Float2); + return(ShaderAst::BasicType::Float2); else if constexpr (std::is_same_v) - return(ShaderNodes::BasicType::Float3); + return(ShaderAst::BasicType::Float3); else if constexpr (std::is_same_v) - return(ShaderNodes::BasicType::Float4); + return(ShaderAst::BasicType::Float4); else if constexpr (std::is_same_v) - return(ShaderNodes::BasicType::Int2); + return(ShaderAst::BasicType::Int2); else if constexpr (std::is_same_v) - return(ShaderNodes::BasicType::Int3); + return(ShaderAst::BasicType::Int3); else if constexpr (std::is_same_v) - return(ShaderNodes::BasicType::Int4); + return(ShaderAst::BasicType::Int4); else static_assert(AlwaysFalse::value, "unhandled type"); } @@ -198,7 +174,7 @@ namespace Nz tsl::ordered_map parameterIds; tsl::ordered_map uniformIds; std::unordered_map extensionInstructions; - std::unordered_map builtinIds; + std::unordered_map builtinIds; std::unordered_map varToResult; std::vector funcs; std::vector functionBlocks; @@ -219,13 +195,12 @@ namespace Nz { } - std::vector SpirvWriter::Generate(const ShaderAst& shader, const States& conditions) + std::vector SpirvWriter::Generate(ShaderAst::StatementPtr& shader, const States& conditions) { std::string error; - if (!ValidateShader(shader, &error)) + if (!ShaderAst::ValidateAst(shader, &error, &m_context.cache)) throw std::runtime_error("Invalid shader AST: " + error); - m_context.shader = &shader; m_context.states = &conditions; State state; @@ -235,23 +210,19 @@ namespace Nz m_currentState = nullptr; }); - std::vector functionStatements; + std::vector functionStatements; - ShaderAstCloner cloner; - - PreVisitor preVisitor(shader, conditions, state.constantTypeCache); - for (const auto& func : shader.GetFunctions()) - { - functionStatements.emplace_back(cloner.Clone(func.statement)); - preVisitor.Visit(func.statement); - } + ShaderAst::AstCloner cloner; // Register all extended instruction sets + PreVisitor preVisitor(&m_context.cache, conditions, state.constantTypeCache); + shader->Visit(preVisitor); + for (const std::string& extInst : preVisitor.extInsts) state.extensionInstructions[extInst] = AllocateResultId(); // Register all types - for (const auto& func : shader.GetFunctions()) + /*for (const auto& func : shader.GetFunctions()) { RegisterType(func.returnType); for (const auto& param : func.parameters) @@ -270,8 +241,8 @@ namespace Nz for (const auto& func : shader.GetFunctions()) RegisterFunctionType(func.returnType, func.parameters); - for (const auto& local : preVisitor.localVars) - RegisterType(local->type); + for (const auto& type : preVisitor.variableTypes) + RegisterType(type); for (const auto& builtin : preVisitor.builtinVars) RegisterType(builtin->type); @@ -283,7 +254,7 @@ namespace Nz SpirvBuiltIn builtinDecoration; switch (builtin->entry) { - case ShaderNodes::BuiltinEntry::VertexPosition: + case ShaderAst::BuiltinEntry::VertexPosition: variable.debugName = "builtin_VertexPosition"; variable.storageClass = SpirvStorageClass::Output; @@ -294,10 +265,10 @@ namespace Nz throw std::runtime_error("unexpected builtin type"); } - const ShaderExpressionType& builtinExprType = builtin->type; + const ShaderAst::ShaderExpressionType& builtinExprType = builtin->type; assert(IsBasicType(builtinExprType)); - ShaderNodes::BasicType builtinType = std::get(builtinExprType); + ShaderAst::BasicType builtinType = std::get(builtinExprType); variable.type = SpirvConstantCache::BuildPointerType(builtinType, variable.storageClass); @@ -420,7 +391,7 @@ namespace Nz if (!state.functionBlocks.back().IsTerminated()) { - assert(func.returnType == ShaderExpressionType(ShaderNodes::BasicType::Void)); + assert(func.returnType == ShaderAst::ShaderExpressionType(ShaderAst::BasicType::Void)); state.functionBlocks.back().Append(SpirvOp::OpReturn); } @@ -475,14 +446,14 @@ namespace Nz if (m_context.shader->GetStage() == ShaderStageType::Fragment) state.header.Append(SpirvOp::OpExecutionMode, entryFunc.id, SpvExecutionModeOriginUpperLeft); - } + }*/ std::vector ret; - MergeSections(ret, state.header); + /*MergeSections(ret, state.header); MergeSections(ret, state.debugInfo); MergeSections(ret, state.annotations); MergeSections(ret, state.constants); - MergeSections(ret, state.instructions); + MergeSections(ret, state.instructions);*/ return ret; } @@ -516,16 +487,16 @@ namespace Nz m_currentState->header.Append(SpirvOp::OpMemoryModel, SpvAddressingModelLogical, SpvMemoryModelGLSL450); } - SpirvConstantCache::Function SpirvWriter::BuildFunctionType(ShaderExpressionType retType, const std::vector& parameters) + SpirvConstantCache::Function SpirvWriter::BuildFunctionType(ShaderAst::ShaderExpressionType retType, const std::vector& parameters) { std::vector parameterTypes; parameterTypes.reserve(parameters.size()); for (const auto& parameter : parameters) - parameterTypes.push_back(SpirvConstantCache::BuildPointerType(*m_context.shader, parameter.type, SpirvStorageClass::Function)); + parameterTypes.push_back(SpirvConstantCache::BuildPointerType(parameter.type, SpirvStorageClass::Function)); return SpirvConstantCache::Function{ - SpirvConstantCache::BuildType(*m_context.shader, retType), + SpirvConstantCache::BuildType(retType), std::move(parameterTypes) }; } @@ -535,12 +506,12 @@ namespace Nz return m_currentState->constantTypeCache.GetId(*SpirvConstantCache::BuildConstant(value)); } - UInt32 SpirvWriter::GetFunctionTypeId(ShaderExpressionType retType, const std::vector& parameters) + UInt32 SpirvWriter::GetFunctionTypeId(ShaderAst::ShaderExpressionType retType, const std::vector& parameters) { return m_currentState->constantTypeCache.GetId({ BuildFunctionType(retType, parameters) }); } - auto SpirvWriter::GetBuiltinVariable(ShaderNodes::BuiltinEntry builtin) const -> const ExtVar& + auto SpirvWriter::GetBuiltinVariable(ShaderAst::BuiltinEntry builtin) const -> const ExtVar& { auto it = m_currentState->builtinIds.find(builtin); assert(it != m_currentState->builtinIds.end()); @@ -572,14 +543,14 @@ namespace Nz return it.value(); } - UInt32 SpirvWriter::GetPointerTypeId(const ShaderExpressionType& type, SpirvStorageClass storageClass) const + UInt32 SpirvWriter::GetPointerTypeId(const ShaderAst::ShaderExpressionType& type, SpirvStorageClass storageClass) const { - return m_currentState->constantTypeCache.GetId(*SpirvConstantCache::BuildPointerType(*m_context.shader, type, storageClass)); + return m_currentState->constantTypeCache.GetId(*SpirvConstantCache::BuildPointerType(type, storageClass)); } - UInt32 SpirvWriter::GetTypeId(const ShaderExpressionType& type) const + UInt32 SpirvWriter::GetTypeId(const ShaderAst::ShaderExpressionType& type) const { - return m_currentState->constantTypeCache.GetId(*SpirvConstantCache::BuildType(*m_context.shader, type)); + return m_currentState->constantTypeCache.GetId(*SpirvConstantCache::BuildType(type)); } UInt32 SpirvWriter::ReadInputVariable(const std::string& name) @@ -673,20 +644,20 @@ namespace Nz return m_currentState->constantTypeCache.Register(*SpirvConstantCache::BuildConstant(value)); } - UInt32 SpirvWriter::RegisterFunctionType(ShaderExpressionType retType, const std::vector& parameters) + UInt32 SpirvWriter::RegisterFunctionType(ShaderAst::ShaderExpressionType retType, const std::vector& parameters) { return m_currentState->constantTypeCache.Register({ BuildFunctionType(retType, parameters) }); } - UInt32 SpirvWriter::RegisterPointerType(ShaderExpressionType type, SpirvStorageClass storageClass) + UInt32 SpirvWriter::RegisterPointerType(ShaderAst::ShaderExpressionType type, SpirvStorageClass storageClass) { - return m_currentState->constantTypeCache.Register(*SpirvConstantCache::BuildPointerType(*m_context.shader, type, storageClass)); + return m_currentState->constantTypeCache.Register(*SpirvConstantCache::BuildPointerType(type, storageClass)); } - UInt32 SpirvWriter::RegisterType(ShaderExpressionType type) + UInt32 SpirvWriter::RegisterType(ShaderAst::ShaderExpressionType type) { assert(m_currentState); - return m_currentState->constantTypeCache.Register(*SpirvConstantCache::BuildType(*m_context.shader, type)); + return m_currentState->constantTypeCache.Register(*SpirvConstantCache::BuildType(type)); } void SpirvWriter::WriteLocalVariable(std::string name, UInt32 resultId) From 48b93a9deac57d5d1e54397fd4bdbdcbdb512d75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 11 Mar 2021 17:50:11 +0100 Subject: [PATCH 078/278] Shader: Fix SPIRV generation --- include/Nazara/Shader/SpirvAstVisitor.hpp | 5 +- include/Nazara/Shader/SpirvAstVisitor.inl | 3 +- include/Nazara/Shader/SpirvConstantCache.hpp | 1 + include/Nazara/Shader/SpirvWriter.hpp | 7 +- src/Nazara/Shader/ShaderAstExpressionType.cpp | 2 + src/Nazara/Shader/SpirvAstVisitor.cpp | 10 +-- src/Nazara/Shader/SpirvConstantCache.cpp | 22 ++++- src/Nazara/Shader/SpirvWriter.cpp | 89 +++++++++---------- 8 files changed, 78 insertions(+), 61 deletions(-) diff --git a/include/Nazara/Shader/SpirvAstVisitor.hpp b/include/Nazara/Shader/SpirvAstVisitor.hpp index ffead5fef..b6536ea2e 100644 --- a/include/Nazara/Shader/SpirvAstVisitor.hpp +++ b/include/Nazara/Shader/SpirvAstVisitor.hpp @@ -21,7 +21,7 @@ namespace Nz class NAZARA_SHADER_API SpirvAstVisitor : public ShaderAst::ExpressionVisitorExcept, public ShaderAst::StatementVisitorExcept { public: - inline SpirvAstVisitor(SpirvWriter& writer, std::vector& blocks); + inline SpirvAstVisitor(SpirvWriter& writer, std::vector& blocks, ShaderAst::AstCache* cache); SpirvAstVisitor(const SpirvAstVisitor&) = delete; SpirvAstVisitor(SpirvAstVisitor&&) = delete; ~SpirvAstVisitor() = default; @@ -56,9 +56,10 @@ namespace Nz void PushResultId(UInt32 value); UInt32 PopResultId(); - SpirvBlock* m_currentBlock; + ShaderAst::AstCache* m_cache; std::vector& m_blocks; std::vector m_resultIds; + SpirvBlock* m_currentBlock; SpirvWriter& m_writer; }; } diff --git a/include/Nazara/Shader/SpirvAstVisitor.inl b/include/Nazara/Shader/SpirvAstVisitor.inl index 048f5768e..8694244be 100644 --- a/include/Nazara/Shader/SpirvAstVisitor.inl +++ b/include/Nazara/Shader/SpirvAstVisitor.inl @@ -7,7 +7,8 @@ namespace Nz { - inline SpirvAstVisitor::SpirvAstVisitor(SpirvWriter& writer, std::vector& blocks) : + inline SpirvAstVisitor::SpirvAstVisitor(SpirvWriter& writer, std::vector& blocks, ShaderAst::AstCache* cache) : + m_cache(cache), m_blocks(blocks), m_writer(writer) { diff --git a/include/Nazara/Shader/SpirvConstantCache.hpp b/include/Nazara/Shader/SpirvConstantCache.hpp index 54a53584c..7cc829518 100644 --- a/include/Nazara/Shader/SpirvConstantCache.hpp +++ b/include/Nazara/Shader/SpirvConstantCache.hpp @@ -172,6 +172,7 @@ namespace Nz SpirvConstantCache& operator=(SpirvConstantCache&& cache) noexcept; static ConstantPtr BuildConstant(const ShaderConstantValue& value); + static TypePtr BuildFunctionType(const ShaderAst::ShaderExpressionType& retType, const std::vector& parameters); static TypePtr BuildPointerType(const ShaderAst::BasicType& type, SpirvStorageClass storageClass); static TypePtr BuildPointerType(const ShaderAst::ShaderExpressionType& type, SpirvStorageClass storageClass); static TypePtr BuildType(const ShaderAst::BasicType& type); diff --git a/include/Nazara/Shader/SpirvWriter.hpp b/include/Nazara/Shader/SpirvWriter.hpp index a8af651cd..d0c5f561d 100644 --- a/include/Nazara/Shader/SpirvWriter.hpp +++ b/include/Nazara/Shader/SpirvWriter.hpp @@ -56,10 +56,8 @@ namespace Nz void AppendHeader(); - SpirvConstantCache::Function BuildFunctionType(ShaderAst::ShaderExpressionType retType, const std::vector& parameters); - UInt32 GetConstantId(const ShaderConstantValue& value) const; - UInt32 GetFunctionTypeId(ShaderAst::ShaderExpressionType retType, const std::vector& parameters); + UInt32 GetFunctionTypeId(const ShaderAst::DeclareFunctionStatement& functionNode); const ExtVar& GetBuiltinVariable(ShaderAst::BuiltinEntry builtin) const; const ExtVar& GetInputVariable(const std::string& name) const; const ExtVar& GetOutputVariable(const std::string& name) const; @@ -81,12 +79,13 @@ namespace Nz std::optional ReadVariable(const ExtVar& var, OnlyCache); UInt32 RegisterConstant(const ShaderConstantValue& value); - UInt32 RegisterFunctionType(ShaderAst::ShaderExpressionType retType, const std::vector& parameters); + UInt32 RegisterFunctionType(const ShaderAst::DeclareFunctionStatement& functionNode); UInt32 RegisterPointerType(ShaderAst::ShaderExpressionType type, SpirvStorageClass storageClass); UInt32 RegisterType(ShaderAst::ShaderExpressionType type); void WriteLocalVariable(std::string name, UInt32 resultId); + static SpirvConstantCache::TypePtr BuildFunctionType(const ShaderAst::DeclareFunctionStatement& functionNode); static void MergeSections(std::vector& output, const SpirvSection& from); struct Context diff --git a/src/Nazara/Shader/ShaderAstExpressionType.cpp b/src/Nazara/Shader/ShaderAstExpressionType.cpp index be4f238e9..9a6b394d7 100644 --- a/src/Nazara/Shader/ShaderAstExpressionType.cpp +++ b/src/Nazara/Shader/ShaderAstExpressionType.cpp @@ -163,6 +163,8 @@ namespace Nz::ShaderAst void ExpressionTypeVisitor::Visit(IdentifierExpression& node) { + assert(m_cache); + auto scopeIt = m_cache->scopeIdByNode.find(&node); if (scopeIt == m_cache->scopeIdByNode.end()) throw std::runtime_error("internal error"); diff --git a/src/Nazara/Shader/SpirvAstVisitor.cpp b/src/Nazara/Shader/SpirvAstVisitor.cpp index 96a099a21..0dd4737a3 100644 --- a/src/Nazara/Shader/SpirvAstVisitor.cpp +++ b/src/Nazara/Shader/SpirvAstVisitor.cpp @@ -39,13 +39,13 @@ namespace Nz void SpirvAstVisitor::Visit(ShaderAst::BinaryExpression& node) { - ShaderAst::ShaderExpressionType resultExprType = ShaderAst::GetExpressionType(node); + ShaderAst::ShaderExpressionType resultExprType = ShaderAst::GetExpressionType(node, m_cache); assert(IsBasicType(resultExprType)); - ShaderAst::ShaderExpressionType leftExprType = ShaderAst::GetExpressionType(*node.left); + ShaderAst::ShaderExpressionType leftExprType = ShaderAst::GetExpressionType(*node.left, m_cache); assert(IsBasicType(leftExprType)); - ShaderAst::ShaderExpressionType rightExprType = ShaderAst::GetExpressionType(*node.right); + ShaderAst::ShaderExpressionType rightExprType = ShaderAst::GetExpressionType(*node.right, m_cache); assert(IsBasicType(rightExprType)); ShaderAst::BasicType resultType = std::get(resultExprType); @@ -582,7 +582,7 @@ namespace Nz { case ShaderAst::IntrinsicType::DotProduct: { - const ShaderAst::ShaderExpressionType& vecExprType = GetExpressionType(*node.parameters[0]); + ShaderAst::ShaderExpressionType vecExprType = GetExpressionType(*node.parameters[0], m_cache); assert(IsBasicType(vecExprType)); ShaderAst::BasicType vecType = std::get(vecExprType); @@ -626,7 +626,7 @@ namespace Nz void SpirvAstVisitor::Visit(ShaderAst::SwizzleExpression& node) { - const ShaderAst::ShaderExpressionType& targetExprType = ShaderAst::GetExpressionType(node); + ShaderAst::ShaderExpressionType targetExprType = ShaderAst::GetExpressionType(node, m_cache); assert(IsBasicType(targetExprType)); ShaderAst::BasicType targetType = std::get(targetExprType); diff --git a/src/Nazara/Shader/SpirvConstantCache.cpp b/src/Nazara/Shader/SpirvConstantCache.cpp index 05108f1f6..97d40a509 100644 --- a/src/Nazara/Shader/SpirvConstantCache.cpp +++ b/src/Nazara/Shader/SpirvConstantCache.cpp @@ -570,18 +570,32 @@ namespace Nz }, value)); } + auto SpirvConstantCache::BuildFunctionType(const ShaderAst::ShaderExpressionType& retType, const std::vector& parameters) -> TypePtr + { + std::vector parameterTypes; + parameterTypes.reserve(parameters.size()); + + for (const auto& parameterType : parameters) + parameterTypes.push_back(BuildPointerType(parameterType, SpirvStorageClass::Function)); + + return std::make_shared(Function{ + BuildType(retType), + std::move(parameterTypes) + }); + } + auto SpirvConstantCache::BuildPointerType(const ShaderAst::BasicType& type, SpirvStorageClass storageClass) -> TypePtr { - return std::make_shared(SpirvConstantCache::Pointer{ - SpirvConstantCache::BuildType(type), + return std::make_shared(Pointer{ + BuildType(type), storageClass }); } auto SpirvConstantCache::BuildPointerType(const ShaderAst::ShaderExpressionType& type, SpirvStorageClass storageClass) -> TypePtr { - return std::make_shared(SpirvConstantCache::Pointer{ - SpirvConstantCache::BuildType(type), + return std::make_shared(Pointer{ + BuildType(type), storageClass }); } diff --git a/src/Nazara/Shader/SpirvWriter.cpp b/src/Nazara/Shader/SpirvWriter.cpp index d108d7efb..c877db5a0 100644 --- a/src/Nazara/Shader/SpirvWriter.cpp +++ b/src/Nazara/Shader/SpirvWriter.cpp @@ -31,6 +31,7 @@ namespace Nz public: using ExtInstList = std::unordered_set; using LocalContainer = std::unordered_set; + using FunctionContainer = std::vector>; PreVisitor(ShaderAst::AstCache* cache, const SpirvWriter::States& conditions, SpirvConstantCache& constantCache) : m_cache(cache), @@ -79,9 +80,15 @@ namespace Nz void Visit(ShaderAst::DeclareFunctionStatement& node) override { - m_constantCache.Register(*SpirvConstantCache::BuildType(node.returnType)); + funcs.emplace_back(node); + + std::vector parameterTypes; for (auto& parameter : node.parameters) - m_constantCache.Register(*SpirvConstantCache::BuildType(parameter.type)); + parameterTypes.push_back(parameter.type); + + m_constantCache.Register(*SpirvConstantCache::BuildFunctionType(node.returnType, parameterTypes)); + + AstRecursiveVisitor::Visit(node); } void Visit(ShaderAst::DeclareStructStatement& node) override @@ -92,14 +99,14 @@ namespace Nz void Visit(ShaderAst::DeclareVariableStatement& node) override { - variableTypes.insert(node.varType); + m_constantCache.Register(*SpirvConstantCache::BuildType(node.varType)); AstRecursiveVisitor::Visit(node); } void Visit(ShaderAst::IdentifierExpression& node) override { - variableTypes.insert(GetExpressionType(node, m_cache)); + m_constantCache.Register(*SpirvConstantCache::BuildType(GetExpressionType(node, m_cache))); AstRecursiveVisitor::Visit(node); } @@ -122,7 +129,7 @@ namespace Nz } ExtInstList extInsts; - LocalContainer variableTypes; + FunctionContainer funcs; private: ShaderAst::AstCache* m_cache; @@ -210,8 +217,6 @@ namespace Nz m_currentState = nullptr; }); - std::vector functionStatements; - ShaderAst::AstCloner cloner; // Register all extended instruction sets @@ -345,26 +350,22 @@ namespace Nz state.annotations.Append(SpirvOp::OpDecorate, varId, SpirvDecoration::Binding, *uniform.bindingIndex); state.annotations.Append(SpirvOp::OpDecorate, varId, SpirvDecoration::DescriptorSet, 0); } - } + }*/ - for (const auto& func : shader.GetFunctions()) + for (const ShaderAst::DeclareFunctionStatement& func : preVisitor.funcs) { auto& funcData = state.funcs.emplace_back(); funcData.id = AllocateResultId(); - funcData.typeId = GetFunctionTypeId(func.returnType, func.parameters); + funcData.typeId = GetFunctionTypeId(func); state.debugInfo.Append(SpirvOp::OpName, funcData.id, func.name); } - std::size_t entryPointIndex = std::numeric_limits::max(); + std::size_t funcIndex = 0; - for (std::size_t funcIndex = 0; funcIndex < shader.GetFunctionCount(); ++funcIndex) + for (const ShaderAst::DeclareFunctionStatement& func : preVisitor.funcs) { - const auto& func = shader.GetFunction(funcIndex); - if (func.name == "main") - entryPointIndex = funcIndex; - - auto& funcData = state.funcs[funcIndex]; + auto& funcData = state.funcs[funcIndex++]; state.instructions.Append(SpirvOp::OpFunction, GetTypeId(func.returnType), funcData.id, 0, funcData.typeId); @@ -386,8 +387,9 @@ namespace Nz state.parameterIds.emplace(param.name, std::move(parameterData)); } - SpirvAstVisitor visitor(*this, state.functionBlocks); - visitor.Visit(functionStatements[funcIndex]); + SpirvAstVisitor visitor(*this, state.functionBlocks, &m_context.cache); + for (const auto& statement : func.statements) + statement->Visit(visitor); if (!state.functionBlocks.back().IsTerminated()) { @@ -405,7 +407,7 @@ namespace Nz AppendHeader(); - if (entryPointIndex != std::numeric_limits::max()) + /*if (entryPointIndex != std::numeric_limits::max()) { SpvExecutionModel execModel; const auto& entryFuncData = shader.GetFunction(entryPointIndex); @@ -415,11 +417,11 @@ namespace Nz switch (m_context.shader->GetStage()) { case ShaderStageType::Fragment: - execModel = SpvExecutionModelFragment; + execModel = SpirvExecutionModel::Fragment; break; case ShaderStageType::Vertex: - execModel = SpvExecutionModelVertex; + execModel = SpirvExecutionModel::Vertex; break; default: @@ -445,15 +447,15 @@ namespace Nz }); if (m_context.shader->GetStage() == ShaderStageType::Fragment) - state.header.Append(SpirvOp::OpExecutionMode, entryFunc.id, SpvExecutionModeOriginUpperLeft); + state.header.Append(SpirvOp::OpExecutionMode, entryFunc.id, SpirvExecutionMode::OriginUpperLeft); }*/ std::vector ret; - /*MergeSections(ret, state.header); + MergeSections(ret, state.header); MergeSections(ret, state.debugInfo); MergeSections(ret, state.annotations); MergeSections(ret, state.constants); - MergeSections(ret, state.instructions);*/ + MergeSections(ret, state.instructions); return ret; } @@ -479,26 +481,12 @@ namespace Nz m_currentState->header.AppendRaw(m_currentState->nextVarIndex); //< Bound (ID count) m_currentState->header.AppendRaw(0); //< Instruction schema (required to be 0 for now) - m_currentState->header.Append(SpirvOp::OpCapability, SpvCapabilityShader); + m_currentState->header.Append(SpirvOp::OpCapability, SpirvCapability::Shader); for (const auto& [extInst, resultId] : m_currentState->extensionInstructions) m_currentState->header.Append(SpirvOp::OpExtInstImport, resultId, extInst); - m_currentState->header.Append(SpirvOp::OpMemoryModel, SpvAddressingModelLogical, SpvMemoryModelGLSL450); - } - - SpirvConstantCache::Function SpirvWriter::BuildFunctionType(ShaderAst::ShaderExpressionType retType, const std::vector& parameters) - { - std::vector parameterTypes; - parameterTypes.reserve(parameters.size()); - - for (const auto& parameter : parameters) - parameterTypes.push_back(SpirvConstantCache::BuildPointerType(parameter.type, SpirvStorageClass::Function)); - - return SpirvConstantCache::Function{ - SpirvConstantCache::BuildType(retType), - std::move(parameterTypes) - }; + m_currentState->header.Append(SpirvOp::OpMemoryModel, SpirvAddressingModel::Logical, SpirvMemoryModel::GLSL450); } UInt32 SpirvWriter::GetConstantId(const ShaderConstantValue& value) const @@ -506,9 +494,9 @@ namespace Nz return m_currentState->constantTypeCache.GetId(*SpirvConstantCache::BuildConstant(value)); } - UInt32 SpirvWriter::GetFunctionTypeId(ShaderAst::ShaderExpressionType retType, const std::vector& parameters) + UInt32 SpirvWriter::GetFunctionTypeId(const ShaderAst::DeclareFunctionStatement& functionNode) { - return m_currentState->constantTypeCache.GetId({ BuildFunctionType(retType, parameters) }); + return m_currentState->constantTypeCache.GetId({ *BuildFunctionType(functionNode) }); } auto SpirvWriter::GetBuiltinVariable(ShaderAst::BuiltinEntry builtin) const -> const ExtVar& @@ -644,9 +632,9 @@ namespace Nz return m_currentState->constantTypeCache.Register(*SpirvConstantCache::BuildConstant(value)); } - UInt32 SpirvWriter::RegisterFunctionType(ShaderAst::ShaderExpressionType retType, const std::vector& parameters) + UInt32 SpirvWriter::RegisterFunctionType(const ShaderAst::DeclareFunctionStatement& functionNode) { - return m_currentState->constantTypeCache.Register({ BuildFunctionType(retType, parameters) }); + return m_currentState->constantTypeCache.Register({ *BuildFunctionType(functionNode) }); } UInt32 SpirvWriter::RegisterPointerType(ShaderAst::ShaderExpressionType type, SpirvStorageClass storageClass) @@ -666,6 +654,17 @@ namespace Nz m_currentState->varToResult.insert_or_assign(std::move(name), resultId); } + SpirvConstantCache::TypePtr SpirvWriter::BuildFunctionType(const ShaderAst::DeclareFunctionStatement& functionNode) + { + std::vector parameterTypes; + parameterTypes.reserve(functionNode.parameters.size()); + + for (const auto& parameter : functionNode.parameters) + parameterTypes.push_back(parameter.type); + + return SpirvConstantCache::BuildFunctionType(functionNode.returnType, parameterTypes); + } + void SpirvWriter::MergeSections(std::vector& output, const SpirvSection& from) { const std::vector& bytecode = from.GetBytecode(); From 3f74ee4d66e8f73da58d902e0db47fbc9d0dae25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 11 Mar 2021 17:51:38 +0100 Subject: [PATCH 079/278] Shader: Rework Parser internals --- include/Nazara/Shader/ShaderLangParser.hpp | 8 +- src/Nazara/Shader/ShaderLangLexer.cpp | 2 +- src/Nazara/Shader/ShaderLangParser.cpp | 117 ++++++++++++--------- 3 files changed, 73 insertions(+), 54 deletions(-) diff --git a/include/Nazara/Shader/ShaderLangParser.hpp b/include/Nazara/Shader/ShaderLangParser.hpp index 0588ecc44..4c0e12d86 100644 --- a/include/Nazara/Shader/ShaderLangParser.hpp +++ b/include/Nazara/Shader/ShaderLangParser.hpp @@ -49,9 +49,9 @@ namespace Nz::ShaderLang private: // Flow control const Token& Advance(); - void Expect(const Token& token, TokenType type); - const Token& ExpectNext(TokenType type); - const Token& PeekNext(); + const Token& Expect(const Token& token, TokenType type); + const Token& Expect(TokenType type); + const Token& Peek(std::size_t advance = 0); // Statements std::vector ParseFunctionBody(); @@ -70,7 +70,7 @@ namespace Nz::ShaderLang ShaderAst::ExpressionPtr ParseParenthesisExpression(); ShaderAst::ExpressionPtr ParsePrimaryExpression(); - std::string ParseIdentifierAsName(); + const std::string& ParseIdentifierAsName(); ShaderAst::ShaderExpressionType ParseIdentifierAsType(); static int GetTokenPrecedence(TokenType token); diff --git a/src/Nazara/Shader/ShaderLangLexer.cpp b/src/Nazara/Shader/ShaderLangLexer.cpp index 13b21b0c4..666b0d8d6 100644 --- a/src/Nazara/Shader/ShaderLangLexer.cpp +++ b/src/Nazara/Shader/ShaderLangLexer.cpp @@ -36,7 +36,7 @@ namespace Nz::ShaderLang std::vector Tokenize(const std::string_view& str) { - // Can't use std::from_chars for double thanks to libc++ and libstdc++ developers being lazy + // Can't use std::from_chars for double thanks to libc++ and libstdc++ developers for being lazy ForceCLocale forceCLocale; std::unordered_map reservedKeywords = { diff --git a/src/Nazara/Shader/ShaderLangParser.cpp b/src/Nazara/Shader/ShaderLangParser.cpp index 050d88f6d..d4ecbf0d5 100644 --- a/src/Nazara/Shader/ShaderLangParser.cpp +++ b/src/Nazara/Shader/ShaderLangParser.cpp @@ -45,12 +45,10 @@ namespace Nz::ShaderLang m_context = &context; - m_context->tokenIndex = -1; - bool reachedEndOfStream = false; while (!reachedEndOfStream) { - const Token& nextToken = PeekNext(); + const Token& nextToken = Peek(); switch (nextToken.type) { case TokenType::FunctionDeclaration: @@ -71,28 +69,32 @@ namespace Nz::ShaderLang const Token& Parser::Advance() { - assert(m_context->tokenIndex + 1 < m_context->tokenCount); - return m_context->tokens[++m_context->tokenIndex]; + const Token& token = Peek(); + m_context->tokenIndex++; + + return token; } - void Parser::Expect(const Token& token, TokenType type) + const Token& Parser::Expect(const Token& token, TokenType type) { if (token.type != type) throw ExpectedToken{}; + + return token; } - const Token& Parser::ExpectNext(TokenType type) + const Token& Parser::Expect(TokenType type) { - const Token& token = Advance(); + const Token& token = Peek(); Expect(token, type); return token; } - const Token& Parser::PeekNext() + const Token& Parser::Peek(std::size_t advance) { - assert(m_context->tokenIndex + 1 < m_context->tokenCount); - return m_context->tokens[m_context->tokenIndex + 1]; + assert(m_context->tokenIndex + advance < m_context->tokenCount); + return m_context->tokens[m_context->tokenIndex + advance]; } std::vector Parser::ParseFunctionBody() @@ -102,18 +104,18 @@ namespace Nz::ShaderLang ShaderAst::StatementPtr Parser::ParseFunctionDeclaration() { - ExpectNext(TokenType::FunctionDeclaration); + Expect(Advance(), TokenType::FunctionDeclaration); std::string functionName = ParseIdentifierAsName(); - ExpectNext(TokenType::OpenParenthesis); + Expect(Advance(), TokenType::OpenParenthesis); std::vector parameters; bool firstParameter = true; for (;;) { - const Token& t = PeekNext(); + const Token& t = Peek(); if (t.type == TokenType::ClosingParenthesis) break; @@ -127,21 +129,21 @@ namespace Nz::ShaderLang firstParameter = false; } - ExpectNext(TokenType::ClosingParenthesis); + Expect(Advance(), TokenType::ClosingParenthesis); ShaderAst::ShaderExpressionType returnType = ShaderAst::BasicType::Void; - if (PeekNext().type == TokenType::FunctionReturn) + if (Peek().type == TokenType::FunctionReturn) { Advance(); //< Consume -> returnType = ParseIdentifierAsType(); } - ExpectNext(TokenType::OpenCurlyBracket); + Expect(Advance(), TokenType::OpenCurlyBracket); std::vector functionBody = ParseFunctionBody(); - ExpectNext(TokenType::ClosingCurlyBracket); + Expect(Advance(), TokenType::ClosingCurlyBracket); return ShaderBuilder::DeclareFunction(std::move(functionName), std::move(parameters), std::move(functionBody), std::move(returnType)); } @@ -150,7 +152,7 @@ namespace Nz::ShaderLang { std::string parameterName = ParseIdentifierAsName(); - ExpectNext(TokenType::Colon); + Expect(Advance(), TokenType::Colon); ShaderAst::ShaderExpressionType parameterType = ParseIdentifierAsType(); @@ -159,10 +161,10 @@ namespace Nz::ShaderLang ShaderAst::StatementPtr Parser::ParseReturnStatement() { - ExpectNext(TokenType::Return); + Expect(Advance(), TokenType::Return); ShaderAst::ExpressionPtr expr; - if (PeekNext().type != TokenType::Semicolon) + if (Peek().type != TokenType::Semicolon) expr = ParseExpression(); return ShaderBuilder::Return(std::move(expr)); @@ -170,7 +172,7 @@ namespace Nz::ShaderLang ShaderAst::StatementPtr Parser::ParseStatement() { - const Token& token = PeekNext(); + const Token& token = Peek(); ShaderAst::StatementPtr statement; switch (token.type) @@ -187,7 +189,7 @@ namespace Nz::ShaderLang break; } - ExpectNext(TokenType::Semicolon); + Expect(Advance(), TokenType::Semicolon); return statement; } @@ -195,7 +197,7 @@ namespace Nz::ShaderLang std::vector Parser::ParseStatementList() { std::vector statements; - while (PeekNext().type != TokenType::ClosingCurlyBracket) + while (Peek().type != TokenType::ClosingCurlyBracket) { statements.push_back(ParseStatement()); } @@ -205,16 +207,16 @@ namespace Nz::ShaderLang ShaderAst::StatementPtr Parser::ParseVariableDeclaration() { - ExpectNext(TokenType::Let); + Expect(Advance(), TokenType::Let); std::string variableName = ParseIdentifierAsName(); - ExpectNext(TokenType::Colon); + Expect(Advance(), TokenType::Colon); ShaderAst::ShaderExpressionType variableType = ParseIdentifierAsType(); ShaderAst::ExpressionPtr expression; - if (PeekNext().type == TokenType::Assign) + if (Peek().type == TokenType::Assign) { Advance(); expression = ParseExpression(); @@ -227,7 +229,7 @@ namespace Nz::ShaderLang { for (;;) { - const Token& currentOp = PeekNext(); + const Token& currentOp = Peek(); int tokenPrecedence = GetTokenPrecedence(currentOp.type); if (tokenPrecedence < exprPrecedence) @@ -236,7 +238,7 @@ namespace Nz::ShaderLang Advance(); ShaderAst::ExpressionPtr rhs = ParsePrimaryExpression(); - const Token& nextOp = PeekNext(); + const Token& nextOp = Peek(); int nextTokenPrecedence = GetTokenPrecedence(nextOp.type); if (tokenPrecedence < nextTokenPrecedence) @@ -266,46 +268,62 @@ namespace Nz::ShaderLang ShaderAst::ExpressionPtr Parser::ParseIdentifier() { - const Token& identifier = ExpectNext(TokenType::Identifier); + const Token& identifierToken = Expect(Advance(), TokenType::Identifier); + const std::string& identifier = std::get(identifierToken.data); - return ShaderBuilder::Identifier(std::get(identifier.data)); + return ShaderBuilder::Identifier(identifier); } ShaderAst::ExpressionPtr Parser::ParseIntegerExpression() { - const Token& integer = ExpectNext(TokenType::IntegerValue); - return ShaderBuilder::Constant(static_cast(std::get(integer.data))); + const Token& integerToken = Expect(Advance(), TokenType::Identifier); + return ShaderBuilder::Constant(static_cast(std::get(integerToken.data))); } ShaderAst::ExpressionPtr Parser::ParseParenthesisExpression() { - ExpectNext(TokenType::OpenParenthesis); + Expect(Advance(), TokenType::OpenParenthesis); ShaderAst::ExpressionPtr expression = ParseExpression(); - ExpectNext(TokenType::ClosingParenthesis); + Expect(Advance(), TokenType::ClosingParenthesis); return expression; } ShaderAst::ExpressionPtr Parser::ParsePrimaryExpression() { - const Token& token = PeekNext(); + const Token& token = Peek(); switch (token.type) { - case TokenType::BoolFalse: return ShaderBuilder::Constant(false); - case TokenType::BoolTrue: return ShaderBuilder::Constant(true); - case TokenType::FloatingPointValue: return ShaderBuilder::Constant(float(std::get(Advance().data))); //< FIXME - case TokenType::Identifier: return ParseIdentifier(); - case TokenType::IntegerValue: return ParseIntegerExpression(); - case TokenType::OpenParenthesis: return ParseParenthesisExpression(); - default: throw UnexpectedToken{}; + case TokenType::BoolFalse: + Advance(); + return ShaderBuilder::Constant(false); + + case TokenType::BoolTrue: + Advance(); + return ShaderBuilder::Constant(true); + + case TokenType::FloatingPointValue: + Advance(); + return ShaderBuilder::Constant(float(std::get(token.data))); //< FIXME + + case TokenType::Identifier: + return ParseIdentifier(); + + case TokenType::IntegerValue: + return ParseIntegerExpression(); + + case TokenType::OpenParenthesis: + return ParseParenthesisExpression(); + + default: + throw UnexpectedToken{}; } } - std::string Parser::ParseIdentifierAsName() + const std::string& Parser::ParseIdentifierAsName() { - const Token& identifierToken = ExpectNext(TokenType::Identifier); - - std::string identifier = std::get(identifierToken.data); + const Token& identifierToken = Expect(Advance(), TokenType::Identifier); + const std::string& identifier = std::get(identifierToken.data); auto it = identifierToBasicType.find(identifier); if (it != identifierToBasicType.end()) @@ -316,9 +334,10 @@ namespace Nz::ShaderLang ShaderAst::ShaderExpressionType Parser::ParseIdentifierAsType() { - const Token& identifier = ExpectNext(TokenType::Identifier); + const Token& identifierToken = Expect(Advance(), TokenType::Identifier); + const std::string& identifier = std::get(identifierToken.data); - auto it = identifierToBasicType.find(std::get(identifier.data)); + auto it = identifierToBasicType.find(identifier); if (it == identifierToBasicType.end()) throw UnknownType{}; From 8135f22b2fed56eb18eea4b0f4585fc3700cf1ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 11 Mar 2021 18:03:25 +0100 Subject: [PATCH 080/278] Shader: Add attribute and square bracket tokens (first step for attribute support) --- include/Nazara/Shader/ShaderLangTokenList.hpp | 4 ++++ src/Nazara/Shader/ShaderLangLexer.cpp | 22 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/include/Nazara/Shader/ShaderLangTokenList.hpp b/include/Nazara/Shader/ShaderLangTokenList.hpp index d8eb56139..959c5df31 100644 --- a/include/Nazara/Shader/ShaderLangTokenList.hpp +++ b/include/Nazara/Shader/ShaderLangTokenList.hpp @@ -13,8 +13,10 @@ NAZARA_SHADERLANG_TOKEN(Assign) NAZARA_SHADERLANG_TOKEN(BoolFalse) NAZARA_SHADERLANG_TOKEN(BoolTrue) +NAZARA_SHADERLANG_TOKEN(ClosingAttribute) NAZARA_SHADERLANG_TOKEN(ClosingParenthesis) NAZARA_SHADERLANG_TOKEN(ClosingCurlyBracket) +NAZARA_SHADERLANG_TOKEN(ClosingSquareBracket) NAZARA_SHADERLANG_TOKEN(Colon) NAZARA_SHADERLANG_TOKEN(Comma) NAZARA_SHADERLANG_TOKEN(Divide) @@ -29,7 +31,9 @@ NAZARA_SHADERLANG_TOKEN(Let) NAZARA_SHADERLANG_TOKEN(Multiply) NAZARA_SHADERLANG_TOKEN(Minus) NAZARA_SHADERLANG_TOKEN(Plus) +NAZARA_SHADERLANG_TOKEN(OpenAttribute) NAZARA_SHADERLANG_TOKEN(OpenCurlyBracket) +NAZARA_SHADERLANG_TOKEN(OpenSquareBracket) NAZARA_SHADERLANG_TOKEN(OpenParenthesis) NAZARA_SHADERLANG_TOKEN(Semicolon) NAZARA_SHADERLANG_TOKEN(Return) diff --git a/src/Nazara/Shader/ShaderLangLexer.cpp b/src/Nazara/Shader/ShaderLangLexer.cpp index 666b0d8d6..3ffd284f4 100644 --- a/src/Nazara/Shader/ShaderLangLexer.cpp +++ b/src/Nazara/Shader/ShaderLangLexer.cpp @@ -221,6 +221,28 @@ namespace Nz::ShaderLang break; } + case '[': + { + char next = Peek(); + if (next == '[') + tokenType = TokenType::OpenAttribute; + else + tokenType = TokenType::OpenSquareBracket; + + break; + } + + case ']': + { + char next = Peek(); + if (next == ']') + tokenType = TokenType::ClosingAttribute; + else + tokenType = TokenType::ClosingSquareBracket; + + break; + } + case '=': tokenType = TokenType::Assign; break; case '+': tokenType = TokenType::Plus; break; case '*': tokenType = TokenType::Multiply; break; From da81a5b871fdc1c733dab199664e81739a03b922 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 11 Mar 2021 23:20:06 +0100 Subject: [PATCH 081/278] Shader: Add attribute parsing --- include/Nazara/Shader/ShaderEnums.hpp | 6 ++ include/Nazara/Shader/ShaderLangParser.hpp | 11 +++ include/Nazara/Shader/ShaderNodes.hpp | 8 +- src/Nazara/Shader/ShaderLangParser.cpp | 98 +++++++++++++++++++--- 4 files changed, 110 insertions(+), 13 deletions(-) diff --git a/include/Nazara/Shader/ShaderEnums.hpp b/include/Nazara/Shader/ShaderEnums.hpp index f5182c243..5c2d3136d 100644 --- a/include/Nazara/Shader/ShaderEnums.hpp +++ b/include/Nazara/Shader/ShaderEnums.hpp @@ -16,6 +16,12 @@ namespace Nz::ShaderAst Simple //< = }; + enum class AttributeType + { + Entry, //< Entry point (function only) - has argument type + Layout //< Struct layout (struct only) - has argument style + }; + enum class BasicType { Boolean, //< bool diff --git a/include/Nazara/Shader/ShaderLangParser.hpp b/include/Nazara/Shader/ShaderLangParser.hpp index 4c0e12d86..785136702 100644 --- a/include/Nazara/Shader/ShaderLangParser.hpp +++ b/include/Nazara/Shader/ShaderLangParser.hpp @@ -25,6 +25,12 @@ namespace Nz::ShaderLang public: using exception::exception; }; + + class UnknownAttribute : public std::exception + { + public: + using exception::exception; + }; class UnknownType : public std::exception { @@ -49,10 +55,13 @@ namespace Nz::ShaderLang private: // Flow control const Token& Advance(); + void Consume(std::size_t count = 1); const Token& Expect(const Token& token, TokenType type); const Token& Expect(TokenType type); const Token& Peek(std::size_t advance = 0); + std::vector ParseAttributes(); + // Statements std::vector ParseFunctionBody(); ShaderAst::StatementPtr ParseFunctionDeclaration(); @@ -70,6 +79,7 @@ namespace Nz::ShaderLang ShaderAst::ExpressionPtr ParseParenthesisExpression(); ShaderAst::ExpressionPtr ParsePrimaryExpression(); + ShaderAst::AttributeType ParseIdentifierAsAttributeType(); const std::string& ParseIdentifierAsName(); ShaderAst::ShaderExpressionType ParseIdentifierAsType(); @@ -77,6 +87,7 @@ namespace Nz::ShaderLang struct Context { + std::vector pendingAttributes; std::unique_ptr root; std::size_t tokenCount; std::size_t tokenIndex = 0; diff --git a/include/Nazara/Shader/ShaderNodes.hpp b/include/Nazara/Shader/ShaderNodes.hpp index 7aeef561c..4e532ad14 100644 --- a/include/Nazara/Shader/ShaderNodes.hpp +++ b/include/Nazara/Shader/ShaderNodes.hpp @@ -12,9 +12,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -25,6 +25,12 @@ namespace Nz::ShaderAst class AstExpressionVisitor; class AstStatementVisitor; + struct Attribute + { + AttributeType type; + std::string args; + }; + struct NAZARA_SHADER_API Node { Node() = default; diff --git a/src/Nazara/Shader/ShaderLangParser.cpp b/src/Nazara/Shader/ShaderLangParser.cpp index d4ecbf0d5..4cd73eedc 100644 --- a/src/Nazara/Shader/ShaderLangParser.cpp +++ b/src/Nazara/Shader/ShaderLangParser.cpp @@ -33,6 +33,11 @@ namespace Nz::ShaderLang { "vec3u32", ShaderAst::BasicType::UInt3 }, { "vec4u32", ShaderAst::BasicType::UInt4 }, }; + + std::unordered_map identifierToAttributeType = { + { "entry", ShaderAst::AttributeType::Entry }, + { "layout", ShaderAst::AttributeType::Layout }, + }; } ShaderAst::StatementPtr Parser::Parse(const std::vector& tokens) @@ -51,6 +56,10 @@ namespace Nz::ShaderLang const Token& nextToken = Peek(); switch (nextToken.type) { + case TokenType::OpenAttribute: + context.pendingAttributes = ParseAttributes(); + break; + case TokenType::FunctionDeclaration: context.root->statements.push_back(ParseFunctionDeclaration()); break; @@ -75,6 +84,12 @@ namespace Nz::ShaderLang return token; } + void Parser::Consume(std::size_t count) + { + assert(m_context->tokenIndex + count < m_context->tokenCount); + m_context->tokenIndex += count; + } + const Token& Parser::Expect(const Token& token, TokenType type) { if (token.type != type) @@ -97,6 +112,58 @@ namespace Nz::ShaderLang return m_context->tokens[m_context->tokenIndex + advance]; } + std::vector Parser::ParseAttributes() + { + std::vector attributes; + + Expect(Advance(), TokenType::OpenAttribute); + + bool expectComma = false; + for (;;) + { + const Token& t = Peek(); + if (t.type == TokenType::ClosingAttribute) + { + // Parse [[attribute1]] [[attribute2]] the same as [[attribute1, attribute2]] + if (Peek(1).type == TokenType::OpenAttribute) + { + Consume(2); + expectComma = false; + continue; + } + + break; + } + + if (expectComma) + Expect(Advance(), TokenType::Comma); + + ShaderAst::AttributeType attributeType = ParseIdentifierAsAttributeType(); + + std::string arg; + if (Peek().type == TokenType::OpenParenthesis) + { + Consume(); + + if (Peek().type == TokenType::Identifier) + arg = std::get(Advance().data); + + Expect(Advance(), TokenType::ClosingParenthesis); + } + + expectComma = true; + + attributes.push_back({ + attributeType, + std::move(arg) + }); + } + + Expect(Advance(), TokenType::ClosingAttribute); + + return attributes; + } + std::vector Parser::ParseFunctionBody() { return ParseStatementList(); @@ -120,10 +187,7 @@ namespace Nz::ShaderLang break; if (!firstParameter) - { - Expect(t, TokenType::Comma); - Advance(); - } + Expect(Advance(), TokenType::Comma); parameters.push_back(ParseFunctionParameter()); firstParameter = false; @@ -134,8 +198,7 @@ namespace Nz::ShaderLang ShaderAst::ShaderExpressionType returnType = ShaderAst::BasicType::Void; if (Peek().type == TokenType::FunctionReturn) { - Advance(); //< Consume -> - + Consume(); returnType = ParseIdentifierAsType(); } @@ -218,7 +281,7 @@ namespace Nz::ShaderLang ShaderAst::ExpressionPtr expression; if (Peek().type == TokenType::Assign) { - Advance(); + Consume(); expression = ParseExpression(); } @@ -235,7 +298,7 @@ namespace Nz::ShaderLang if (tokenPrecedence < exprPrecedence) return lhs; - Advance(); + Consume(); ShaderAst::ExpressionPtr rhs = ParsePrimaryExpression(); const Token& nextOp = Peek(); @@ -255,7 +318,6 @@ namespace Nz::ShaderLang default: throw UnexpectedToken{}; } } - lhs = ShaderBuilder::Binary(binaryType, std::move(lhs), std::move(rhs)); } @@ -295,15 +357,15 @@ namespace Nz::ShaderLang switch (token.type) { case TokenType::BoolFalse: - Advance(); + Consume(); return ShaderBuilder::Constant(false); case TokenType::BoolTrue: - Advance(); + Consume(); return ShaderBuilder::Constant(true); case TokenType::FloatingPointValue: - Advance(); + Consume(); return ShaderBuilder::Constant(float(std::get(token.data))); //< FIXME case TokenType::Identifier: @@ -320,6 +382,18 @@ namespace Nz::ShaderLang } } + ShaderAst::AttributeType Parser::ParseIdentifierAsAttributeType() + { + const Token& identifierToken = Expect(Advance(), TokenType::Identifier); + const std::string& identifier = std::get(identifierToken.data); + + auto it = identifierToAttributeType.find(identifier); + if (it == identifierToAttributeType.end()) + throw UnknownAttribute{}; + + return it->second; + } + const std::string& Parser::ParseIdentifierAsName() { const Token& identifierToken = Expect(Advance(), TokenType::Identifier); From 5598487e87ab9350c3fefa6cd4596c7fed272fe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 11 Mar 2021 23:20:22 +0100 Subject: [PATCH 082/278] ShaderLang: Improve lexer --- src/Nazara/Shader/ShaderLangLexer.cpp | 41 ++++++++++++++++----------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/src/Nazara/Shader/ShaderLangLexer.cpp b/src/Nazara/Shader/ShaderLangLexer.cpp index 3ffd284f4..93b6bda1c 100644 --- a/src/Nazara/Shader/ShaderLangLexer.cpp +++ b/src/Nazara/Shader/ShaderLangLexer.cpp @@ -100,6 +100,7 @@ namespace Nz::ShaderLang { if (Peek() == '>') { + currentPos++; tokenType = TokenType::FunctionReturn; break; } @@ -225,7 +226,10 @@ namespace Nz::ShaderLang { char next = Peek(); if (next == '[') + { + currentPos++; tokenType = TokenType::OpenAttribute; + } else tokenType = TokenType::OpenSquareBracket; @@ -236,7 +240,10 @@ namespace Nz::ShaderLang { char next = Peek(); if (next == ']') + { + currentPos++; tokenType = TokenType::ClosingAttribute; + } else tokenType = TokenType::ClosingSquareBracket; @@ -255,26 +262,28 @@ namespace Nz::ShaderLang case '(': tokenType = TokenType::OpenParenthesis; break; case ')': tokenType = TokenType::ClosingParenthesis; break; - default: break; - } - - if (!tokenType) - { - if (IsAlphaNum(c)) + default: { - std::size_t start = currentPos; - - while (IsAlphaNum(Peek())) - currentPos++; - - std::string identifier(str.substr(start, currentPos - start + 1)); - if (auto it = reservedKeywords.find(identifier); it == reservedKeywords.end()) + if (IsAlphaNum(c)) { - tokenType = TokenType::Identifier; - token.data = std::move(identifier); + std::size_t start = currentPos; + + while (IsAlphaNum(Peek())) + currentPos++; + + std::string identifier(str.substr(start, currentPos - start + 1)); + if (auto it = reservedKeywords.find(identifier); it == reservedKeywords.end()) + { + tokenType = TokenType::Identifier; + token.data = std::move(identifier); + } + else + tokenType = it->second; + + break; } else - tokenType = it->second; + throw UnrecognizedToken{}; } } From f694eb767fbc5bcf1d47862d7fb485aaf623e01e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 11 Mar 2021 23:20:35 +0100 Subject: [PATCH 083/278] Shader: Fix return type not being properly registered --- src/Nazara/Shader/SpirvConstantCache.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nazara/Shader/SpirvConstantCache.cpp b/src/Nazara/Shader/SpirvConstantCache.cpp index 97d40a509..6146c29e5 100644 --- a/src/Nazara/Shader/SpirvConstantCache.cpp +++ b/src/Nazara/Shader/SpirvConstantCache.cpp @@ -233,7 +233,7 @@ namespace Nz void Register(const Function& func) { - Register(func.returnType); + cache.Register(*func.returnType); Register(func.parameters); } From 593d80c80ec3b81aa055fa76ea8c97e11488cf00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sat, 13 Mar 2021 15:59:41 +0100 Subject: [PATCH 084/278] SpirV grammar parser: Add result id operand and version info --- build/scripts/actions/spirv.lua | 29 +- include/Nazara/Shader/SpirvData.hpp | 11 + src/Nazara/Shader/SpirvData.cpp | 916 +++++++++++++++++++++++----- 3 files changed, 800 insertions(+), 156 deletions(-) diff --git a/build/scripts/actions/spirv.lua b/build/scripts/actions/spirv.lua index 6843e548a..432acc0d0 100644 --- a/build/scripts/actions/spirv.lua +++ b/build/scripts/actions/spirv.lua @@ -15,6 +15,8 @@ ACTION.Function = function() print("Done") + io.write("Parsing... ") + local result, err = json.decode(content) assert(result, err) @@ -34,16 +36,26 @@ ACTION.Function = function() local operandByInstruction = {} for _, instruction in pairs(instructions) do if (instruction.operands) then + local resultId local firstId = #operands local operandCount = #instruction.operands - for _, operand in pairs(instruction.operands) do + for i, operand in pairs(instruction.operands) do table.insert(operands, operand) + + if (operand.kind == "IdResult") then + assert(not resultId, "unexpected operand with two IdResult") + resultId = i - 1 + end end - operandByInstruction[instruction.opcode] = { firstId = firstId, count = operandCount } + operandByInstruction[instruction.opcode] = { firstId = firstId, count = operandCount, resultId = resultId } end end + print("Done") + + io.write("Generating... ") + local headerFile = io.open("../include/Nazara/Shader/SpirvData.hpp", "w+") assert(headerFile, "failed to open Spir-V header") @@ -65,6 +77,15 @@ ACTION.Function = function() namespace Nz { +]]) + + headerFile:write([[ + constexpr UInt32 SpirvMagicNumber = ]] .. result.magic_number .. [[; + constexpr UInt32 SpirvMajorVersion = ]] .. result.major_version .. [[; + constexpr UInt32 SpirvMinorVersion = ]] .. result.minor_version .. [[; + constexpr UInt32 SpirvRevision = ]] .. result.revision .. [[; + constexpr UInt32 SpirvVersion = (SpirvMajorVersion << 16) | (SpirvMinorVersion << 8); + ]]) -- SpirV operations @@ -155,6 +176,7 @@ headerFile:write([[ SpirvOp op; const char* name; const Operand* operands; + const Operand* resultOperand; std::size_t minOperandCount; }; @@ -210,12 +232,14 @@ namespace Nz for _, instruction in pairs(instructions) do local opByInstruction = operandByInstruction[instruction.opcode] + local resultId = opByInstruction and opByInstruction.resultId or nil sourceFile:write([[ { SpirvOp::]] .. instruction.opname .. [[, R"(]] .. instruction.opname .. [[)", ]] .. (opByInstruction and "&s_operands[" .. opByInstruction.firstId .. "]" or "nullptr") .. [[, + ]] .. (resultId and "&s_operands[" .. opByInstruction.firstId + resultId .. "]" or "nullptr") .. [[, ]] .. (opByInstruction and opByInstruction.count or "0") .. [[, }, ]]) @@ -243,4 +267,5 @@ namespace Nz } ]]) + print("Done") end diff --git a/include/Nazara/Shader/SpirvData.hpp b/include/Nazara/Shader/SpirvData.hpp index 3295d2edb..aaacc4631 100644 --- a/include/Nazara/Shader/SpirvData.hpp +++ b/include/Nazara/Shader/SpirvData.hpp @@ -15,6 +15,12 @@ namespace Nz { + constexpr UInt32 SpirvMagicNumber = 0x07230203; + constexpr UInt32 SpirvMajorVersion = 1; + constexpr UInt32 SpirvMinorVersion = 5; + constexpr UInt32 SpirvRevision = 4; + constexpr UInt32 SpirvVersion = (SpirvMajorVersion << 16) | (SpirvMinorVersion << 8); + enum class SpirvOp { OpNop = 0, @@ -442,6 +448,8 @@ namespace Nz OpAsmCallINTEL = 5611, OpAtomicFMinEXT = 5614, OpAtomicFMaxEXT = 5615, + OpAssumeTrueKHR = 5630, + OpExpectKHR = 5631, OpDecorateString = 5632, OpDecorateStringGOOGLE = 5632, OpMemberDecorateString = 5633, @@ -1178,6 +1186,7 @@ namespace Nz { Export = 0, Import = 1, + LinkOnceODR = 2, }; enum class SpirvAccessQualifier @@ -1636,6 +1645,7 @@ namespace Nz AtomicFloat16MinMaxEXT = 5616, VectorComputeINTEL = 5617, VectorAnyINTEL = 5619, + ExpectAssumeKHR = 5629, SubgroupAvcMotionEstimationINTEL = 5696, SubgroupAvcMotionEstimationIntraINTEL = 5697, SubgroupAvcMotionEstimationChromaINTEL = 5698, @@ -1691,6 +1701,7 @@ namespace Nz SpirvOp op; const char* name; const Operand* operands; + const Operand* resultOperand; std::size_t minOperandCount; }; diff --git a/src/Nazara/Shader/SpirvData.cpp b/src/Nazara/Shader/SpirvData.cpp index 5bb2f2794..c0c333eeb 100644 --- a/src/Nazara/Shader/SpirvData.cpp +++ b/src/Nazara/Shader/SpirvData.cpp @@ -11,7 +11,7 @@ namespace Nz { - static constexpr std::array s_operands = { + static constexpr std::array s_operands = { { { SpirvOperandKind::IdResultType, @@ -5779,7 +5779,7 @@ namespace Nz }, { SpirvOperandKind::IdScope, - R"('Execution')" + R"('Scope')" }, { SpirvOperandKind::IdResultType, @@ -6509,6 +6509,26 @@ namespace Nz SpirvOperandKind::IdRef, R"('Value')" }, + { + SpirvOperandKind::IdRef, + R"('Condition')" + }, + { + SpirvOperandKind::IdResultType, + R"(IdResultType)" + }, + { + SpirvOperandKind::IdResult, + R"(IdResult)" + }, + { + SpirvOperandKind::IdRef, + R"('Value')" + }, + { + SpirvOperandKind::IdRef, + R"('ExpectedValue')" + }, { SpirvOperandKind::IdRef, R"('Target')" @@ -8746,3450 +8766,4038 @@ namespace Nz } }; - static std::array s_instructions = { + static std::array s_instructions = { { { SpirvOp::OpNop, R"(OpNop)", nullptr, + nullptr, 0, }, { SpirvOp::OpUndef, R"(OpUndef)", &s_operands[0], + &s_operands[1], 2, }, { SpirvOp::OpSourceContinued, R"(OpSourceContinued)", &s_operands[2], + nullptr, 1, }, { SpirvOp::OpSource, R"(OpSource)", &s_operands[3], + nullptr, 4, }, { SpirvOp::OpSourceExtension, R"(OpSourceExtension)", &s_operands[7], + nullptr, 1, }, { SpirvOp::OpName, R"(OpName)", &s_operands[8], + nullptr, 2, }, { SpirvOp::OpMemberName, R"(OpMemberName)", &s_operands[10], + nullptr, 3, }, { SpirvOp::OpString, R"(OpString)", &s_operands[13], + &s_operands[13], 2, }, { SpirvOp::OpLine, R"(OpLine)", &s_operands[15], + nullptr, 3, }, { SpirvOp::OpExtension, R"(OpExtension)", &s_operands[18], + nullptr, 1, }, { SpirvOp::OpExtInstImport, R"(OpExtInstImport)", &s_operands[19], + &s_operands[19], 2, }, { SpirvOp::OpExtInst, R"(OpExtInst)", &s_operands[21], + &s_operands[22], 5, }, { SpirvOp::OpMemoryModel, R"(OpMemoryModel)", &s_operands[26], + nullptr, 2, }, { SpirvOp::OpEntryPoint, R"(OpEntryPoint)", &s_operands[28], + nullptr, 4, }, { SpirvOp::OpExecutionMode, R"(OpExecutionMode)", &s_operands[32], + nullptr, 2, }, { SpirvOp::OpCapability, R"(OpCapability)", &s_operands[34], + nullptr, 1, }, { SpirvOp::OpTypeVoid, R"(OpTypeVoid)", &s_operands[35], + &s_operands[35], 1, }, { SpirvOp::OpTypeBool, R"(OpTypeBool)", &s_operands[36], + &s_operands[36], 1, }, { SpirvOp::OpTypeInt, R"(OpTypeInt)", &s_operands[37], + &s_operands[37], 3, }, { SpirvOp::OpTypeFloat, R"(OpTypeFloat)", &s_operands[40], + &s_operands[40], 2, }, { SpirvOp::OpTypeVector, R"(OpTypeVector)", &s_operands[42], + &s_operands[42], 3, }, { SpirvOp::OpTypeMatrix, R"(OpTypeMatrix)", &s_operands[45], + &s_operands[45], 3, }, { SpirvOp::OpTypeImage, R"(OpTypeImage)", &s_operands[48], + &s_operands[48], 9, }, { SpirvOp::OpTypeSampler, R"(OpTypeSampler)", &s_operands[57], + &s_operands[57], 1, }, { SpirvOp::OpTypeSampledImage, R"(OpTypeSampledImage)", &s_operands[58], + &s_operands[58], 2, }, { SpirvOp::OpTypeArray, R"(OpTypeArray)", &s_operands[60], + &s_operands[60], 3, }, { SpirvOp::OpTypeRuntimeArray, R"(OpTypeRuntimeArray)", &s_operands[63], + &s_operands[63], 2, }, { SpirvOp::OpTypeStruct, R"(OpTypeStruct)", &s_operands[65], + &s_operands[65], 2, }, { SpirvOp::OpTypeOpaque, R"(OpTypeOpaque)", &s_operands[67], + &s_operands[67], 2, }, { SpirvOp::OpTypePointer, R"(OpTypePointer)", &s_operands[69], + &s_operands[69], 3, }, { SpirvOp::OpTypeFunction, R"(OpTypeFunction)", &s_operands[72], + &s_operands[72], 3, }, { SpirvOp::OpTypeEvent, R"(OpTypeEvent)", &s_operands[75], + &s_operands[75], 1, }, { SpirvOp::OpTypeDeviceEvent, R"(OpTypeDeviceEvent)", &s_operands[76], + &s_operands[76], 1, }, { SpirvOp::OpTypeReserveId, R"(OpTypeReserveId)", &s_operands[77], + &s_operands[77], 1, }, { SpirvOp::OpTypeQueue, R"(OpTypeQueue)", &s_operands[78], + &s_operands[78], 1, }, { SpirvOp::OpTypePipe, R"(OpTypePipe)", &s_operands[79], + &s_operands[79], 2, }, { SpirvOp::OpTypeForwardPointer, R"(OpTypeForwardPointer)", &s_operands[81], + nullptr, 2, }, { SpirvOp::OpConstantTrue, R"(OpConstantTrue)", &s_operands[83], + &s_operands[84], 2, }, { SpirvOp::OpConstantFalse, R"(OpConstantFalse)", &s_operands[85], + &s_operands[86], 2, }, { SpirvOp::OpConstant, R"(OpConstant)", &s_operands[87], + &s_operands[88], 3, }, { SpirvOp::OpConstantComposite, R"(OpConstantComposite)", &s_operands[90], + &s_operands[91], 3, }, { SpirvOp::OpConstantSampler, R"(OpConstantSampler)", &s_operands[93], + &s_operands[94], 5, }, { SpirvOp::OpConstantNull, R"(OpConstantNull)", &s_operands[98], + &s_operands[99], 2, }, { SpirvOp::OpSpecConstantTrue, R"(OpSpecConstantTrue)", &s_operands[100], + &s_operands[101], 2, }, { SpirvOp::OpSpecConstantFalse, R"(OpSpecConstantFalse)", &s_operands[102], + &s_operands[103], 2, }, { SpirvOp::OpSpecConstant, R"(OpSpecConstant)", &s_operands[104], + &s_operands[105], 3, }, { SpirvOp::OpSpecConstantComposite, R"(OpSpecConstantComposite)", &s_operands[107], + &s_operands[108], 3, }, { SpirvOp::OpSpecConstantOp, R"(OpSpecConstantOp)", &s_operands[110], + &s_operands[111], 3, }, { SpirvOp::OpFunction, R"(OpFunction)", &s_operands[113], + &s_operands[114], 4, }, { SpirvOp::OpFunctionParameter, R"(OpFunctionParameter)", &s_operands[117], + &s_operands[118], 2, }, { SpirvOp::OpFunctionEnd, R"(OpFunctionEnd)", nullptr, + nullptr, 0, }, { SpirvOp::OpFunctionCall, R"(OpFunctionCall)", &s_operands[119], + &s_operands[120], 4, }, { SpirvOp::OpVariable, R"(OpVariable)", &s_operands[123], + &s_operands[124], 4, }, { SpirvOp::OpImageTexelPointer, R"(OpImageTexelPointer)", &s_operands[127], + &s_operands[128], 5, }, { SpirvOp::OpLoad, R"(OpLoad)", &s_operands[132], + &s_operands[133], 4, }, { SpirvOp::OpStore, R"(OpStore)", &s_operands[136], + nullptr, 3, }, { SpirvOp::OpCopyMemory, R"(OpCopyMemory)", &s_operands[139], + nullptr, 4, }, { SpirvOp::OpCopyMemorySized, R"(OpCopyMemorySized)", &s_operands[143], + nullptr, 5, }, { SpirvOp::OpAccessChain, R"(OpAccessChain)", &s_operands[148], + &s_operands[149], 4, }, { SpirvOp::OpInBoundsAccessChain, R"(OpInBoundsAccessChain)", &s_operands[152], + &s_operands[153], 4, }, { SpirvOp::OpPtrAccessChain, R"(OpPtrAccessChain)", &s_operands[156], + &s_operands[157], 5, }, { SpirvOp::OpArrayLength, R"(OpArrayLength)", &s_operands[161], + &s_operands[162], 4, }, { SpirvOp::OpGenericPtrMemSemantics, R"(OpGenericPtrMemSemantics)", &s_operands[165], + &s_operands[166], 3, }, { SpirvOp::OpInBoundsPtrAccessChain, R"(OpInBoundsPtrAccessChain)", &s_operands[168], + &s_operands[169], 5, }, { SpirvOp::OpDecorate, R"(OpDecorate)", &s_operands[173], + nullptr, 2, }, { SpirvOp::OpMemberDecorate, R"(OpMemberDecorate)", &s_operands[175], + nullptr, 3, }, { SpirvOp::OpDecorationGroup, R"(OpDecorationGroup)", &s_operands[178], + &s_operands[178], 1, }, { SpirvOp::OpGroupDecorate, R"(OpGroupDecorate)", &s_operands[179], + nullptr, 2, }, { SpirvOp::OpGroupMemberDecorate, R"(OpGroupMemberDecorate)", &s_operands[181], + nullptr, 2, }, { SpirvOp::OpVectorExtractDynamic, R"(OpVectorExtractDynamic)", &s_operands[183], + &s_operands[184], 4, }, { SpirvOp::OpVectorInsertDynamic, R"(OpVectorInsertDynamic)", &s_operands[187], + &s_operands[188], 5, }, { SpirvOp::OpVectorShuffle, R"(OpVectorShuffle)", &s_operands[192], + &s_operands[193], 5, }, { SpirvOp::OpCompositeConstruct, R"(OpCompositeConstruct)", &s_operands[197], + &s_operands[198], 3, }, { SpirvOp::OpCompositeExtract, R"(OpCompositeExtract)", &s_operands[200], + &s_operands[201], 4, }, { SpirvOp::OpCompositeInsert, R"(OpCompositeInsert)", &s_operands[204], + &s_operands[205], 5, }, { SpirvOp::OpCopyObject, R"(OpCopyObject)", &s_operands[209], + &s_operands[210], 3, }, { SpirvOp::OpTranspose, R"(OpTranspose)", &s_operands[212], + &s_operands[213], 3, }, { SpirvOp::OpSampledImage, R"(OpSampledImage)", &s_operands[215], + &s_operands[216], 4, }, { SpirvOp::OpImageSampleImplicitLod, R"(OpImageSampleImplicitLod)", &s_operands[219], + &s_operands[220], 5, }, { SpirvOp::OpImageSampleExplicitLod, R"(OpImageSampleExplicitLod)", &s_operands[224], + &s_operands[225], 5, }, { SpirvOp::OpImageSampleDrefImplicitLod, R"(OpImageSampleDrefImplicitLod)", &s_operands[229], + &s_operands[230], 6, }, { SpirvOp::OpImageSampleDrefExplicitLod, R"(OpImageSampleDrefExplicitLod)", &s_operands[235], + &s_operands[236], 6, }, { SpirvOp::OpImageSampleProjImplicitLod, R"(OpImageSampleProjImplicitLod)", &s_operands[241], + &s_operands[242], 5, }, { SpirvOp::OpImageSampleProjExplicitLod, R"(OpImageSampleProjExplicitLod)", &s_operands[246], + &s_operands[247], 5, }, { SpirvOp::OpImageSampleProjDrefImplicitLod, R"(OpImageSampleProjDrefImplicitLod)", &s_operands[251], + &s_operands[252], 6, }, { SpirvOp::OpImageSampleProjDrefExplicitLod, R"(OpImageSampleProjDrefExplicitLod)", &s_operands[257], + &s_operands[258], 6, }, { SpirvOp::OpImageFetch, R"(OpImageFetch)", &s_operands[263], + &s_operands[264], 5, }, { SpirvOp::OpImageGather, R"(OpImageGather)", &s_operands[268], + &s_operands[269], 6, }, { SpirvOp::OpImageDrefGather, R"(OpImageDrefGather)", &s_operands[274], + &s_operands[275], 6, }, { SpirvOp::OpImageRead, R"(OpImageRead)", &s_operands[280], + &s_operands[281], 5, }, { SpirvOp::OpImageWrite, R"(OpImageWrite)", &s_operands[285], + nullptr, 4, }, { SpirvOp::OpImage, R"(OpImage)", &s_operands[289], + &s_operands[290], 3, }, { SpirvOp::OpImageQueryFormat, R"(OpImageQueryFormat)", &s_operands[292], + &s_operands[293], 3, }, { SpirvOp::OpImageQueryOrder, R"(OpImageQueryOrder)", &s_operands[295], + &s_operands[296], 3, }, { SpirvOp::OpImageQuerySizeLod, R"(OpImageQuerySizeLod)", &s_operands[298], + &s_operands[299], 4, }, { SpirvOp::OpImageQuerySize, R"(OpImageQuerySize)", &s_operands[302], + &s_operands[303], 3, }, { SpirvOp::OpImageQueryLod, R"(OpImageQueryLod)", &s_operands[305], + &s_operands[306], 4, }, { SpirvOp::OpImageQueryLevels, R"(OpImageQueryLevels)", &s_operands[309], + &s_operands[310], 3, }, { SpirvOp::OpImageQuerySamples, R"(OpImageQuerySamples)", &s_operands[312], + &s_operands[313], 3, }, { SpirvOp::OpConvertFToU, R"(OpConvertFToU)", &s_operands[315], + &s_operands[316], 3, }, { SpirvOp::OpConvertFToS, R"(OpConvertFToS)", &s_operands[318], + &s_operands[319], 3, }, { SpirvOp::OpConvertSToF, R"(OpConvertSToF)", &s_operands[321], + &s_operands[322], 3, }, { SpirvOp::OpConvertUToF, R"(OpConvertUToF)", &s_operands[324], + &s_operands[325], 3, }, { SpirvOp::OpUConvert, R"(OpUConvert)", &s_operands[327], + &s_operands[328], 3, }, { SpirvOp::OpSConvert, R"(OpSConvert)", &s_operands[330], + &s_operands[331], 3, }, { SpirvOp::OpFConvert, R"(OpFConvert)", &s_operands[333], + &s_operands[334], 3, }, { SpirvOp::OpQuantizeToF16, R"(OpQuantizeToF16)", &s_operands[336], + &s_operands[337], 3, }, { SpirvOp::OpConvertPtrToU, R"(OpConvertPtrToU)", &s_operands[339], + &s_operands[340], 3, }, { SpirvOp::OpSatConvertSToU, R"(OpSatConvertSToU)", &s_operands[342], + &s_operands[343], 3, }, { SpirvOp::OpSatConvertUToS, R"(OpSatConvertUToS)", &s_operands[345], + &s_operands[346], 3, }, { SpirvOp::OpConvertUToPtr, R"(OpConvertUToPtr)", &s_operands[348], + &s_operands[349], 3, }, { SpirvOp::OpPtrCastToGeneric, R"(OpPtrCastToGeneric)", &s_operands[351], + &s_operands[352], 3, }, { SpirvOp::OpGenericCastToPtr, R"(OpGenericCastToPtr)", &s_operands[354], + &s_operands[355], 3, }, { SpirvOp::OpGenericCastToPtrExplicit, R"(OpGenericCastToPtrExplicit)", &s_operands[357], + &s_operands[358], 4, }, { SpirvOp::OpBitcast, R"(OpBitcast)", &s_operands[361], + &s_operands[362], 3, }, { SpirvOp::OpSNegate, R"(OpSNegate)", &s_operands[364], + &s_operands[365], 3, }, { SpirvOp::OpFNegate, R"(OpFNegate)", &s_operands[367], + &s_operands[368], 3, }, { SpirvOp::OpIAdd, R"(OpIAdd)", &s_operands[370], + &s_operands[371], 4, }, { SpirvOp::OpFAdd, R"(OpFAdd)", &s_operands[374], + &s_operands[375], 4, }, { SpirvOp::OpISub, R"(OpISub)", &s_operands[378], + &s_operands[379], 4, }, { SpirvOp::OpFSub, R"(OpFSub)", &s_operands[382], + &s_operands[383], 4, }, { SpirvOp::OpIMul, R"(OpIMul)", &s_operands[386], + &s_operands[387], 4, }, { SpirvOp::OpFMul, R"(OpFMul)", &s_operands[390], + &s_operands[391], 4, }, { SpirvOp::OpUDiv, R"(OpUDiv)", &s_operands[394], + &s_operands[395], 4, }, { SpirvOp::OpSDiv, R"(OpSDiv)", &s_operands[398], + &s_operands[399], 4, }, { SpirvOp::OpFDiv, R"(OpFDiv)", &s_operands[402], + &s_operands[403], 4, }, { SpirvOp::OpUMod, R"(OpUMod)", &s_operands[406], + &s_operands[407], 4, }, { SpirvOp::OpSRem, R"(OpSRem)", &s_operands[410], + &s_operands[411], 4, }, { SpirvOp::OpSMod, R"(OpSMod)", &s_operands[414], + &s_operands[415], 4, }, { SpirvOp::OpFRem, R"(OpFRem)", &s_operands[418], + &s_operands[419], 4, }, { SpirvOp::OpFMod, R"(OpFMod)", &s_operands[422], + &s_operands[423], 4, }, { SpirvOp::OpVectorTimesScalar, R"(OpVectorTimesScalar)", &s_operands[426], + &s_operands[427], 4, }, { SpirvOp::OpMatrixTimesScalar, R"(OpMatrixTimesScalar)", &s_operands[430], + &s_operands[431], 4, }, { SpirvOp::OpVectorTimesMatrix, R"(OpVectorTimesMatrix)", &s_operands[434], + &s_operands[435], 4, }, { SpirvOp::OpMatrixTimesVector, R"(OpMatrixTimesVector)", &s_operands[438], + &s_operands[439], 4, }, { SpirvOp::OpMatrixTimesMatrix, R"(OpMatrixTimesMatrix)", &s_operands[442], + &s_operands[443], 4, }, { SpirvOp::OpOuterProduct, R"(OpOuterProduct)", &s_operands[446], + &s_operands[447], 4, }, { SpirvOp::OpDot, R"(OpDot)", &s_operands[450], + &s_operands[451], 4, }, { SpirvOp::OpIAddCarry, R"(OpIAddCarry)", &s_operands[454], + &s_operands[455], 4, }, { SpirvOp::OpISubBorrow, R"(OpISubBorrow)", &s_operands[458], + &s_operands[459], 4, }, { SpirvOp::OpUMulExtended, R"(OpUMulExtended)", &s_operands[462], + &s_operands[463], 4, }, { SpirvOp::OpSMulExtended, R"(OpSMulExtended)", &s_operands[466], + &s_operands[467], 4, }, { SpirvOp::OpAny, R"(OpAny)", &s_operands[470], + &s_operands[471], 3, }, { SpirvOp::OpAll, R"(OpAll)", &s_operands[473], + &s_operands[474], 3, }, { SpirvOp::OpIsNan, R"(OpIsNan)", &s_operands[476], + &s_operands[477], 3, }, { SpirvOp::OpIsInf, R"(OpIsInf)", &s_operands[479], + &s_operands[480], 3, }, { SpirvOp::OpIsFinite, R"(OpIsFinite)", &s_operands[482], + &s_operands[483], 3, }, { SpirvOp::OpIsNormal, R"(OpIsNormal)", &s_operands[485], + &s_operands[486], 3, }, { SpirvOp::OpSignBitSet, R"(OpSignBitSet)", &s_operands[488], + &s_operands[489], 3, }, { SpirvOp::OpLessOrGreater, R"(OpLessOrGreater)", &s_operands[491], + &s_operands[492], 4, }, { SpirvOp::OpOrdered, R"(OpOrdered)", &s_operands[495], + &s_operands[496], 4, }, { SpirvOp::OpUnordered, R"(OpUnordered)", &s_operands[499], + &s_operands[500], 4, }, { SpirvOp::OpLogicalEqual, R"(OpLogicalEqual)", &s_operands[503], + &s_operands[504], 4, }, { SpirvOp::OpLogicalNotEqual, R"(OpLogicalNotEqual)", &s_operands[507], + &s_operands[508], 4, }, { SpirvOp::OpLogicalOr, R"(OpLogicalOr)", &s_operands[511], + &s_operands[512], 4, }, { SpirvOp::OpLogicalAnd, R"(OpLogicalAnd)", &s_operands[515], + &s_operands[516], 4, }, { SpirvOp::OpLogicalNot, R"(OpLogicalNot)", &s_operands[519], + &s_operands[520], 3, }, { SpirvOp::OpSelect, R"(OpSelect)", &s_operands[522], + &s_operands[523], 5, }, { SpirvOp::OpIEqual, R"(OpIEqual)", &s_operands[527], + &s_operands[528], 4, }, { SpirvOp::OpINotEqual, R"(OpINotEqual)", &s_operands[531], + &s_operands[532], 4, }, { SpirvOp::OpUGreaterThan, R"(OpUGreaterThan)", &s_operands[535], + &s_operands[536], 4, }, { SpirvOp::OpSGreaterThan, R"(OpSGreaterThan)", &s_operands[539], + &s_operands[540], 4, }, { SpirvOp::OpUGreaterThanEqual, R"(OpUGreaterThanEqual)", &s_operands[543], + &s_operands[544], 4, }, { SpirvOp::OpSGreaterThanEqual, R"(OpSGreaterThanEqual)", &s_operands[547], + &s_operands[548], 4, }, { SpirvOp::OpULessThan, R"(OpULessThan)", &s_operands[551], + &s_operands[552], 4, }, { SpirvOp::OpSLessThan, R"(OpSLessThan)", &s_operands[555], + &s_operands[556], 4, }, { SpirvOp::OpULessThanEqual, R"(OpULessThanEqual)", &s_operands[559], + &s_operands[560], 4, }, { SpirvOp::OpSLessThanEqual, R"(OpSLessThanEqual)", &s_operands[563], + &s_operands[564], 4, }, { SpirvOp::OpFOrdEqual, R"(OpFOrdEqual)", &s_operands[567], + &s_operands[568], 4, }, { SpirvOp::OpFUnordEqual, R"(OpFUnordEqual)", &s_operands[571], + &s_operands[572], 4, }, { SpirvOp::OpFOrdNotEqual, R"(OpFOrdNotEqual)", &s_operands[575], + &s_operands[576], 4, }, { SpirvOp::OpFUnordNotEqual, R"(OpFUnordNotEqual)", &s_operands[579], + &s_operands[580], 4, }, { SpirvOp::OpFOrdLessThan, R"(OpFOrdLessThan)", &s_operands[583], + &s_operands[584], 4, }, { SpirvOp::OpFUnordLessThan, R"(OpFUnordLessThan)", &s_operands[587], + &s_operands[588], 4, }, { SpirvOp::OpFOrdGreaterThan, R"(OpFOrdGreaterThan)", &s_operands[591], + &s_operands[592], 4, }, { SpirvOp::OpFUnordGreaterThan, R"(OpFUnordGreaterThan)", &s_operands[595], + &s_operands[596], 4, }, { SpirvOp::OpFOrdLessThanEqual, R"(OpFOrdLessThanEqual)", &s_operands[599], + &s_operands[600], 4, }, { SpirvOp::OpFUnordLessThanEqual, R"(OpFUnordLessThanEqual)", &s_operands[603], + &s_operands[604], 4, }, { SpirvOp::OpFOrdGreaterThanEqual, R"(OpFOrdGreaterThanEqual)", &s_operands[607], + &s_operands[608], 4, }, { SpirvOp::OpFUnordGreaterThanEqual, R"(OpFUnordGreaterThanEqual)", &s_operands[611], + &s_operands[612], 4, }, { SpirvOp::OpShiftRightLogical, R"(OpShiftRightLogical)", &s_operands[615], + &s_operands[616], 4, }, { SpirvOp::OpShiftRightArithmetic, R"(OpShiftRightArithmetic)", &s_operands[619], + &s_operands[620], 4, }, { SpirvOp::OpShiftLeftLogical, R"(OpShiftLeftLogical)", &s_operands[623], + &s_operands[624], 4, }, { SpirvOp::OpBitwiseOr, R"(OpBitwiseOr)", &s_operands[627], + &s_operands[628], 4, }, { SpirvOp::OpBitwiseXor, R"(OpBitwiseXor)", &s_operands[631], + &s_operands[632], 4, }, { SpirvOp::OpBitwiseAnd, R"(OpBitwiseAnd)", &s_operands[635], + &s_operands[636], 4, }, { SpirvOp::OpNot, R"(OpNot)", &s_operands[639], + &s_operands[640], 3, }, { SpirvOp::OpBitFieldInsert, R"(OpBitFieldInsert)", &s_operands[642], + &s_operands[643], 6, }, { SpirvOp::OpBitFieldSExtract, R"(OpBitFieldSExtract)", &s_operands[648], + &s_operands[649], 5, }, { SpirvOp::OpBitFieldUExtract, R"(OpBitFieldUExtract)", &s_operands[653], + &s_operands[654], 5, }, { SpirvOp::OpBitReverse, R"(OpBitReverse)", &s_operands[658], + &s_operands[659], 3, }, { SpirvOp::OpBitCount, R"(OpBitCount)", &s_operands[661], + &s_operands[662], 3, }, { SpirvOp::OpDPdx, R"(OpDPdx)", &s_operands[664], + &s_operands[665], 3, }, { SpirvOp::OpDPdy, R"(OpDPdy)", &s_operands[667], + &s_operands[668], 3, }, { SpirvOp::OpFwidth, R"(OpFwidth)", &s_operands[670], + &s_operands[671], 3, }, { SpirvOp::OpDPdxFine, R"(OpDPdxFine)", &s_operands[673], + &s_operands[674], 3, }, { SpirvOp::OpDPdyFine, R"(OpDPdyFine)", &s_operands[676], + &s_operands[677], 3, }, { SpirvOp::OpFwidthFine, R"(OpFwidthFine)", &s_operands[679], + &s_operands[680], 3, }, { SpirvOp::OpDPdxCoarse, R"(OpDPdxCoarse)", &s_operands[682], + &s_operands[683], 3, }, { SpirvOp::OpDPdyCoarse, R"(OpDPdyCoarse)", &s_operands[685], + &s_operands[686], 3, }, { SpirvOp::OpFwidthCoarse, R"(OpFwidthCoarse)", &s_operands[688], + &s_operands[689], 3, }, { SpirvOp::OpEmitVertex, R"(OpEmitVertex)", nullptr, + nullptr, 0, }, { SpirvOp::OpEndPrimitive, R"(OpEndPrimitive)", nullptr, + nullptr, 0, }, { SpirvOp::OpEmitStreamVertex, R"(OpEmitStreamVertex)", &s_operands[691], + nullptr, 1, }, { SpirvOp::OpEndStreamPrimitive, R"(OpEndStreamPrimitive)", &s_operands[692], + nullptr, 1, }, { SpirvOp::OpControlBarrier, R"(OpControlBarrier)", &s_operands[693], + nullptr, 3, }, { SpirvOp::OpMemoryBarrier, R"(OpMemoryBarrier)", &s_operands[696], + nullptr, 2, }, { SpirvOp::OpAtomicLoad, R"(OpAtomicLoad)", &s_operands[698], + &s_operands[699], 5, }, { SpirvOp::OpAtomicStore, R"(OpAtomicStore)", &s_operands[703], + nullptr, 4, }, { SpirvOp::OpAtomicExchange, R"(OpAtomicExchange)", &s_operands[707], + &s_operands[708], 6, }, { SpirvOp::OpAtomicCompareExchange, R"(OpAtomicCompareExchange)", &s_operands[713], + &s_operands[714], 8, }, { SpirvOp::OpAtomicCompareExchangeWeak, R"(OpAtomicCompareExchangeWeak)", &s_operands[721], + &s_operands[722], 8, }, { SpirvOp::OpAtomicIIncrement, R"(OpAtomicIIncrement)", &s_operands[729], + &s_operands[730], 5, }, { SpirvOp::OpAtomicIDecrement, R"(OpAtomicIDecrement)", &s_operands[734], + &s_operands[735], 5, }, { SpirvOp::OpAtomicIAdd, R"(OpAtomicIAdd)", &s_operands[739], + &s_operands[740], 6, }, { SpirvOp::OpAtomicISub, R"(OpAtomicISub)", &s_operands[745], + &s_operands[746], 6, }, { SpirvOp::OpAtomicSMin, R"(OpAtomicSMin)", &s_operands[751], + &s_operands[752], 6, }, { SpirvOp::OpAtomicUMin, R"(OpAtomicUMin)", &s_operands[757], + &s_operands[758], 6, }, { SpirvOp::OpAtomicSMax, R"(OpAtomicSMax)", &s_operands[763], + &s_operands[764], 6, }, { SpirvOp::OpAtomicUMax, R"(OpAtomicUMax)", &s_operands[769], + &s_operands[770], 6, }, { SpirvOp::OpAtomicAnd, R"(OpAtomicAnd)", &s_operands[775], + &s_operands[776], 6, }, { SpirvOp::OpAtomicOr, R"(OpAtomicOr)", &s_operands[781], + &s_operands[782], 6, }, { SpirvOp::OpAtomicXor, R"(OpAtomicXor)", &s_operands[787], + &s_operands[788], 6, }, { SpirvOp::OpPhi, R"(OpPhi)", &s_operands[793], + &s_operands[794], 3, }, { SpirvOp::OpLoopMerge, R"(OpLoopMerge)", &s_operands[796], + nullptr, 3, }, { SpirvOp::OpSelectionMerge, R"(OpSelectionMerge)", &s_operands[799], + nullptr, 2, }, { SpirvOp::OpLabel, R"(OpLabel)", &s_operands[801], + &s_operands[801], 1, }, { SpirvOp::OpBranch, R"(OpBranch)", &s_operands[802], + nullptr, 1, }, { SpirvOp::OpBranchConditional, R"(OpBranchConditional)", &s_operands[803], + nullptr, 4, }, { SpirvOp::OpSwitch, R"(OpSwitch)", &s_operands[807], + nullptr, 3, }, { SpirvOp::OpKill, R"(OpKill)", nullptr, + nullptr, 0, }, { SpirvOp::OpReturn, R"(OpReturn)", nullptr, + nullptr, 0, }, { SpirvOp::OpReturnValue, R"(OpReturnValue)", &s_operands[810], + nullptr, 1, }, { SpirvOp::OpUnreachable, R"(OpUnreachable)", nullptr, + nullptr, 0, }, { SpirvOp::OpLifetimeStart, R"(OpLifetimeStart)", &s_operands[811], + nullptr, 2, }, { SpirvOp::OpLifetimeStop, R"(OpLifetimeStop)", &s_operands[813], + nullptr, 2, }, { SpirvOp::OpGroupAsyncCopy, R"(OpGroupAsyncCopy)", &s_operands[815], + &s_operands[816], 8, }, { SpirvOp::OpGroupWaitEvents, R"(OpGroupWaitEvents)", &s_operands[823], + nullptr, 3, }, { SpirvOp::OpGroupAll, R"(OpGroupAll)", &s_operands[826], + &s_operands[827], 4, }, { SpirvOp::OpGroupAny, R"(OpGroupAny)", &s_operands[830], + &s_operands[831], 4, }, { SpirvOp::OpGroupBroadcast, R"(OpGroupBroadcast)", &s_operands[834], + &s_operands[835], 5, }, { SpirvOp::OpGroupIAdd, R"(OpGroupIAdd)", &s_operands[839], + &s_operands[840], 5, }, { SpirvOp::OpGroupFAdd, R"(OpGroupFAdd)", &s_operands[844], + &s_operands[845], 5, }, { SpirvOp::OpGroupFMin, R"(OpGroupFMin)", &s_operands[849], + &s_operands[850], 5, }, { SpirvOp::OpGroupUMin, R"(OpGroupUMin)", &s_operands[854], + &s_operands[855], 5, }, { SpirvOp::OpGroupSMin, R"(OpGroupSMin)", &s_operands[859], + &s_operands[860], 5, }, { SpirvOp::OpGroupFMax, R"(OpGroupFMax)", &s_operands[864], + &s_operands[865], 5, }, { SpirvOp::OpGroupUMax, R"(OpGroupUMax)", &s_operands[869], + &s_operands[870], 5, }, { SpirvOp::OpGroupSMax, R"(OpGroupSMax)", &s_operands[874], + &s_operands[875], 5, }, { SpirvOp::OpReadPipe, R"(OpReadPipe)", &s_operands[879], + &s_operands[880], 6, }, { SpirvOp::OpWritePipe, R"(OpWritePipe)", &s_operands[885], + &s_operands[886], 6, }, { SpirvOp::OpReservedReadPipe, R"(OpReservedReadPipe)", &s_operands[891], + &s_operands[892], 8, }, { SpirvOp::OpReservedWritePipe, R"(OpReservedWritePipe)", &s_operands[899], + &s_operands[900], 8, }, { SpirvOp::OpReserveReadPipePackets, R"(OpReserveReadPipePackets)", &s_operands[907], + &s_operands[908], 6, }, { SpirvOp::OpReserveWritePipePackets, R"(OpReserveWritePipePackets)", &s_operands[913], + &s_operands[914], 6, }, { SpirvOp::OpCommitReadPipe, R"(OpCommitReadPipe)", &s_operands[919], + nullptr, 4, }, { SpirvOp::OpCommitWritePipe, R"(OpCommitWritePipe)", &s_operands[923], + nullptr, 4, }, { SpirvOp::OpIsValidReserveId, R"(OpIsValidReserveId)", &s_operands[927], + &s_operands[928], 3, }, { SpirvOp::OpGetNumPipePackets, R"(OpGetNumPipePackets)", &s_operands[930], + &s_operands[931], 5, }, { SpirvOp::OpGetMaxPipePackets, R"(OpGetMaxPipePackets)", &s_operands[935], + &s_operands[936], 5, }, { SpirvOp::OpGroupReserveReadPipePackets, R"(OpGroupReserveReadPipePackets)", &s_operands[940], + &s_operands[941], 7, }, { SpirvOp::OpGroupReserveWritePipePackets, R"(OpGroupReserveWritePipePackets)", &s_operands[947], + &s_operands[948], 7, }, { SpirvOp::OpGroupCommitReadPipe, R"(OpGroupCommitReadPipe)", &s_operands[954], + nullptr, 5, }, { SpirvOp::OpGroupCommitWritePipe, R"(OpGroupCommitWritePipe)", &s_operands[959], + nullptr, 5, }, { SpirvOp::OpEnqueueMarker, R"(OpEnqueueMarker)", &s_operands[964], + &s_operands[965], 6, }, { SpirvOp::OpEnqueueKernel, R"(OpEnqueueKernel)", &s_operands[970], + &s_operands[971], 13, }, { SpirvOp::OpGetKernelNDrangeSubGroupCount, R"(OpGetKernelNDrangeSubGroupCount)", &s_operands[983], + &s_operands[984], 7, }, { SpirvOp::OpGetKernelNDrangeMaxSubGroupSize, R"(OpGetKernelNDrangeMaxSubGroupSize)", &s_operands[990], + &s_operands[991], 7, }, { SpirvOp::OpGetKernelWorkGroupSize, R"(OpGetKernelWorkGroupSize)", &s_operands[997], + &s_operands[998], 6, }, { SpirvOp::OpGetKernelPreferredWorkGroupSizeMultiple, R"(OpGetKernelPreferredWorkGroupSizeMultiple)", &s_operands[1003], + &s_operands[1004], 6, }, { SpirvOp::OpRetainEvent, R"(OpRetainEvent)", &s_operands[1009], + nullptr, 1, }, { SpirvOp::OpReleaseEvent, R"(OpReleaseEvent)", &s_operands[1010], + nullptr, 1, }, { SpirvOp::OpCreateUserEvent, R"(OpCreateUserEvent)", &s_operands[1011], + &s_operands[1012], 2, }, { SpirvOp::OpIsValidEvent, R"(OpIsValidEvent)", &s_operands[1013], + &s_operands[1014], 3, }, { SpirvOp::OpSetUserEventStatus, R"(OpSetUserEventStatus)", &s_operands[1016], + nullptr, 2, }, { SpirvOp::OpCaptureEventProfilingInfo, R"(OpCaptureEventProfilingInfo)", &s_operands[1018], + nullptr, 3, }, { SpirvOp::OpGetDefaultQueue, R"(OpGetDefaultQueue)", &s_operands[1021], + &s_operands[1022], 2, }, { SpirvOp::OpBuildNDRange, R"(OpBuildNDRange)", &s_operands[1023], + &s_operands[1024], 5, }, { SpirvOp::OpImageSparseSampleImplicitLod, R"(OpImageSparseSampleImplicitLod)", &s_operands[1028], + &s_operands[1029], 5, }, { SpirvOp::OpImageSparseSampleExplicitLod, R"(OpImageSparseSampleExplicitLod)", &s_operands[1033], + &s_operands[1034], 5, }, { SpirvOp::OpImageSparseSampleDrefImplicitLod, R"(OpImageSparseSampleDrefImplicitLod)", &s_operands[1038], + &s_operands[1039], 6, }, { SpirvOp::OpImageSparseSampleDrefExplicitLod, R"(OpImageSparseSampleDrefExplicitLod)", &s_operands[1044], + &s_operands[1045], 6, }, { SpirvOp::OpImageSparseSampleProjImplicitLod, R"(OpImageSparseSampleProjImplicitLod)", &s_operands[1050], + &s_operands[1051], 5, }, { SpirvOp::OpImageSparseSampleProjExplicitLod, R"(OpImageSparseSampleProjExplicitLod)", &s_operands[1055], + &s_operands[1056], 5, }, { SpirvOp::OpImageSparseSampleProjDrefImplicitLod, R"(OpImageSparseSampleProjDrefImplicitLod)", &s_operands[1060], + &s_operands[1061], 6, }, { SpirvOp::OpImageSparseSampleProjDrefExplicitLod, R"(OpImageSparseSampleProjDrefExplicitLod)", &s_operands[1066], + &s_operands[1067], 6, }, { SpirvOp::OpImageSparseFetch, R"(OpImageSparseFetch)", &s_operands[1072], + &s_operands[1073], 5, }, { SpirvOp::OpImageSparseGather, R"(OpImageSparseGather)", &s_operands[1077], + &s_operands[1078], 6, }, { SpirvOp::OpImageSparseDrefGather, R"(OpImageSparseDrefGather)", &s_operands[1083], + &s_operands[1084], 6, }, { SpirvOp::OpImageSparseTexelsResident, R"(OpImageSparseTexelsResident)", &s_operands[1089], + &s_operands[1090], 3, }, { SpirvOp::OpNoLine, R"(OpNoLine)", nullptr, + nullptr, 0, }, { SpirvOp::OpAtomicFlagTestAndSet, R"(OpAtomicFlagTestAndSet)", &s_operands[1092], + &s_operands[1093], 5, }, { SpirvOp::OpAtomicFlagClear, R"(OpAtomicFlagClear)", &s_operands[1097], + nullptr, 3, }, { SpirvOp::OpImageSparseRead, R"(OpImageSparseRead)", &s_operands[1100], + &s_operands[1101], 5, }, { SpirvOp::OpSizeOf, R"(OpSizeOf)", &s_operands[1105], + &s_operands[1106], 3, }, { SpirvOp::OpTypePipeStorage, R"(OpTypePipeStorage)", &s_operands[1108], + &s_operands[1108], 1, }, { SpirvOp::OpConstantPipeStorage, R"(OpConstantPipeStorage)", &s_operands[1109], + &s_operands[1110], 5, }, { SpirvOp::OpCreatePipeFromPipeStorage, R"(OpCreatePipeFromPipeStorage)", &s_operands[1114], + &s_operands[1115], 3, }, { SpirvOp::OpGetKernelLocalSizeForSubgroupCount, R"(OpGetKernelLocalSizeForSubgroupCount)", &s_operands[1117], + &s_operands[1118], 7, }, { SpirvOp::OpGetKernelMaxNumSubgroups, R"(OpGetKernelMaxNumSubgroups)", &s_operands[1124], + &s_operands[1125], 6, }, { SpirvOp::OpTypeNamedBarrier, R"(OpTypeNamedBarrier)", &s_operands[1130], + &s_operands[1130], 1, }, { SpirvOp::OpNamedBarrierInitialize, R"(OpNamedBarrierInitialize)", &s_operands[1131], + &s_operands[1132], 3, }, { SpirvOp::OpMemoryNamedBarrier, R"(OpMemoryNamedBarrier)", &s_operands[1134], + nullptr, 3, }, { SpirvOp::OpModuleProcessed, R"(OpModuleProcessed)", &s_operands[1137], + nullptr, 1, }, { SpirvOp::OpExecutionModeId, R"(OpExecutionModeId)", &s_operands[1138], + nullptr, 2, }, { SpirvOp::OpDecorateId, R"(OpDecorateId)", &s_operands[1140], + nullptr, 2, }, { SpirvOp::OpGroupNonUniformElect, R"(OpGroupNonUniformElect)", &s_operands[1142], + &s_operands[1143], 3, }, { SpirvOp::OpGroupNonUniformAll, R"(OpGroupNonUniformAll)", &s_operands[1145], + &s_operands[1146], 4, }, { SpirvOp::OpGroupNonUniformAny, R"(OpGroupNonUniformAny)", &s_operands[1149], + &s_operands[1150], 4, }, { SpirvOp::OpGroupNonUniformAllEqual, R"(OpGroupNonUniformAllEqual)", &s_operands[1153], + &s_operands[1154], 4, }, { SpirvOp::OpGroupNonUniformBroadcast, R"(OpGroupNonUniformBroadcast)", &s_operands[1157], + &s_operands[1158], 5, }, { SpirvOp::OpGroupNonUniformBroadcastFirst, R"(OpGroupNonUniformBroadcastFirst)", &s_operands[1162], + &s_operands[1163], 4, }, { SpirvOp::OpGroupNonUniformBallot, R"(OpGroupNonUniformBallot)", &s_operands[1166], + &s_operands[1167], 4, }, { SpirvOp::OpGroupNonUniformInverseBallot, R"(OpGroupNonUniformInverseBallot)", &s_operands[1170], + &s_operands[1171], 4, }, { SpirvOp::OpGroupNonUniformBallotBitExtract, R"(OpGroupNonUniformBallotBitExtract)", &s_operands[1174], + &s_operands[1175], 5, }, { SpirvOp::OpGroupNonUniformBallotBitCount, R"(OpGroupNonUniformBallotBitCount)", &s_operands[1179], + &s_operands[1180], 5, }, { SpirvOp::OpGroupNonUniformBallotFindLSB, R"(OpGroupNonUniformBallotFindLSB)", &s_operands[1184], + &s_operands[1185], 4, }, { SpirvOp::OpGroupNonUniformBallotFindMSB, R"(OpGroupNonUniformBallotFindMSB)", &s_operands[1188], + &s_operands[1189], 4, }, { SpirvOp::OpGroupNonUniformShuffle, R"(OpGroupNonUniformShuffle)", &s_operands[1192], + &s_operands[1193], 5, }, { SpirvOp::OpGroupNonUniformShuffleXor, R"(OpGroupNonUniformShuffleXor)", &s_operands[1197], + &s_operands[1198], 5, }, { SpirvOp::OpGroupNonUniformShuffleUp, R"(OpGroupNonUniformShuffleUp)", &s_operands[1202], + &s_operands[1203], 5, }, { SpirvOp::OpGroupNonUniformShuffleDown, R"(OpGroupNonUniformShuffleDown)", &s_operands[1207], + &s_operands[1208], 5, }, { SpirvOp::OpGroupNonUniformIAdd, R"(OpGroupNonUniformIAdd)", &s_operands[1212], + &s_operands[1213], 6, }, { SpirvOp::OpGroupNonUniformFAdd, R"(OpGroupNonUniformFAdd)", &s_operands[1218], + &s_operands[1219], 6, }, { SpirvOp::OpGroupNonUniformIMul, R"(OpGroupNonUniformIMul)", &s_operands[1224], + &s_operands[1225], 6, }, { SpirvOp::OpGroupNonUniformFMul, R"(OpGroupNonUniformFMul)", &s_operands[1230], + &s_operands[1231], 6, }, { SpirvOp::OpGroupNonUniformSMin, R"(OpGroupNonUniformSMin)", &s_operands[1236], + &s_operands[1237], 6, }, { SpirvOp::OpGroupNonUniformUMin, R"(OpGroupNonUniformUMin)", &s_operands[1242], + &s_operands[1243], 6, }, { SpirvOp::OpGroupNonUniformFMin, R"(OpGroupNonUniformFMin)", &s_operands[1248], + &s_operands[1249], 6, }, { SpirvOp::OpGroupNonUniformSMax, R"(OpGroupNonUniformSMax)", &s_operands[1254], + &s_operands[1255], 6, }, { SpirvOp::OpGroupNonUniformUMax, R"(OpGroupNonUniformUMax)", &s_operands[1260], + &s_operands[1261], 6, }, { SpirvOp::OpGroupNonUniformFMax, R"(OpGroupNonUniformFMax)", &s_operands[1266], + &s_operands[1267], 6, }, { SpirvOp::OpGroupNonUniformBitwiseAnd, R"(OpGroupNonUniformBitwiseAnd)", &s_operands[1272], + &s_operands[1273], 6, }, { SpirvOp::OpGroupNonUniformBitwiseOr, R"(OpGroupNonUniformBitwiseOr)", &s_operands[1278], + &s_operands[1279], 6, }, { SpirvOp::OpGroupNonUniformBitwiseXor, R"(OpGroupNonUniformBitwiseXor)", &s_operands[1284], + &s_operands[1285], 6, }, { SpirvOp::OpGroupNonUniformLogicalAnd, R"(OpGroupNonUniformLogicalAnd)", &s_operands[1290], + &s_operands[1291], 6, }, { SpirvOp::OpGroupNonUniformLogicalOr, R"(OpGroupNonUniformLogicalOr)", &s_operands[1296], + &s_operands[1297], 6, }, { SpirvOp::OpGroupNonUniformLogicalXor, R"(OpGroupNonUniformLogicalXor)", &s_operands[1302], + &s_operands[1303], 6, }, { SpirvOp::OpGroupNonUniformQuadBroadcast, R"(OpGroupNonUniformQuadBroadcast)", &s_operands[1308], + &s_operands[1309], 5, }, { SpirvOp::OpGroupNonUniformQuadSwap, R"(OpGroupNonUniformQuadSwap)", &s_operands[1313], + &s_operands[1314], 5, }, { SpirvOp::OpCopyLogical, R"(OpCopyLogical)", &s_operands[1318], + &s_operands[1319], 3, }, { SpirvOp::OpPtrEqual, R"(OpPtrEqual)", &s_operands[1321], + &s_operands[1322], 4, }, { SpirvOp::OpPtrNotEqual, R"(OpPtrNotEqual)", &s_operands[1325], + &s_operands[1326], 4, }, { SpirvOp::OpPtrDiff, R"(OpPtrDiff)", &s_operands[1329], + &s_operands[1330], 4, }, { SpirvOp::OpTerminateInvocation, R"(OpTerminateInvocation)", nullptr, + nullptr, 0, }, { SpirvOp::OpSubgroupBallotKHR, R"(OpSubgroupBallotKHR)", &s_operands[1333], + &s_operands[1334], 3, }, { SpirvOp::OpSubgroupFirstInvocationKHR, R"(OpSubgroupFirstInvocationKHR)", &s_operands[1336], + &s_operands[1337], 3, }, { SpirvOp::OpSubgroupAllKHR, R"(OpSubgroupAllKHR)", &s_operands[1339], + &s_operands[1340], 3, }, { SpirvOp::OpSubgroupAnyKHR, R"(OpSubgroupAnyKHR)", &s_operands[1342], + &s_operands[1343], 3, }, { SpirvOp::OpSubgroupAllEqualKHR, R"(OpSubgroupAllEqualKHR)", &s_operands[1345], + &s_operands[1346], 3, }, { SpirvOp::OpSubgroupReadInvocationKHR, R"(OpSubgroupReadInvocationKHR)", &s_operands[1348], + &s_operands[1349], 4, }, { SpirvOp::OpTraceRayKHR, R"(OpTraceRayKHR)", &s_operands[1352], + nullptr, 11, }, { SpirvOp::OpExecuteCallableKHR, R"(OpExecuteCallableKHR)", &s_operands[1363], + nullptr, 2, }, { SpirvOp::OpConvertUToAccelerationStructureKHR, R"(OpConvertUToAccelerationStructureKHR)", &s_operands[1365], + &s_operands[1366], 3, }, { SpirvOp::OpIgnoreIntersectionKHR, R"(OpIgnoreIntersectionKHR)", nullptr, + nullptr, 0, }, { SpirvOp::OpTerminateRayKHR, R"(OpTerminateRayKHR)", nullptr, + nullptr, 0, }, { SpirvOp::OpTypeRayQueryKHR, R"(OpTypeRayQueryKHR)", &s_operands[1368], + &s_operands[1368], 1, }, { SpirvOp::OpRayQueryInitializeKHR, R"(OpRayQueryInitializeKHR)", &s_operands[1369], + nullptr, 8, }, { SpirvOp::OpRayQueryTerminateKHR, R"(OpRayQueryTerminateKHR)", &s_operands[1377], + nullptr, 1, }, { SpirvOp::OpRayQueryGenerateIntersectionKHR, R"(OpRayQueryGenerateIntersectionKHR)", &s_operands[1378], + nullptr, 2, }, { SpirvOp::OpRayQueryConfirmIntersectionKHR, R"(OpRayQueryConfirmIntersectionKHR)", &s_operands[1380], + nullptr, 1, }, { SpirvOp::OpRayQueryProceedKHR, R"(OpRayQueryProceedKHR)", &s_operands[1381], + &s_operands[1382], 3, }, { SpirvOp::OpRayQueryGetIntersectionTypeKHR, R"(OpRayQueryGetIntersectionTypeKHR)", &s_operands[1384], + &s_operands[1385], 4, }, { SpirvOp::OpGroupIAddNonUniformAMD, R"(OpGroupIAddNonUniformAMD)", &s_operands[1388], + &s_operands[1389], 5, }, { SpirvOp::OpGroupFAddNonUniformAMD, R"(OpGroupFAddNonUniformAMD)", &s_operands[1393], + &s_operands[1394], 5, }, { SpirvOp::OpGroupFMinNonUniformAMD, R"(OpGroupFMinNonUniformAMD)", &s_operands[1398], + &s_operands[1399], 5, }, { SpirvOp::OpGroupUMinNonUniformAMD, R"(OpGroupUMinNonUniformAMD)", &s_operands[1403], + &s_operands[1404], 5, }, { SpirvOp::OpGroupSMinNonUniformAMD, R"(OpGroupSMinNonUniformAMD)", &s_operands[1408], + &s_operands[1409], 5, }, { SpirvOp::OpGroupFMaxNonUniformAMD, R"(OpGroupFMaxNonUniformAMD)", &s_operands[1413], + &s_operands[1414], 5, }, { SpirvOp::OpGroupUMaxNonUniformAMD, R"(OpGroupUMaxNonUniformAMD)", &s_operands[1418], + &s_operands[1419], 5, }, { SpirvOp::OpGroupSMaxNonUniformAMD, R"(OpGroupSMaxNonUniformAMD)", &s_operands[1423], + &s_operands[1424], 5, }, { SpirvOp::OpFragmentMaskFetchAMD, R"(OpFragmentMaskFetchAMD)", &s_operands[1428], + &s_operands[1429], 4, }, { SpirvOp::OpFragmentFetchAMD, R"(OpFragmentFetchAMD)", &s_operands[1432], + &s_operands[1433], 5, }, { SpirvOp::OpReadClockKHR, R"(OpReadClockKHR)", &s_operands[1437], + &s_operands[1438], 3, }, { SpirvOp::OpImageSampleFootprintNV, R"(OpImageSampleFootprintNV)", &s_operands[1440], + &s_operands[1441], 7, }, { SpirvOp::OpGroupNonUniformPartitionNV, R"(OpGroupNonUniformPartitionNV)", &s_operands[1447], + &s_operands[1448], 3, }, { SpirvOp::OpWritePackedPrimitiveIndices4x8NV, R"(OpWritePackedPrimitiveIndices4x8NV)", &s_operands[1450], + nullptr, 2, }, { SpirvOp::OpReportIntersectionKHR, R"(OpReportIntersectionKHR)", &s_operands[1452], + &s_operands[1453], 4, }, { SpirvOp::OpIgnoreIntersectionNV, R"(OpIgnoreIntersectionNV)", nullptr, + nullptr, 0, }, { SpirvOp::OpTerminateRayNV, R"(OpTerminateRayNV)", nullptr, + nullptr, 0, }, { SpirvOp::OpTraceNV, R"(OpTraceNV)", &s_operands[1456], + nullptr, 11, }, { SpirvOp::OpTypeAccelerationStructureKHR, R"(OpTypeAccelerationStructureKHR)", &s_operands[1467], + &s_operands[1467], 1, }, { SpirvOp::OpExecuteCallableNV, R"(OpExecuteCallableNV)", &s_operands[1468], + nullptr, 2, }, { SpirvOp::OpTypeCooperativeMatrixNV, R"(OpTypeCooperativeMatrixNV)", &s_operands[1470], + &s_operands[1470], 5, }, { SpirvOp::OpCooperativeMatrixLoadNV, R"(OpCooperativeMatrixLoadNV)", &s_operands[1475], + &s_operands[1476], 6, }, { SpirvOp::OpCooperativeMatrixStoreNV, R"(OpCooperativeMatrixStoreNV)", &s_operands[1481], + nullptr, 5, }, { SpirvOp::OpCooperativeMatrixMulAddNV, R"(OpCooperativeMatrixMulAddNV)", &s_operands[1486], + &s_operands[1487], 5, }, { SpirvOp::OpCooperativeMatrixLengthNV, R"(OpCooperativeMatrixLengthNV)", &s_operands[1491], + &s_operands[1492], 3, }, { SpirvOp::OpBeginInvocationInterlockEXT, R"(OpBeginInvocationInterlockEXT)", nullptr, + nullptr, 0, }, { SpirvOp::OpEndInvocationInterlockEXT, R"(OpEndInvocationInterlockEXT)", nullptr, + nullptr, 0, }, { SpirvOp::OpDemoteToHelperInvocationEXT, R"(OpDemoteToHelperInvocationEXT)", nullptr, + nullptr, 0, }, { SpirvOp::OpIsHelperInvocationEXT, R"(OpIsHelperInvocationEXT)", &s_operands[1494], + &s_operands[1495], 2, }, { SpirvOp::OpSubgroupShuffleINTEL, R"(OpSubgroupShuffleINTEL)", &s_operands[1496], + &s_operands[1497], 4, }, { SpirvOp::OpSubgroupShuffleDownINTEL, R"(OpSubgroupShuffleDownINTEL)", &s_operands[1500], + &s_operands[1501], 5, }, { SpirvOp::OpSubgroupShuffleUpINTEL, R"(OpSubgroupShuffleUpINTEL)", &s_operands[1505], + &s_operands[1506], 5, }, { SpirvOp::OpSubgroupShuffleXorINTEL, R"(OpSubgroupShuffleXorINTEL)", &s_operands[1510], + &s_operands[1511], 4, }, { SpirvOp::OpSubgroupBlockReadINTEL, R"(OpSubgroupBlockReadINTEL)", &s_operands[1514], + &s_operands[1515], 3, }, { SpirvOp::OpSubgroupBlockWriteINTEL, R"(OpSubgroupBlockWriteINTEL)", &s_operands[1517], + nullptr, 2, }, { SpirvOp::OpSubgroupImageBlockReadINTEL, R"(OpSubgroupImageBlockReadINTEL)", &s_operands[1519], + &s_operands[1520], 4, }, { SpirvOp::OpSubgroupImageBlockWriteINTEL, R"(OpSubgroupImageBlockWriteINTEL)", &s_operands[1523], + nullptr, 3, }, { SpirvOp::OpSubgroupImageMediaBlockReadINTEL, R"(OpSubgroupImageMediaBlockReadINTEL)", &s_operands[1526], + &s_operands[1527], 6, }, { SpirvOp::OpSubgroupImageMediaBlockWriteINTEL, R"(OpSubgroupImageMediaBlockWriteINTEL)", &s_operands[1532], + nullptr, 5, }, { SpirvOp::OpUCountLeadingZerosINTEL, R"(OpUCountLeadingZerosINTEL)", &s_operands[1537], + &s_operands[1538], 3, }, { SpirvOp::OpUCountTrailingZerosINTEL, R"(OpUCountTrailingZerosINTEL)", &s_operands[1540], + &s_operands[1541], 3, }, { SpirvOp::OpAbsISubINTEL, R"(OpAbsISubINTEL)", &s_operands[1543], + &s_operands[1544], 4, }, { SpirvOp::OpAbsUSubINTEL, R"(OpAbsUSubINTEL)", &s_operands[1547], + &s_operands[1548], 4, }, { SpirvOp::OpIAddSatINTEL, R"(OpIAddSatINTEL)", &s_operands[1551], + &s_operands[1552], 4, }, { SpirvOp::OpUAddSatINTEL, R"(OpUAddSatINTEL)", &s_operands[1555], + &s_operands[1556], 4, }, { SpirvOp::OpIAverageINTEL, R"(OpIAverageINTEL)", &s_operands[1559], + &s_operands[1560], 4, }, { SpirvOp::OpUAverageINTEL, R"(OpUAverageINTEL)", &s_operands[1563], + &s_operands[1564], 4, }, { SpirvOp::OpIAverageRoundedINTEL, R"(OpIAverageRoundedINTEL)", &s_operands[1567], + &s_operands[1568], 4, }, { SpirvOp::OpUAverageRoundedINTEL, R"(OpUAverageRoundedINTEL)", &s_operands[1571], + &s_operands[1572], 4, }, { SpirvOp::OpISubSatINTEL, R"(OpISubSatINTEL)", &s_operands[1575], + &s_operands[1576], 4, }, { SpirvOp::OpUSubSatINTEL, R"(OpUSubSatINTEL)", &s_operands[1579], + &s_operands[1580], 4, }, { SpirvOp::OpIMul32x16INTEL, R"(OpIMul32x16INTEL)", &s_operands[1583], + &s_operands[1584], 4, }, { SpirvOp::OpUMul32x16INTEL, R"(OpUMul32x16INTEL)", &s_operands[1587], + &s_operands[1588], 4, }, { SpirvOp::OpConstFunctionPointerINTEL, R"(OpConstFunctionPointerINTEL)", &s_operands[1591], + &s_operands[1592], 3, }, { SpirvOp::OpFunctionPointerCallINTEL, R"(OpFunctionPointerCallINTEL)", &s_operands[1594], + &s_operands[1595], 3, }, { SpirvOp::OpAsmTargetINTEL, R"(OpAsmTargetINTEL)", &s_operands[1597], + &s_operands[1598], 3, }, { SpirvOp::OpAsmINTEL, R"(OpAsmINTEL)", &s_operands[1600], + &s_operands[1601], 6, }, { SpirvOp::OpAsmCallINTEL, R"(OpAsmCallINTEL)", &s_operands[1606], + &s_operands[1607], 4, }, { SpirvOp::OpAtomicFMinEXT, R"(OpAtomicFMinEXT)", &s_operands[1610], + &s_operands[1611], 6, }, { SpirvOp::OpAtomicFMaxEXT, R"(OpAtomicFMaxEXT)", &s_operands[1616], + &s_operands[1617], 6, }, + { + SpirvOp::OpAssumeTrueKHR, + R"(OpAssumeTrueKHR)", + &s_operands[1622], + nullptr, + 1, + }, + { + SpirvOp::OpExpectKHR, + R"(OpExpectKHR)", + &s_operands[1623], + &s_operands[1624], + 4, + }, { SpirvOp::OpDecorateStringGOOGLE, R"(OpDecorateStringGOOGLE)", - &s_operands[1622], + &s_operands[1627], + nullptr, 2, }, { SpirvOp::OpMemberDecorateStringGOOGLE, R"(OpMemberDecorateStringGOOGLE)", - &s_operands[1624], + &s_operands[1629], + nullptr, 3, }, { SpirvOp::OpVmeImageINTEL, R"(OpVmeImageINTEL)", - &s_operands[1627], + &s_operands[1632], + &s_operands[1633], 4, }, { SpirvOp::OpTypeVmeImageINTEL, R"(OpTypeVmeImageINTEL)", - &s_operands[1631], + &s_operands[1636], + &s_operands[1636], 2, }, { SpirvOp::OpTypeAvcImePayloadINTEL, R"(OpTypeAvcImePayloadINTEL)", - &s_operands[1633], + &s_operands[1638], + &s_operands[1638], 1, }, { SpirvOp::OpTypeAvcRefPayloadINTEL, R"(OpTypeAvcRefPayloadINTEL)", - &s_operands[1634], + &s_operands[1639], + &s_operands[1639], 1, }, { SpirvOp::OpTypeAvcSicPayloadINTEL, R"(OpTypeAvcSicPayloadINTEL)", - &s_operands[1635], + &s_operands[1640], + &s_operands[1640], 1, }, { SpirvOp::OpTypeAvcMcePayloadINTEL, R"(OpTypeAvcMcePayloadINTEL)", - &s_operands[1636], + &s_operands[1641], + &s_operands[1641], 1, }, { SpirvOp::OpTypeAvcMceResultINTEL, R"(OpTypeAvcMceResultINTEL)", - &s_operands[1637], + &s_operands[1642], + &s_operands[1642], 1, }, { SpirvOp::OpTypeAvcImeResultINTEL, R"(OpTypeAvcImeResultINTEL)", - &s_operands[1638], + &s_operands[1643], + &s_operands[1643], 1, }, { SpirvOp::OpTypeAvcImeResultSingleReferenceStreamoutINTEL, R"(OpTypeAvcImeResultSingleReferenceStreamoutINTEL)", - &s_operands[1639], + &s_operands[1644], + &s_operands[1644], 1, }, { SpirvOp::OpTypeAvcImeResultDualReferenceStreamoutINTEL, R"(OpTypeAvcImeResultDualReferenceStreamoutINTEL)", - &s_operands[1640], + &s_operands[1645], + &s_operands[1645], 1, }, { SpirvOp::OpTypeAvcImeSingleReferenceStreaminINTEL, R"(OpTypeAvcImeSingleReferenceStreaminINTEL)", - &s_operands[1641], + &s_operands[1646], + &s_operands[1646], 1, }, { SpirvOp::OpTypeAvcImeDualReferenceStreaminINTEL, R"(OpTypeAvcImeDualReferenceStreaminINTEL)", - &s_operands[1642], + &s_operands[1647], + &s_operands[1647], 1, }, { SpirvOp::OpTypeAvcRefResultINTEL, R"(OpTypeAvcRefResultINTEL)", - &s_operands[1643], + &s_operands[1648], + &s_operands[1648], 1, }, { SpirvOp::OpTypeAvcSicResultINTEL, R"(OpTypeAvcSicResultINTEL)", - &s_operands[1644], + &s_operands[1649], + &s_operands[1649], 1, }, { SpirvOp::OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL, R"(OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL)", - &s_operands[1645], + &s_operands[1650], + &s_operands[1651], 4, }, { SpirvOp::OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL, R"(OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL)", - &s_operands[1649], + &s_operands[1654], + &s_operands[1655], 4, }, { SpirvOp::OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL, R"(OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL)", - &s_operands[1653], + &s_operands[1658], + &s_operands[1659], 4, }, { SpirvOp::OpSubgroupAvcMceSetInterShapePenaltyINTEL, R"(OpSubgroupAvcMceSetInterShapePenaltyINTEL)", - &s_operands[1657], + &s_operands[1662], + &s_operands[1663], 4, }, { SpirvOp::OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL, R"(OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL)", - &s_operands[1661], + &s_operands[1666], + &s_operands[1667], 4, }, { SpirvOp::OpSubgroupAvcMceSetInterDirectionPenaltyINTEL, R"(OpSubgroupAvcMceSetInterDirectionPenaltyINTEL)", - &s_operands[1665], + &s_operands[1670], + &s_operands[1671], 4, }, { SpirvOp::OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL, R"(OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL)", - &s_operands[1669], + &s_operands[1674], + &s_operands[1675], 4, }, { SpirvOp::OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL, R"(OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL)", - &s_operands[1673], + &s_operands[1678], + &s_operands[1679], 4, }, { SpirvOp::OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL, R"(OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL)", - &s_operands[1677], + &s_operands[1682], + &s_operands[1683], 2, }, { SpirvOp::OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL, R"(OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL)", - &s_operands[1679], + &s_operands[1684], + &s_operands[1685], 2, }, { SpirvOp::OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL, R"(OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL)", - &s_operands[1681], + &s_operands[1686], + &s_operands[1687], 2, }, { SpirvOp::OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL, R"(OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL)", - &s_operands[1683], + &s_operands[1688], + &s_operands[1689], 6, }, { SpirvOp::OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL, R"(OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL)", - &s_operands[1689], + &s_operands[1694], + &s_operands[1695], 4, }, { SpirvOp::OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL, R"(OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL)", - &s_operands[1693], + &s_operands[1698], + &s_operands[1699], 2, }, { SpirvOp::OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL, R"(OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL)", - &s_operands[1695], + &s_operands[1700], + &s_operands[1701], 2, }, { SpirvOp::OpSubgroupAvcMceSetAcOnlyHaarINTEL, R"(OpSubgroupAvcMceSetAcOnlyHaarINTEL)", - &s_operands[1697], + &s_operands[1702], + &s_operands[1703], 3, }, { SpirvOp::OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL, R"(OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL)", - &s_operands[1700], + &s_operands[1705], + &s_operands[1706], 4, }, { SpirvOp::OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL, R"(OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL)", - &s_operands[1704], + &s_operands[1709], + &s_operands[1710], 4, }, { SpirvOp::OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL, R"(OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL)", - &s_operands[1708], + &s_operands[1713], + &s_operands[1714], 5, }, { SpirvOp::OpSubgroupAvcMceConvertToImePayloadINTEL, R"(OpSubgroupAvcMceConvertToImePayloadINTEL)", - &s_operands[1713], + &s_operands[1718], + &s_operands[1719], 3, }, { SpirvOp::OpSubgroupAvcMceConvertToImeResultINTEL, R"(OpSubgroupAvcMceConvertToImeResultINTEL)", - &s_operands[1716], + &s_operands[1721], + &s_operands[1722], 3, }, { SpirvOp::OpSubgroupAvcMceConvertToRefPayloadINTEL, R"(OpSubgroupAvcMceConvertToRefPayloadINTEL)", - &s_operands[1719], + &s_operands[1724], + &s_operands[1725], 3, }, { SpirvOp::OpSubgroupAvcMceConvertToRefResultINTEL, R"(OpSubgroupAvcMceConvertToRefResultINTEL)", - &s_operands[1722], + &s_operands[1727], + &s_operands[1728], 3, }, { SpirvOp::OpSubgroupAvcMceConvertToSicPayloadINTEL, R"(OpSubgroupAvcMceConvertToSicPayloadINTEL)", - &s_operands[1725], + &s_operands[1730], + &s_operands[1731], 3, }, { SpirvOp::OpSubgroupAvcMceConvertToSicResultINTEL, R"(OpSubgroupAvcMceConvertToSicResultINTEL)", - &s_operands[1728], + &s_operands[1733], + &s_operands[1734], 3, }, { SpirvOp::OpSubgroupAvcMceGetMotionVectorsINTEL, R"(OpSubgroupAvcMceGetMotionVectorsINTEL)", - &s_operands[1731], + &s_operands[1736], + &s_operands[1737], 3, }, { SpirvOp::OpSubgroupAvcMceGetInterDistortionsINTEL, R"(OpSubgroupAvcMceGetInterDistortionsINTEL)", - &s_operands[1734], + &s_operands[1739], + &s_operands[1740], 3, }, { SpirvOp::OpSubgroupAvcMceGetBestInterDistortionsINTEL, R"(OpSubgroupAvcMceGetBestInterDistortionsINTEL)", - &s_operands[1737], + &s_operands[1742], + &s_operands[1743], 3, }, { SpirvOp::OpSubgroupAvcMceGetInterMajorShapeINTEL, R"(OpSubgroupAvcMceGetInterMajorShapeINTEL)", - &s_operands[1740], + &s_operands[1745], + &s_operands[1746], 3, }, { SpirvOp::OpSubgroupAvcMceGetInterMinorShapeINTEL, R"(OpSubgroupAvcMceGetInterMinorShapeINTEL)", - &s_operands[1743], + &s_operands[1748], + &s_operands[1749], 3, }, { SpirvOp::OpSubgroupAvcMceGetInterDirectionsINTEL, R"(OpSubgroupAvcMceGetInterDirectionsINTEL)", - &s_operands[1746], + &s_operands[1751], + &s_operands[1752], 3, }, { SpirvOp::OpSubgroupAvcMceGetInterMotionVectorCountINTEL, R"(OpSubgroupAvcMceGetInterMotionVectorCountINTEL)", - &s_operands[1749], + &s_operands[1754], + &s_operands[1755], 3, }, { SpirvOp::OpSubgroupAvcMceGetInterReferenceIdsINTEL, R"(OpSubgroupAvcMceGetInterReferenceIdsINTEL)", - &s_operands[1752], + &s_operands[1757], + &s_operands[1758], 3, }, { SpirvOp::OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL, R"(OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL)", - &s_operands[1755], + &s_operands[1760], + &s_operands[1761], 5, }, { SpirvOp::OpSubgroupAvcImeInitializeINTEL, R"(OpSubgroupAvcImeInitializeINTEL)", - &s_operands[1760], + &s_operands[1765], + &s_operands[1766], 5, }, { SpirvOp::OpSubgroupAvcImeSetSingleReferenceINTEL, R"(OpSubgroupAvcImeSetSingleReferenceINTEL)", - &s_operands[1765], + &s_operands[1770], + &s_operands[1771], 5, }, { SpirvOp::OpSubgroupAvcImeSetDualReferenceINTEL, R"(OpSubgroupAvcImeSetDualReferenceINTEL)", - &s_operands[1770], + &s_operands[1775], + &s_operands[1776], 6, }, { SpirvOp::OpSubgroupAvcImeRefWindowSizeINTEL, R"(OpSubgroupAvcImeRefWindowSizeINTEL)", - &s_operands[1776], + &s_operands[1781], + &s_operands[1782], 4, }, { SpirvOp::OpSubgroupAvcImeAdjustRefOffsetINTEL, R"(OpSubgroupAvcImeAdjustRefOffsetINTEL)", - &s_operands[1780], + &s_operands[1785], + &s_operands[1786], 6, }, { SpirvOp::OpSubgroupAvcImeConvertToMcePayloadINTEL, R"(OpSubgroupAvcImeConvertToMcePayloadINTEL)", - &s_operands[1786], + &s_operands[1791], + &s_operands[1792], 3, }, { SpirvOp::OpSubgroupAvcImeSetMaxMotionVectorCountINTEL, R"(OpSubgroupAvcImeSetMaxMotionVectorCountINTEL)", - &s_operands[1789], + &s_operands[1794], + &s_operands[1795], 4, }, { SpirvOp::OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL, R"(OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL)", - &s_operands[1793], + &s_operands[1798], + &s_operands[1799], 3, }, { SpirvOp::OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL, R"(OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL)", - &s_operands[1796], + &s_operands[1801], + &s_operands[1802], 4, }, { SpirvOp::OpSubgroupAvcImeSetWeightedSadINTEL, R"(OpSubgroupAvcImeSetWeightedSadINTEL)", - &s_operands[1800], + &s_operands[1805], + &s_operands[1806], 4, }, { SpirvOp::OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL, R"(OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL)", - &s_operands[1804], + &s_operands[1809], + &s_operands[1810], 5, }, { SpirvOp::OpSubgroupAvcImeEvaluateWithDualReferenceINTEL, R"(OpSubgroupAvcImeEvaluateWithDualReferenceINTEL)", - &s_operands[1809], + &s_operands[1814], + &s_operands[1815], 6, }, { SpirvOp::OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL, R"(OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL)", - &s_operands[1815], + &s_operands[1820], + &s_operands[1821], 6, }, { SpirvOp::OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL, R"(OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL)", - &s_operands[1821], + &s_operands[1826], + &s_operands[1827], 7, }, { SpirvOp::OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL, R"(OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL)", - &s_operands[1828], + &s_operands[1833], + &s_operands[1834], 5, }, { SpirvOp::OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL, R"(OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL)", - &s_operands[1833], + &s_operands[1838], + &s_operands[1839], 6, }, { SpirvOp::OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL, R"(OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL)", - &s_operands[1839], + &s_operands[1844], + &s_operands[1845], 6, }, { SpirvOp::OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL, R"(OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL)", - &s_operands[1845], + &s_operands[1850], + &s_operands[1851], 7, }, { SpirvOp::OpSubgroupAvcImeConvertToMceResultINTEL, R"(OpSubgroupAvcImeConvertToMceResultINTEL)", - &s_operands[1852], + &s_operands[1857], + &s_operands[1858], 3, }, { SpirvOp::OpSubgroupAvcImeGetSingleReferenceStreaminINTEL, R"(OpSubgroupAvcImeGetSingleReferenceStreaminINTEL)", - &s_operands[1855], + &s_operands[1860], + &s_operands[1861], 3, }, { SpirvOp::OpSubgroupAvcImeGetDualReferenceStreaminINTEL, R"(OpSubgroupAvcImeGetDualReferenceStreaminINTEL)", - &s_operands[1858], + &s_operands[1863], + &s_operands[1864], 3, }, { SpirvOp::OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL, R"(OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL)", - &s_operands[1861], + &s_operands[1866], + &s_operands[1867], 3, }, { SpirvOp::OpSubgroupAvcImeStripDualReferenceStreamoutINTEL, R"(OpSubgroupAvcImeStripDualReferenceStreamoutINTEL)", - &s_operands[1864], + &s_operands[1869], + &s_operands[1870], 3, }, { SpirvOp::OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL, R"(OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL)", - &s_operands[1867], + &s_operands[1872], + &s_operands[1873], 4, }, { SpirvOp::OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL, R"(OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL)", - &s_operands[1871], + &s_operands[1876], + &s_operands[1877], 4, }, { SpirvOp::OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL, R"(OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL)", - &s_operands[1875], + &s_operands[1880], + &s_operands[1881], 4, }, { SpirvOp::OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL, R"(OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL)", - &s_operands[1879], + &s_operands[1884], + &s_operands[1885], 5, }, { SpirvOp::OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL, R"(OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL)", - &s_operands[1884], + &s_operands[1889], + &s_operands[1890], 5, }, { SpirvOp::OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL, R"(OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL)", - &s_operands[1889], + &s_operands[1894], + &s_operands[1895], 5, }, { SpirvOp::OpSubgroupAvcImeGetBorderReachedINTEL, R"(OpSubgroupAvcImeGetBorderReachedINTEL)", - &s_operands[1894], + &s_operands[1899], + &s_operands[1900], 4, }, { SpirvOp::OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL, R"(OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL)", - &s_operands[1898], + &s_operands[1903], + &s_operands[1904], 3, }, { SpirvOp::OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL, R"(OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL)", - &s_operands[1901], + &s_operands[1906], + &s_operands[1907], 3, }, { SpirvOp::OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL, R"(OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL)", - &s_operands[1904], + &s_operands[1909], + &s_operands[1910], 3, }, { SpirvOp::OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL, R"(OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL)", - &s_operands[1907], + &s_operands[1912], + &s_operands[1913], 3, }, { SpirvOp::OpSubgroupAvcFmeInitializeINTEL, R"(OpSubgroupAvcFmeInitializeINTEL)", - &s_operands[1910], + &s_operands[1915], + &s_operands[1916], 9, }, { SpirvOp::OpSubgroupAvcBmeInitializeINTEL, R"(OpSubgroupAvcBmeInitializeINTEL)", - &s_operands[1919], + &s_operands[1924], + &s_operands[1925], 10, }, { SpirvOp::OpSubgroupAvcRefConvertToMcePayloadINTEL, R"(OpSubgroupAvcRefConvertToMcePayloadINTEL)", - &s_operands[1929], + &s_operands[1934], + &s_operands[1935], 3, }, { SpirvOp::OpSubgroupAvcRefSetBidirectionalMixDisableINTEL, R"(OpSubgroupAvcRefSetBidirectionalMixDisableINTEL)", - &s_operands[1932], + &s_operands[1937], + &s_operands[1938], 3, }, { SpirvOp::OpSubgroupAvcRefSetBilinearFilterEnableINTEL, R"(OpSubgroupAvcRefSetBilinearFilterEnableINTEL)", - &s_operands[1935], + &s_operands[1940], + &s_operands[1941], 3, }, { SpirvOp::OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL, R"(OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL)", - &s_operands[1938], + &s_operands[1943], + &s_operands[1944], 5, }, { SpirvOp::OpSubgroupAvcRefEvaluateWithDualReferenceINTEL, R"(OpSubgroupAvcRefEvaluateWithDualReferenceINTEL)", - &s_operands[1943], + &s_operands[1948], + &s_operands[1949], 6, }, { SpirvOp::OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL, R"(OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL)", - &s_operands[1949], + &s_operands[1954], + &s_operands[1955], 5, }, { SpirvOp::OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL, R"(OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL)", - &s_operands[1954], + &s_operands[1959], + &s_operands[1960], 6, }, { SpirvOp::OpSubgroupAvcRefConvertToMceResultINTEL, R"(OpSubgroupAvcRefConvertToMceResultINTEL)", - &s_operands[1960], + &s_operands[1965], + &s_operands[1966], 3, }, { SpirvOp::OpSubgroupAvcSicInitializeINTEL, R"(OpSubgroupAvcSicInitializeINTEL)", - &s_operands[1963], + &s_operands[1968], + &s_operands[1969], 3, }, { SpirvOp::OpSubgroupAvcSicConfigureSkcINTEL, R"(OpSubgroupAvcSicConfigureSkcINTEL)", - &s_operands[1966], + &s_operands[1971], + &s_operands[1972], 8, }, { SpirvOp::OpSubgroupAvcSicConfigureIpeLumaINTEL, R"(OpSubgroupAvcSicConfigureIpeLumaINTEL)", - &s_operands[1974], + &s_operands[1979], + &s_operands[1980], 10, }, { SpirvOp::OpSubgroupAvcSicConfigureIpeLumaChromaINTEL, R"(OpSubgroupAvcSicConfigureIpeLumaChromaINTEL)", - &s_operands[1984], + &s_operands[1989], + &s_operands[1990], 13, }, { SpirvOp::OpSubgroupAvcSicGetMotionVectorMaskINTEL, R"(OpSubgroupAvcSicGetMotionVectorMaskINTEL)", - &s_operands[1997], + &s_operands[2002], + &s_operands[2003], 4, }, { SpirvOp::OpSubgroupAvcSicConvertToMcePayloadINTEL, R"(OpSubgroupAvcSicConvertToMcePayloadINTEL)", - &s_operands[2001], + &s_operands[2006], + &s_operands[2007], 3, }, { SpirvOp::OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL, R"(OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL)", - &s_operands[2004], + &s_operands[2009], + &s_operands[2010], 4, }, { SpirvOp::OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL, R"(OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL)", - &s_operands[2008], + &s_operands[2013], + &s_operands[2014], 6, }, { SpirvOp::OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL, R"(OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL)", - &s_operands[2014], + &s_operands[2019], + &s_operands[2020], 4, }, { SpirvOp::OpSubgroupAvcSicSetBilinearFilterEnableINTEL, R"(OpSubgroupAvcSicSetBilinearFilterEnableINTEL)", - &s_operands[2018], + &s_operands[2023], + &s_operands[2024], 3, }, { SpirvOp::OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL, R"(OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL)", - &s_operands[2021], + &s_operands[2026], + &s_operands[2027], 4, }, { SpirvOp::OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL, R"(OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL)", - &s_operands[2025], + &s_operands[2030], + &s_operands[2031], 4, }, { SpirvOp::OpSubgroupAvcSicEvaluateIpeINTEL, R"(OpSubgroupAvcSicEvaluateIpeINTEL)", - &s_operands[2029], + &s_operands[2034], + &s_operands[2035], 4, }, { SpirvOp::OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL, R"(OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL)", - &s_operands[2033], + &s_operands[2038], + &s_operands[2039], 5, }, { SpirvOp::OpSubgroupAvcSicEvaluateWithDualReferenceINTEL, R"(OpSubgroupAvcSicEvaluateWithDualReferenceINTEL)", - &s_operands[2038], + &s_operands[2043], + &s_operands[2044], 6, }, { SpirvOp::OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL, R"(OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL)", - &s_operands[2044], + &s_operands[2049], + &s_operands[2050], 5, }, { SpirvOp::OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL, R"(OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL)", - &s_operands[2049], + &s_operands[2054], + &s_operands[2055], 6, }, { SpirvOp::OpSubgroupAvcSicConvertToMceResultINTEL, R"(OpSubgroupAvcSicConvertToMceResultINTEL)", - &s_operands[2055], + &s_operands[2060], + &s_operands[2061], 3, }, { SpirvOp::OpSubgroupAvcSicGetIpeLumaShapeINTEL, R"(OpSubgroupAvcSicGetIpeLumaShapeINTEL)", - &s_operands[2058], + &s_operands[2063], + &s_operands[2064], 3, }, { SpirvOp::OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL, R"(OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL)", - &s_operands[2061], + &s_operands[2066], + &s_operands[2067], 3, }, { SpirvOp::OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL, R"(OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL)", - &s_operands[2064], + &s_operands[2069], + &s_operands[2070], 3, }, { SpirvOp::OpSubgroupAvcSicGetPackedIpeLumaModesINTEL, R"(OpSubgroupAvcSicGetPackedIpeLumaModesINTEL)", - &s_operands[2067], + &s_operands[2072], + &s_operands[2073], 3, }, { SpirvOp::OpSubgroupAvcSicGetIpeChromaModeINTEL, R"(OpSubgroupAvcSicGetIpeChromaModeINTEL)", - &s_operands[2070], + &s_operands[2075], + &s_operands[2076], 3, }, { SpirvOp::OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL, R"(OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL)", - &s_operands[2073], + &s_operands[2078], + &s_operands[2079], 3, }, { SpirvOp::OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL, R"(OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL)", - &s_operands[2076], + &s_operands[2081], + &s_operands[2082], 3, }, { SpirvOp::OpSubgroupAvcSicGetInterRawSadsINTEL, R"(OpSubgroupAvcSicGetInterRawSadsINTEL)", - &s_operands[2079], + &s_operands[2084], + &s_operands[2085], 3, }, { SpirvOp::OpVariableLengthArrayINTEL, R"(OpVariableLengthArrayINTEL)", - &s_operands[2082], + &s_operands[2087], + &s_operands[2088], 3, }, { SpirvOp::OpSaveMemoryINTEL, R"(OpSaveMemoryINTEL)", - &s_operands[2085], + &s_operands[2090], + &s_operands[2091], 2, }, { SpirvOp::OpRestoreMemoryINTEL, R"(OpRestoreMemoryINTEL)", - &s_operands[2087], + &s_operands[2092], + nullptr, 1, }, { SpirvOp::OpLoopControlINTEL, R"(OpLoopControlINTEL)", - &s_operands[2088], + &s_operands[2093], + nullptr, 1, }, { SpirvOp::OpPtrCastToCrossWorkgroupINTEL, R"(OpPtrCastToCrossWorkgroupINTEL)", - &s_operands[2089], + &s_operands[2094], + &s_operands[2095], 3, }, { SpirvOp::OpCrossWorkgroupCastToPtrINTEL, R"(OpCrossWorkgroupCastToPtrINTEL)", - &s_operands[2092], + &s_operands[2097], + &s_operands[2098], 3, }, { SpirvOp::OpReadPipeBlockingINTEL, R"(OpReadPipeBlockingINTEL)", - &s_operands[2095], + &s_operands[2100], + &s_operands[2101], 4, }, { SpirvOp::OpWritePipeBlockingINTEL, R"(OpWritePipeBlockingINTEL)", - &s_operands[2099], + &s_operands[2104], + &s_operands[2105], 4, }, { SpirvOp::OpFPGARegINTEL, R"(OpFPGARegINTEL)", - &s_operands[2103], + &s_operands[2108], + &s_operands[2109], 4, }, { SpirvOp::OpRayQueryGetRayTMinKHR, R"(OpRayQueryGetRayTMinKHR)", - &s_operands[2107], + &s_operands[2112], + &s_operands[2113], 3, }, { SpirvOp::OpRayQueryGetRayFlagsKHR, R"(OpRayQueryGetRayFlagsKHR)", - &s_operands[2110], + &s_operands[2115], + &s_operands[2116], 3, }, { SpirvOp::OpRayQueryGetIntersectionTKHR, R"(OpRayQueryGetIntersectionTKHR)", - &s_operands[2113], + &s_operands[2118], + &s_operands[2119], 4, }, { SpirvOp::OpRayQueryGetIntersectionInstanceCustomIndexKHR, R"(OpRayQueryGetIntersectionInstanceCustomIndexKHR)", - &s_operands[2117], + &s_operands[2122], + &s_operands[2123], 4, }, { SpirvOp::OpRayQueryGetIntersectionInstanceIdKHR, R"(OpRayQueryGetIntersectionInstanceIdKHR)", - &s_operands[2121], + &s_operands[2126], + &s_operands[2127], 4, }, { SpirvOp::OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR, R"(OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR)", - &s_operands[2125], + &s_operands[2130], + &s_operands[2131], 4, }, { SpirvOp::OpRayQueryGetIntersectionGeometryIndexKHR, R"(OpRayQueryGetIntersectionGeometryIndexKHR)", - &s_operands[2129], + &s_operands[2134], + &s_operands[2135], 4, }, { SpirvOp::OpRayQueryGetIntersectionPrimitiveIndexKHR, R"(OpRayQueryGetIntersectionPrimitiveIndexKHR)", - &s_operands[2133], + &s_operands[2138], + &s_operands[2139], 4, }, { SpirvOp::OpRayQueryGetIntersectionBarycentricsKHR, R"(OpRayQueryGetIntersectionBarycentricsKHR)", - &s_operands[2137], + &s_operands[2142], + &s_operands[2143], 4, }, { SpirvOp::OpRayQueryGetIntersectionFrontFaceKHR, R"(OpRayQueryGetIntersectionFrontFaceKHR)", - &s_operands[2141], + &s_operands[2146], + &s_operands[2147], 4, }, { SpirvOp::OpRayQueryGetIntersectionCandidateAABBOpaqueKHR, R"(OpRayQueryGetIntersectionCandidateAABBOpaqueKHR)", - &s_operands[2145], + &s_operands[2150], + &s_operands[2151], 3, }, { SpirvOp::OpRayQueryGetIntersectionObjectRayDirectionKHR, R"(OpRayQueryGetIntersectionObjectRayDirectionKHR)", - &s_operands[2148], + &s_operands[2153], + &s_operands[2154], 4, }, { SpirvOp::OpRayQueryGetIntersectionObjectRayOriginKHR, R"(OpRayQueryGetIntersectionObjectRayOriginKHR)", - &s_operands[2152], + &s_operands[2157], + &s_operands[2158], 4, }, { SpirvOp::OpRayQueryGetWorldRayDirectionKHR, R"(OpRayQueryGetWorldRayDirectionKHR)", - &s_operands[2156], + &s_operands[2161], + &s_operands[2162], 3, }, { SpirvOp::OpRayQueryGetWorldRayOriginKHR, R"(OpRayQueryGetWorldRayOriginKHR)", - &s_operands[2159], + &s_operands[2164], + &s_operands[2165], 3, }, { SpirvOp::OpRayQueryGetIntersectionObjectToWorldKHR, R"(OpRayQueryGetIntersectionObjectToWorldKHR)", - &s_operands[2162], + &s_operands[2167], + &s_operands[2168], 4, }, { SpirvOp::OpRayQueryGetIntersectionWorldToObjectKHR, R"(OpRayQueryGetIntersectionWorldToObjectKHR)", - &s_operands[2166], + &s_operands[2171], + &s_operands[2172], 4, }, { SpirvOp::OpAtomicFAddEXT, R"(OpAtomicFAddEXT)", - &s_operands[2170], + &s_operands[2175], + &s_operands[2176], 6, }, { SpirvOp::OpTypeBufferSurfaceINTEL, R"(OpTypeBufferSurfaceINTEL)", - &s_operands[2176], + &s_operands[2181], + &s_operands[2181], 1, }, { SpirvOp::OpTypeStructContinuedINTEL, R"(OpTypeStructContinuedINTEL)", - &s_operands[2177], + &s_operands[2182], + nullptr, 1, }, { SpirvOp::OpConstantCompositeContinuedINTEL, R"(OpConstantCompositeContinuedINTEL)", - &s_operands[2178], + &s_operands[2183], + nullptr, 1, }, { SpirvOp::OpSpecConstantCompositeContinuedINTEL, R"(OpSpecConstantCompositeContinuedINTEL)", - &s_operands[2179], + &s_operands[2184], + nullptr, 1, }, } From a318b28cd6096f46c19d196d6fa0d656ed01a414 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sat, 13 Mar 2021 16:09:18 +0100 Subject: [PATCH 085/278] Shader: Improve SpirvPrinter output --- src/Nazara/Shader/SpirvPrinter.cpp | 241 ++++++++++++++++------------- 1 file changed, 133 insertions(+), 108 deletions(-) diff --git a/src/Nazara/Shader/SpirvPrinter.cpp b/src/Nazara/Shader/SpirvPrinter.cpp index 180a54d68..01eb65cb0 100644 --- a/src/Nazara/Shader/SpirvPrinter.cpp +++ b/src/Nazara/Shader/SpirvPrinter.cpp @@ -4,9 +4,10 @@ #include #include +#include #include -#include #include +#include #include #include #include @@ -21,6 +22,7 @@ namespace Nz } const UInt32* codepoints; + std::size_t resultOffset; std::size_t index = 0; std::size_t count; std::ostringstream stream; @@ -37,14 +39,14 @@ namespace Nz CallOnExit resetOnExit([&] { m_currentState = nullptr; }); UInt32 magicNumber = ReadWord(); - if (magicNumber != SpvMagicNumber) + if (magicNumber != SpirvMagicNumber) throw std::runtime_error("invalid Spir-V: magic number didn't match"); if (m_currentState->settings.printHeader) m_currentState->stream << "Spir-V module\n"; UInt32 versionNumber = ReadWord(); - if (versionNumber > SpvVersion) + if (versionNumber > SpirvVersion) throw std::runtime_error("Spir-V is more recent than printer, dismissing"); UInt8 majorVersion = ((versionNumber) >> 16) & 0xFF; @@ -54,6 +56,8 @@ namespace Nz UInt32 bound = ReadWord(); UInt32 schema = ReadWord(); + state.resultOffset = std::snprintf(nullptr, 0, "%%%u = ", bound); + if (m_currentState->settings.printHeader) { m_currentState->stream << "Version " + std::to_string(+majorVersion) << "." << std::to_string(+minorVersion) << "\n"; @@ -81,134 +85,155 @@ namespace Nz if (!inst) throw std::runtime_error("invalid instruction"); - m_currentState->stream << inst->name; - if (m_currentState->settings.printParameters) { + std::ostringstream instructionStream; + instructionStream << inst->name; + + UInt32 resultId = 0; + std::size_t currentOperand = 0; std::size_t instructionEnd = startIndex + wordCount; while (m_currentState->index < instructionEnd) { const SpirvInstruction::Operand* operand = &inst->operands[currentOperand]; - m_currentState->stream << " " << operand->name << "("; - - switch (operand->kind) + if (operand->kind != SpirvOperandKind::IdResult) { - case SpirvOperandKind::ImageOperands: - case SpirvOperandKind::FPFastMathMode: - case SpirvOperandKind::SelectionControl: - case SpirvOperandKind::LoopControl: - case SpirvOperandKind::FunctionControl: - case SpirvOperandKind::MemorySemantics: - case SpirvOperandKind::MemoryAccess: - case SpirvOperandKind::KernelProfilingInfo: - case SpirvOperandKind::RayFlags: - case SpirvOperandKind::SourceLanguage: - case SpirvOperandKind::ExecutionModel: - case SpirvOperandKind::AddressingModel: - case SpirvOperandKind::MemoryModel: - case SpirvOperandKind::ExecutionMode: - case SpirvOperandKind::StorageClass: - case SpirvOperandKind::Dim: - case SpirvOperandKind::SamplerAddressingMode: - case SpirvOperandKind::SamplerFilterMode: - case SpirvOperandKind::ImageFormat: - case SpirvOperandKind::ImageChannelOrder: - case SpirvOperandKind::ImageChannelDataType: - case SpirvOperandKind::FPRoundingMode: - case SpirvOperandKind::LinkageType: - case SpirvOperandKind::AccessQualifier: - case SpirvOperandKind::FunctionParameterAttribute: - case SpirvOperandKind::Decoration: - case SpirvOperandKind::BuiltIn: - case SpirvOperandKind::Scope: - case SpirvOperandKind::GroupOperation: - case SpirvOperandKind::KernelEnqueueFlags: - case SpirvOperandKind::Capability: - case SpirvOperandKind::RayQueryIntersection: - case SpirvOperandKind::RayQueryCommittedIntersectionType: - case SpirvOperandKind::RayQueryCandidateIntersectionType: - case SpirvOperandKind::IdResultType: - case SpirvOperandKind::IdResult: - case SpirvOperandKind::IdMemorySemantics: - case SpirvOperandKind::IdScope: - case SpirvOperandKind::IdRef: - case SpirvOperandKind::LiteralInteger: - case SpirvOperandKind::LiteralExtInstInteger: - case SpirvOperandKind::LiteralSpecConstantOpInteger: - case SpirvOperandKind::LiteralContextDependentNumber: //< FIXME + switch (operand->kind) { - UInt32 value = ReadWord(); - m_currentState->stream << value; - break; - } - - case SpirvOperandKind::LiteralString: - { - std::string str = ReadString(); - m_currentState->stream << "\"" << str << "\""; - - /* - std::size_t offset = GetOutputOffset(); - - std::size_t size4 = CountWord(str); - for (std::size_t i = 0; i < size4; ++i) + case SpirvOperandKind::IdRef: + case SpirvOperandKind::IdResultType: + case SpirvOperandKind::IdMemorySemantics: + case SpirvOperandKind::IdScope: { - UInt32 codepoint = 0; - for (std::size_t j = 0; j < 4; ++j) - { - std::size_t pos = i * 4 + j; - if (pos < str.size()) - codepoint |= UInt32(str[pos]) << (j * 8); - } - - Append(codepoint); + UInt32 value = ReadWord(); + instructionStream << " %" << value; + break; + } + + case SpirvOperandKind::ImageOperands: + case SpirvOperandKind::FPFastMathMode: + case SpirvOperandKind::SelectionControl: + case SpirvOperandKind::LoopControl: + case SpirvOperandKind::FunctionControl: + case SpirvOperandKind::MemorySemantics: + case SpirvOperandKind::MemoryAccess: + case SpirvOperandKind::KernelProfilingInfo: + case SpirvOperandKind::RayFlags: + case SpirvOperandKind::SourceLanguage: + case SpirvOperandKind::ExecutionModel: + case SpirvOperandKind::AddressingModel: + case SpirvOperandKind::MemoryModel: + case SpirvOperandKind::ExecutionMode: + case SpirvOperandKind::StorageClass: + case SpirvOperandKind::Dim: + case SpirvOperandKind::SamplerAddressingMode: + case SpirvOperandKind::SamplerFilterMode: + case SpirvOperandKind::ImageFormat: + case SpirvOperandKind::ImageChannelOrder: + case SpirvOperandKind::ImageChannelDataType: + case SpirvOperandKind::FPRoundingMode: + case SpirvOperandKind::LinkageType: + case SpirvOperandKind::AccessQualifier: + case SpirvOperandKind::FunctionParameterAttribute: + case SpirvOperandKind::Decoration: + case SpirvOperandKind::BuiltIn: + case SpirvOperandKind::Scope: + case SpirvOperandKind::GroupOperation: + case SpirvOperandKind::KernelEnqueueFlags: + case SpirvOperandKind::Capability: + case SpirvOperandKind::RayQueryIntersection: + case SpirvOperandKind::RayQueryCommittedIntersectionType: + case SpirvOperandKind::RayQueryCandidateIntersectionType: + case SpirvOperandKind::LiteralInteger: + case SpirvOperandKind::LiteralExtInstInteger: + case SpirvOperandKind::LiteralSpecConstantOpInteger: + case SpirvOperandKind::LiteralContextDependentNumber: //< FIXME + { + UInt32 value = ReadWord(); + instructionStream << " " << operand->name << "(" << value << ")"; + break; + } + + case SpirvOperandKind::LiteralString: + { + std::string str = ReadString(); + instructionStream << " \"" << str << "\""; + + /* + std::size_t offset = GetOutputOffset(); + + std::size_t size4 = CountWord(str); + for (std::size_t i = 0; i < size4; ++i) + { + UInt32 codepoint = 0; + for (std::size_t j = 0; j < 4; ++j) + { + std::size_t pos = i * 4 + j; + if (pos < str.size()) + codepoint |= UInt32(str[pos]) << (j * 8); + } + + Append(codepoint); + } + */ + break; } - */ - break; - } - case SpirvOperandKind::PairLiteralIntegerIdRef: - { - ReadWord(); - ReadWord(); - break; + case SpirvOperandKind::PairLiteralIntegerIdRef: + { + ReadWord(); + ReadWord(); + break; + } + + case SpirvOperandKind::PairIdRefLiteralInteger: + { + ReadWord(); + ReadWord(); + break; + } + + case SpirvOperandKind::PairIdRefIdRef: + { + ReadWord(); + ReadWord(); + break; + } + + /*case SpirvOperandKind::LiteralContextDependentNumber: + { + throw std::runtime_error("not yet implemented"); + }*/ + + default: + break; + } - - case SpirvOperandKind::PairIdRefLiteralInteger: - { - ReadWord(); - ReadWord(); - break; - } - - case SpirvOperandKind::PairIdRefIdRef: - { - ReadWord(); - ReadWord(); - break; - } - - /*case SpirvOperandKind::LiteralContextDependentNumber: - { - throw std::runtime_error("not yet implemented"); - }*/ - - default: - break; - } - - m_currentState->stream << ")"; + else + resultId = ReadWord(); if (currentOperand < inst->minOperandCount - 1) currentOperand++; } + + if (resultId != 0) + { + std::string resultInfo = "%" + std::to_string(resultId) + " = "; + m_currentState->stream << std::setw(m_currentState->resultOffset) << resultInfo; + } + else + m_currentState->stream << std::string(m_currentState->resultOffset, ' '); + + m_currentState->stream << instructionStream.str(); } else { + m_currentState->stream << inst->name; + m_currentState->index += wordCount - 1; if (m_currentState->index > m_currentState->count) throw std::runtime_error("unexpected end of stream"); From 9d8ce8f2cdae122fef48a690d158c909ad11a9d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sat, 13 Mar 2021 16:10:01 +0100 Subject: [PATCH 086/278] Shader: Add support for function attributes (entry) --- include/Nazara/Shader/ShaderAstCache.hpp | 1 + include/Nazara/Shader/ShaderBuilder.hpp | 1 + include/Nazara/Shader/ShaderBuilder.inl | 12 +++++ include/Nazara/Shader/ShaderLangParser.hpp | 6 +-- include/Nazara/Shader/ShaderNodes.hpp | 1 + src/Nazara/Shader/ShaderAstCloner.cpp | 1 + src/Nazara/Shader/ShaderAstExpressionType.cpp | 2 +- src/Nazara/Shader/ShaderAstSerializer.cpp | 7 +++ src/Nazara/Shader/ShaderAstValidator.cpp | 54 ++++++++++++++++--- src/Nazara/Shader/ShaderLangParser.cpp | 33 ++++++++++-- src/Nazara/Shader/SpirvWriter.cpp | 34 +++++++----- 11 files changed, 123 insertions(+), 29 deletions(-) diff --git a/include/Nazara/Shader/ShaderAstCache.hpp b/include/Nazara/Shader/ShaderAstCache.hpp index 595b6b410..6e1b0a144 100644 --- a/include/Nazara/Shader/ShaderAstCache.hpp +++ b/include/Nazara/Shader/ShaderAstCache.hpp @@ -37,6 +37,7 @@ namespace Nz::ShaderAst inline std::size_t GetScopeId(const Node* node) const; ShaderStageType stageType = ShaderStageType::Undefined; + std::array entryFunctions = {}; std::unordered_map nodeExpressionType; std::unordered_map scopeIdByNode; std::vector scopes; diff --git a/include/Nazara/Shader/ShaderBuilder.hpp b/include/Nazara/Shader/ShaderBuilder.hpp index 6a18b25ed..625875470 100644 --- a/include/Nazara/Shader/ShaderBuilder.hpp +++ b/include/Nazara/Shader/ShaderBuilder.hpp @@ -34,6 +34,7 @@ namespace Nz::ShaderBuilder struct DeclareFunction { inline std::unique_ptr operator()(std::string name, std::vector parameters, std::vector statements, ShaderAst::ShaderExpressionType returnType = ShaderAst::BasicType::Void) const; + inline std::unique_ptr operator()(std::vector attributes, std::string name, std::vector parameters, std::vector statements, ShaderAst::ShaderExpressionType returnType = ShaderAst::BasicType::Void) const; }; struct DeclareVariable diff --git a/include/Nazara/Shader/ShaderBuilder.inl b/include/Nazara/Shader/ShaderBuilder.inl index ef7e89849..31fb4dcf9 100644 --- a/include/Nazara/Shader/ShaderBuilder.inl +++ b/include/Nazara/Shader/ShaderBuilder.inl @@ -58,6 +58,18 @@ namespace Nz::ShaderBuilder return declareFunctionNode; } + inline std::unique_ptr Impl::DeclareFunction::operator()(std::vector attributes, std::string name, std::vector parameters, std::vector statements, ShaderAst::ShaderExpressionType returnType) const + { + auto declareFunctionNode = std::make_unique(); + declareFunctionNode->attributes = std::move(attributes); + declareFunctionNode->name = std::move(name); + declareFunctionNode->parameters = std::move(parameters); + declareFunctionNode->returnType = std::move(returnType); + declareFunctionNode->statements = std::move(statements); + + return declareFunctionNode; + } + inline std::unique_ptr Nz::ShaderBuilder::Impl::DeclareVariable::operator()(std::string name, ShaderAst::ShaderExpressionType type, ShaderAst::ExpressionPtr initialValue) const { auto declareVariableNode = std::make_unique(); diff --git a/include/Nazara/Shader/ShaderLangParser.hpp b/include/Nazara/Shader/ShaderLangParser.hpp index 785136702..ba727b73a 100644 --- a/include/Nazara/Shader/ShaderLangParser.hpp +++ b/include/Nazara/Shader/ShaderLangParser.hpp @@ -57,14 +57,15 @@ namespace Nz::ShaderLang const Token& Advance(); void Consume(std::size_t count = 1); const Token& Expect(const Token& token, TokenType type); + const Token& ExpectNot(const Token& token, TokenType type); const Token& Expect(TokenType type); const Token& Peek(std::size_t advance = 0); - std::vector ParseAttributes(); + void HandleAttributes(); // Statements std::vector ParseFunctionBody(); - ShaderAst::StatementPtr ParseFunctionDeclaration(); + ShaderAst::StatementPtr ParseFunctionDeclaration(std::vector attributes = {}); ShaderAst::DeclareFunctionStatement::Parameter ParseFunctionParameter(); ShaderAst::StatementPtr ParseReturnStatement(); ShaderAst::StatementPtr ParseStatement(); @@ -87,7 +88,6 @@ namespace Nz::ShaderLang struct Context { - std::vector pendingAttributes; std::unique_ptr root; std::size_t tokenCount; std::size_t tokenIndex = 0; diff --git a/include/Nazara/Shader/ShaderNodes.hpp b/include/Nazara/Shader/ShaderNodes.hpp index 4e532ad14..386f53168 100644 --- a/include/Nazara/Shader/ShaderNodes.hpp +++ b/include/Nazara/Shader/ShaderNodes.hpp @@ -201,6 +201,7 @@ namespace Nz::ShaderAst }; std::string name; + std::vector attributes; std::vector parameters; std::vector statements; ShaderExpressionType returnType = BasicType::Void; diff --git a/src/Nazara/Shader/ShaderAstCloner.cpp b/src/Nazara/Shader/ShaderAstCloner.cpp index 2948cd753..ea7ed0276 100644 --- a/src/Nazara/Shader/ShaderAstCloner.cpp +++ b/src/Nazara/Shader/ShaderAstCloner.cpp @@ -165,6 +165,7 @@ namespace Nz::ShaderAst void AstCloner::Visit(DeclareFunctionStatement& node) { auto clone = std::make_unique(); + clone->attributes = node.attributes; clone->name = node.name; clone->parameters = node.parameters; clone->returnType = node.returnType; diff --git a/src/Nazara/Shader/ShaderAstExpressionType.cpp b/src/Nazara/Shader/ShaderAstExpressionType.cpp index 9a6b394d7..71f831f69 100644 --- a/src/Nazara/Shader/ShaderAstExpressionType.cpp +++ b/src/Nazara/Shader/ShaderAstExpressionType.cpp @@ -192,7 +192,7 @@ namespace Nz::ShaderAst void ExpressionTypeVisitor::Visit(SwizzleExpression& node) { - const ShaderExpressionType& exprType = GetExpressionTypeInternal(*node.expression); + ShaderExpressionType exprType = GetExpressionTypeInternal(*node.expression); assert(IsBasicType(exprType)); m_lastExpressionType = static_cast(UnderlyingCast(GetComponentType(std::get(exprType))) + node.componentCount - 1); diff --git a/src/Nazara/Shader/ShaderAstSerializer.cpp b/src/Nazara/Shader/ShaderAstSerializer.cpp index 4100a0204..b078a53f8 100644 --- a/src/Nazara/Shader/ShaderAstSerializer.cpp +++ b/src/Nazara/Shader/ShaderAstSerializer.cpp @@ -157,6 +157,13 @@ namespace Nz::ShaderAst Value(node.name); Type(node.returnType); + Container(node.attributes); + for (auto& attribute : node.attributes) + { + Enum(attribute.type); + Value(attribute.args); + } + Container(node.parameters); for (auto& parameter : node.parameters) { diff --git a/src/Nazara/Shader/ShaderAstValidator.cpp b/src/Nazara/Shader/ShaderAstValidator.cpp index 0e5d8f52f..2c41cf999 100644 --- a/src/Nazara/Shader/ShaderAstValidator.cpp +++ b/src/Nazara/Shader/ShaderAstValidator.cpp @@ -6,11 +6,21 @@ #include #include #include +#include #include #include namespace Nz::ShaderAst { + namespace + { + std::unordered_map entryPoints = { + { "frag", ShaderStageType::Fragment }, + { "vert", ShaderStageType::Vertex }, + }; + + } + struct AstError { std::string errMsg; @@ -135,7 +145,7 @@ namespace Nz::ShaderAst { RegisterScope(node); - const ShaderExpressionType& exprType = GetExpressionType(MandatoryExpr(node.structExpr), m_context->cache); + ShaderExpressionType exprType = GetExpressionType(MandatoryExpr(node.structExpr), m_context->cache); if (!IsStructType(exprType)) throw AstError{ "expression is not a structure" }; @@ -165,11 +175,11 @@ namespace Nz::ShaderAst // Register expression type AstRecursiveVisitor::Visit(node); - const ShaderExpressionType& leftExprType = GetExpressionType(MandatoryExpr(node.left), m_context->cache); + ShaderExpressionType leftExprType = GetExpressionType(MandatoryExpr(node.left), m_context->cache); if (!IsBasicType(leftExprType)) throw AstError{ "left expression type does not support binary operation" }; - const ShaderExpressionType& rightExprType = GetExpressionType(MandatoryExpr(node.right), m_context->cache); + ShaderExpressionType rightExprType = GetExpressionType(MandatoryExpr(node.right), m_context->cache); if (!IsBasicType(rightExprType)) throw AstError{ "right expression type does not support binary operation" }; @@ -349,7 +359,7 @@ namespace Nz::ShaderAst if (node.componentCount > 4) throw AstError{ "Cannot swizzle more than four elements" }; - const ShaderExpressionType& exprType = GetExpressionType(MandatoryExpr(node.expression), m_context->cache); + ShaderExpressionType exprType = GetExpressionType(MandatoryExpr(node.expression), m_context->cache); if (!IsBasicType(exprType)) throw AstError{ "Cannot swizzle this type" }; @@ -378,7 +388,7 @@ namespace Nz::ShaderAst for (auto& condStatement : node.condStatements) { - const ShaderExpressionType& condType = GetExpressionType(MandatoryExpr(condStatement.condition), m_context->cache); + ShaderExpressionType condType = GetExpressionType(MandatoryExpr(condStatement.condition), m_context->cache); if (!IsBasicType(condType) || std::get(condType) != BasicType::Boolean) throw AstError{ "if expression must resolve to boolean type" }; @@ -401,8 +411,40 @@ namespace Nz::ShaderAst void AstValidator::Visit(DeclareFunctionStatement& node) { - auto& scope = EnterScope(); + bool hasEntry = false; + for (const auto& [attributeType, arg] : node.attributes) + { + switch (attributeType) + { + case AttributeType::Entry: + { + if (hasEntry) + throw AstError{ "attribute entry must be present once" }; + if (arg.empty()) + throw AstError{ "attribute entry requires a parameter" }; + + auto it = entryPoints.find(arg); + if (it == entryPoints.end()) + throw AstError{ "invalid parameter " + arg + " for entry attribute" }; + + ShaderStageType stageType = it->second; + + if (m_context->cache->entryFunctions[UnderlyingCast(stageType)]) + throw AstError{ "the same entry type has been defined multiple times" }; + + m_context->cache->entryFunctions[UnderlyingCast(it->second)] = &node; + + hasEntry = true; + break; + } + + default: + throw AstError{ "unhandled attribute for function" }; + } + } + + auto& scope = EnterScope(); RegisterScope(node); for (auto& parameter : node.parameters) diff --git a/src/Nazara/Shader/ShaderLangParser.cpp b/src/Nazara/Shader/ShaderLangParser.cpp index 4cd73eedc..c2a05aad3 100644 --- a/src/Nazara/Shader/ShaderLangParser.cpp +++ b/src/Nazara/Shader/ShaderLangParser.cpp @@ -57,7 +57,7 @@ namespace Nz::ShaderLang switch (nextToken.type) { case TokenType::OpenAttribute: - context.pendingAttributes = ParseAttributes(); + HandleAttributes(); break; case TokenType::FunctionDeclaration: @@ -98,6 +98,14 @@ namespace Nz::ShaderLang return token; } + const Token& Parser::ExpectNot(const Token& token, TokenType type) + { + if (token.type == type) + throw ExpectedToken{}; + + return token; + } + const Token& Parser::Expect(TokenType type) { const Token& token = Peek(); @@ -112,7 +120,7 @@ namespace Nz::ShaderLang return m_context->tokens[m_context->tokenIndex + advance]; } - std::vector Parser::ParseAttributes() + void Parser::HandleAttributes() { std::vector attributes; @@ -122,6 +130,8 @@ namespace Nz::ShaderLang for (;;) { const Token& t = Peek(); + ExpectNot(t, TokenType::EndOfStream); + if (t.type == TokenType::ClosingAttribute) { // Parse [[attribute1]] [[attribute2]] the same as [[attribute1, attribute2]] @@ -161,7 +171,16 @@ namespace Nz::ShaderLang Expect(Advance(), TokenType::ClosingAttribute); - return attributes; + const Token& nextToken = Peek(); + switch (nextToken.type) + { + case TokenType::FunctionDeclaration: + m_context->root->statements.push_back(ParseFunctionDeclaration(std::move(attributes))); + break; + + default: + throw UnexpectedToken{}; + } } std::vector Parser::ParseFunctionBody() @@ -169,7 +188,7 @@ namespace Nz::ShaderLang return ParseStatementList(); } - ShaderAst::StatementPtr Parser::ParseFunctionDeclaration() + ShaderAst::StatementPtr Parser::ParseFunctionDeclaration(std::vector attributes) { Expect(Advance(), TokenType::FunctionDeclaration); @@ -183,6 +202,8 @@ namespace Nz::ShaderLang for (;;) { const Token& t = Peek(); + ExpectNot(t, TokenType::EndOfStream); + if (t.type == TokenType::ClosingParenthesis) break; @@ -208,7 +229,7 @@ namespace Nz::ShaderLang Expect(Advance(), TokenType::ClosingCurlyBracket); - return ShaderBuilder::DeclareFunction(std::move(functionName), std::move(parameters), std::move(functionBody), std::move(returnType)); + return ShaderBuilder::DeclareFunction(std::move(attributes), std::move(functionName), std::move(parameters), std::move(functionBody), std::move(returnType)); } ShaderAst::DeclareFunctionStatement::Parameter Parser::ParseFunctionParameter() @@ -262,6 +283,7 @@ namespace Nz::ShaderLang std::vector statements; while (Peek().type != TokenType::ClosingCurlyBracket) { + ExpectNot(Peek(), TokenType::EndOfStream); statements.push_back(ParseStatement()); } @@ -293,6 +315,7 @@ namespace Nz::ShaderLang for (;;) { const Token& currentOp = Peek(); + ExpectNot(currentOp, TokenType::EndOfStream); int tokenPrecedence = GetTokenPrecedence(currentOp.type); if (tokenPrecedence < exprPrecedence) diff --git a/src/Nazara/Shader/SpirvWriter.cpp b/src/Nazara/Shader/SpirvWriter.cpp index c877db5a0..eb52edeca 100644 --- a/src/Nazara/Shader/SpirvWriter.cpp +++ b/src/Nazara/Shader/SpirvWriter.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -172,6 +171,7 @@ namespace Nz struct Func { + const ShaderAst::DeclareFunctionStatement* statement = nullptr; UInt32 typeId; UInt32 id; }; @@ -355,6 +355,7 @@ namespace Nz for (const ShaderAst::DeclareFunctionStatement& func : preVisitor.funcs) { auto& funcData = state.funcs.emplace_back(); + funcData.statement = &func; funcData.id = AllocateResultId(); funcData.typeId = GetFunctionTypeId(func); @@ -407,14 +408,21 @@ namespace Nz AppendHeader(); - /*if (entryPointIndex != std::numeric_limits::max()) + for (std::size_t i = 0; i < ShaderStageTypeCount; ++i) { - SpvExecutionModel execModel; - const auto& entryFuncData = shader.GetFunction(entryPointIndex); - const auto& entryFunc = state.funcs[entryPointIndex]; + const ShaderAst::DeclareFunctionStatement* statement = m_context.cache.entryFunctions[i]; + if (!statement) + continue; - assert(m_context.shader); - switch (m_context.shader->GetStage()) + auto it = std::find_if(state.funcs.begin(), state.funcs.end(), [&](const auto& funcData) { return funcData.statement == statement; }); + assert(it != state.funcs.end()); + + const auto& entryFunc = *it; + + SpirvExecutionModel execModel; + + ShaderStageType stage = static_cast(i); + switch (stage) { case ShaderStageType::Fragment: execModel = SpirvExecutionModel::Fragment; @@ -427,14 +435,12 @@ namespace Nz default: throw std::runtime_error("not yet implemented"); } - - // OpEntryPoint Vertex %main "main" %outNormal %inNormals %outTexCoords %inTexCoord %_ %inPos - + state.header.AppendVariadic(SpirvOp::OpEntryPoint, [&](const auto& appender) { appender(execModel); appender(entryFunc.id); - appender(entryFuncData.name); + appender(statement->name); for (const auto& [name, varData] : state.builtinIds) appender(varData.varId); @@ -446,9 +452,9 @@ namespace Nz appender(varData.varId); }); - if (m_context.shader->GetStage() == ShaderStageType::Fragment) + if (stage == ShaderStageType::Fragment) state.header.Append(SpirvOp::OpExecutionMode, entryFunc.id, SpirvExecutionMode::OriginUpperLeft); - }*/ + } std::vector ret; MergeSections(ret, state.header); @@ -472,7 +478,7 @@ namespace Nz void SpirvWriter::AppendHeader() { - m_currentState->header.AppendRaw(SpvMagicNumber); //< Spir-V magic number + m_currentState->header.AppendRaw(SpirvMagicNumber); //< Spir-V magic number UInt32 version = (m_environment.spvMajorVersion << 16) | m_environment.spvMinorVersion << 8; m_currentState->header.AppendRaw(version); //< Spir-V version number (1.0 for compatibility) From 2a73005295ac0a204a1cc39555a4b3beb1eeb575 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sat, 13 Mar 2021 16:10:10 +0100 Subject: [PATCH 087/278] Delete spirv.h --- thirdparty/include/SpirV/spirv.h | 2163 ------------------------------ 1 file changed, 2163 deletions(-) delete mode 100644 thirdparty/include/SpirV/spirv.h diff --git a/thirdparty/include/SpirV/spirv.h b/thirdparty/include/SpirV/spirv.h deleted file mode 100644 index 1e999f27b..000000000 --- a/thirdparty/include/SpirV/spirv.h +++ /dev/null @@ -1,2163 +0,0 @@ -/* -** Copyright (c) 2014-2020 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and/or associated documentation files (the "Materials"), -** to deal in the Materials without restriction, including without limitation -** the rights to use, copy, modify, merge, publish, distribute, sublicense, -** and/or sell copies of the Materials, and to permit persons to whom the -** Materials are furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Materials. -** -** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -** IN THE MATERIALS. -*/ - -/* -** This header is automatically generated by the same tool that creates -** the Binary Section of the SPIR-V specification. -*/ - -/* -** Enumeration tokens for SPIR-V, in various styles: -** C, C++, C++11, JSON, Lua, Python, C#, D -** -** - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL -** - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL -** - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL -** - Lua will use tables, e.g.: spv.SourceLanguage.GLSL -** - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] -** - C# will use enum classes in the Specification class located in the "Spv" namespace, -** e.g.: Spv.Specification.SourceLanguage.GLSL -** - D will have tokens under the "spv" module, e.g: spv.SourceLanguage.GLSL -** -** Some tokens act like mask values, which can be OR'd together, -** while others are mutually exclusive. The mask-like ones have -** "Mask" in their name, and a parallel enum that has the shift -** amount (1 << x) for each corresponding enumerant. -*/ - -#ifndef spirv_H -#define spirv_H - -typedef unsigned int SpvId; - -#define SPV_VERSION 0x10500 -#define SPV_REVISION 3 - -static const unsigned int SpvMagicNumber = 0x07230203; -static const unsigned int SpvVersion = 0x00010500; -static const unsigned int SpvRevision = 3; -static const unsigned int SpvOpCodeMask = 0xffff; -static const unsigned int SpvWordCountShift = 16; - -typedef enum SpvSourceLanguage_ { - SpvSourceLanguageUnknown = 0, - SpvSourceLanguageESSL = 1, - SpvSourceLanguageGLSL = 2, - SpvSourceLanguageOpenCL_C = 3, - SpvSourceLanguageOpenCL_CPP = 4, - SpvSourceLanguageHLSL = 5, - SpvSourceLanguageMax = 0x7fffffff, -} SpvSourceLanguage; - -typedef enum SpvExecutionModel_ { - SpvExecutionModelVertex = 0, - SpvExecutionModelTessellationControl = 1, - SpvExecutionModelTessellationEvaluation = 2, - SpvExecutionModelGeometry = 3, - SpvExecutionModelFragment = 4, - SpvExecutionModelGLCompute = 5, - SpvExecutionModelKernel = 6, - SpvExecutionModelTaskNV = 5267, - SpvExecutionModelMeshNV = 5268, - SpvExecutionModelRayGenerationKHR = 5313, - SpvExecutionModelRayGenerationNV = 5313, - SpvExecutionModelIntersectionKHR = 5314, - SpvExecutionModelIntersectionNV = 5314, - SpvExecutionModelAnyHitKHR = 5315, - SpvExecutionModelAnyHitNV = 5315, - SpvExecutionModelClosestHitKHR = 5316, - SpvExecutionModelClosestHitNV = 5316, - SpvExecutionModelMissKHR = 5317, - SpvExecutionModelMissNV = 5317, - SpvExecutionModelCallableKHR = 5318, - SpvExecutionModelCallableNV = 5318, - SpvExecutionModelMax = 0x7fffffff, -} SpvExecutionModel; - -typedef enum SpvAddressingModel_ { - SpvAddressingModelLogical = 0, - SpvAddressingModelPhysical32 = 1, - SpvAddressingModelPhysical64 = 2, - SpvAddressingModelPhysicalStorageBuffer64 = 5348, - SpvAddressingModelPhysicalStorageBuffer64EXT = 5348, - SpvAddressingModelMax = 0x7fffffff, -} SpvAddressingModel; - -typedef enum SpvMemoryModel_ { - SpvMemoryModelSimple = 0, - SpvMemoryModelGLSL450 = 1, - SpvMemoryModelOpenCL = 2, - SpvMemoryModelVulkan = 3, - SpvMemoryModelVulkanKHR = 3, - SpvMemoryModelMax = 0x7fffffff, -} SpvMemoryModel; - -typedef enum SpvExecutionMode_ { - SpvExecutionModeInvocations = 0, - SpvExecutionModeSpacingEqual = 1, - SpvExecutionModeSpacingFractionalEven = 2, - SpvExecutionModeSpacingFractionalOdd = 3, - SpvExecutionModeVertexOrderCw = 4, - SpvExecutionModeVertexOrderCcw = 5, - SpvExecutionModePixelCenterInteger = 6, - SpvExecutionModeOriginUpperLeft = 7, - SpvExecutionModeOriginLowerLeft = 8, - SpvExecutionModeEarlyFragmentTests = 9, - SpvExecutionModePointMode = 10, - SpvExecutionModeXfb = 11, - SpvExecutionModeDepthReplacing = 12, - SpvExecutionModeDepthGreater = 14, - SpvExecutionModeDepthLess = 15, - SpvExecutionModeDepthUnchanged = 16, - SpvExecutionModeLocalSize = 17, - SpvExecutionModeLocalSizeHint = 18, - SpvExecutionModeInputPoints = 19, - SpvExecutionModeInputLines = 20, - SpvExecutionModeInputLinesAdjacency = 21, - SpvExecutionModeTriangles = 22, - SpvExecutionModeInputTrianglesAdjacency = 23, - SpvExecutionModeQuads = 24, - SpvExecutionModeIsolines = 25, - SpvExecutionModeOutputVertices = 26, - SpvExecutionModeOutputPoints = 27, - SpvExecutionModeOutputLineStrip = 28, - SpvExecutionModeOutputTriangleStrip = 29, - SpvExecutionModeVecTypeHint = 30, - SpvExecutionModeContractionOff = 31, - SpvExecutionModeInitializer = 33, - SpvExecutionModeFinalizer = 34, - SpvExecutionModeSubgroupSize = 35, - SpvExecutionModeSubgroupsPerWorkgroup = 36, - SpvExecutionModeSubgroupsPerWorkgroupId = 37, - SpvExecutionModeLocalSizeId = 38, - SpvExecutionModeLocalSizeHintId = 39, - SpvExecutionModePostDepthCoverage = 4446, - SpvExecutionModeDenormPreserve = 4459, - SpvExecutionModeDenormFlushToZero = 4460, - SpvExecutionModeSignedZeroInfNanPreserve = 4461, - SpvExecutionModeRoundingModeRTE = 4462, - SpvExecutionModeRoundingModeRTZ = 4463, - SpvExecutionModeStencilRefReplacingEXT = 5027, - SpvExecutionModeOutputLinesNV = 5269, - SpvExecutionModeOutputPrimitivesNV = 5270, - SpvExecutionModeDerivativeGroupQuadsNV = 5289, - SpvExecutionModeDerivativeGroupLinearNV = 5290, - SpvExecutionModeOutputTrianglesNV = 5298, - SpvExecutionModePixelInterlockOrderedEXT = 5366, - SpvExecutionModePixelInterlockUnorderedEXT = 5367, - SpvExecutionModeSampleInterlockOrderedEXT = 5368, - SpvExecutionModeSampleInterlockUnorderedEXT = 5369, - SpvExecutionModeShadingRateInterlockOrderedEXT = 5370, - SpvExecutionModeShadingRateInterlockUnorderedEXT = 5371, - SpvExecutionModeMaxWorkgroupSizeINTEL = 5893, - SpvExecutionModeMaxWorkDimINTEL = 5894, - SpvExecutionModeNoGlobalOffsetINTEL = 5895, - SpvExecutionModeNumSIMDWorkitemsINTEL = 5896, - SpvExecutionModeMax = 0x7fffffff, -} SpvExecutionMode; - -typedef enum SpvStorageClass_ { - SpvStorageClassUniformConstant = 0, - SpvStorageClassInput = 1, - SpvStorageClassUniform = 2, - SpvStorageClassOutput = 3, - SpvStorageClassWorkgroup = 4, - SpvStorageClassCrossWorkgroup = 5, - SpvStorageClassPrivate = 6, - SpvStorageClassFunction = 7, - SpvStorageClassGeneric = 8, - SpvStorageClassPushConstant = 9, - SpvStorageClassAtomicCounter = 10, - SpvStorageClassImage = 11, - SpvStorageClassStorageBuffer = 12, - SpvStorageClassCallableDataKHR = 5328, - SpvStorageClassCallableDataNV = 5328, - SpvStorageClassIncomingCallableDataKHR = 5329, - SpvStorageClassIncomingCallableDataNV = 5329, - SpvStorageClassRayPayloadKHR = 5338, - SpvStorageClassRayPayloadNV = 5338, - SpvStorageClassHitAttributeKHR = 5339, - SpvStorageClassHitAttributeNV = 5339, - SpvStorageClassIncomingRayPayloadKHR = 5342, - SpvStorageClassIncomingRayPayloadNV = 5342, - SpvStorageClassShaderRecordBufferKHR = 5343, - SpvStorageClassShaderRecordBufferNV = 5343, - SpvStorageClassPhysicalStorageBuffer = 5349, - SpvStorageClassPhysicalStorageBufferEXT = 5349, - SpvStorageClassCodeSectionINTEL = 5605, - SpvStorageClassMax = 0x7fffffff, -} SpvStorageClass; - -typedef enum SpvDim_ { - SpvDim1D = 0, - SpvDim2D = 1, - SpvDim3D = 2, - SpvDimCube = 3, - SpvDimRect = 4, - SpvDimBuffer = 5, - SpvDimSubpassData = 6, - SpvDimMax = 0x7fffffff, -} SpvDim; - -typedef enum SpvSamplerAddressingMode_ { - SpvSamplerAddressingModeNone = 0, - SpvSamplerAddressingModeClampToEdge = 1, - SpvSamplerAddressingModeClamp = 2, - SpvSamplerAddressingModeRepeat = 3, - SpvSamplerAddressingModeRepeatMirrored = 4, - SpvSamplerAddressingModeMax = 0x7fffffff, -} SpvSamplerAddressingMode; - -typedef enum SpvSamplerFilterMode_ { - SpvSamplerFilterModeNearest = 0, - SpvSamplerFilterModeLinear = 1, - SpvSamplerFilterModeMax = 0x7fffffff, -} SpvSamplerFilterMode; - -typedef enum SpvImageFormat_ { - SpvImageFormatUnknown = 0, - SpvImageFormatRgba32f = 1, - SpvImageFormatRgba16f = 2, - SpvImageFormatR32f = 3, - SpvImageFormatRgba8 = 4, - SpvImageFormatRgba8Snorm = 5, - SpvImageFormatRg32f = 6, - SpvImageFormatRg16f = 7, - SpvImageFormatR11fG11fB10f = 8, - SpvImageFormatR16f = 9, - SpvImageFormatRgba16 = 10, - SpvImageFormatRgb10A2 = 11, - SpvImageFormatRg16 = 12, - SpvImageFormatRg8 = 13, - SpvImageFormatR16 = 14, - SpvImageFormatR8 = 15, - SpvImageFormatRgba16Snorm = 16, - SpvImageFormatRg16Snorm = 17, - SpvImageFormatRg8Snorm = 18, - SpvImageFormatR16Snorm = 19, - SpvImageFormatR8Snorm = 20, - SpvImageFormatRgba32i = 21, - SpvImageFormatRgba16i = 22, - SpvImageFormatRgba8i = 23, - SpvImageFormatR32i = 24, - SpvImageFormatRg32i = 25, - SpvImageFormatRg16i = 26, - SpvImageFormatRg8i = 27, - SpvImageFormatR16i = 28, - SpvImageFormatR8i = 29, - SpvImageFormatRgba32ui = 30, - SpvImageFormatRgba16ui = 31, - SpvImageFormatRgba8ui = 32, - SpvImageFormatR32ui = 33, - SpvImageFormatRgb10a2ui = 34, - SpvImageFormatRg32ui = 35, - SpvImageFormatRg16ui = 36, - SpvImageFormatRg8ui = 37, - SpvImageFormatR16ui = 38, - SpvImageFormatR8ui = 39, - SpvImageFormatMax = 0x7fffffff, -} SpvImageFormat; - -typedef enum SpvImageChannelOrder_ { - SpvImageChannelOrderR = 0, - SpvImageChannelOrderA = 1, - SpvImageChannelOrderRG = 2, - SpvImageChannelOrderRA = 3, - SpvImageChannelOrderRGB = 4, - SpvImageChannelOrderRGBA = 5, - SpvImageChannelOrderBGRA = 6, - SpvImageChannelOrderARGB = 7, - SpvImageChannelOrderIntensity = 8, - SpvImageChannelOrderLuminance = 9, - SpvImageChannelOrderRx = 10, - SpvImageChannelOrderRGx = 11, - SpvImageChannelOrderRGBx = 12, - SpvImageChannelOrderDepth = 13, - SpvImageChannelOrderDepthStencil = 14, - SpvImageChannelOrdersRGB = 15, - SpvImageChannelOrdersRGBx = 16, - SpvImageChannelOrdersRGBA = 17, - SpvImageChannelOrdersBGRA = 18, - SpvImageChannelOrderABGR = 19, - SpvImageChannelOrderMax = 0x7fffffff, -} SpvImageChannelOrder; - -typedef enum SpvImageChannelDataType_ { - SpvImageChannelDataTypeSnormInt8 = 0, - SpvImageChannelDataTypeSnormInt16 = 1, - SpvImageChannelDataTypeUnormInt8 = 2, - SpvImageChannelDataTypeUnormInt16 = 3, - SpvImageChannelDataTypeUnormShort565 = 4, - SpvImageChannelDataTypeUnormShort555 = 5, - SpvImageChannelDataTypeUnormInt101010 = 6, - SpvImageChannelDataTypeSignedInt8 = 7, - SpvImageChannelDataTypeSignedInt16 = 8, - SpvImageChannelDataTypeSignedInt32 = 9, - SpvImageChannelDataTypeUnsignedInt8 = 10, - SpvImageChannelDataTypeUnsignedInt16 = 11, - SpvImageChannelDataTypeUnsignedInt32 = 12, - SpvImageChannelDataTypeHalfFloat = 13, - SpvImageChannelDataTypeFloat = 14, - SpvImageChannelDataTypeUnormInt24 = 15, - SpvImageChannelDataTypeUnormInt101010_2 = 16, - SpvImageChannelDataTypeMax = 0x7fffffff, -} SpvImageChannelDataType; - -typedef enum SpvImageOperandsShift_ { - SpvImageOperandsBiasShift = 0, - SpvImageOperandsLodShift = 1, - SpvImageOperandsGradShift = 2, - SpvImageOperandsConstOffsetShift = 3, - SpvImageOperandsOffsetShift = 4, - SpvImageOperandsConstOffsetsShift = 5, - SpvImageOperandsSampleShift = 6, - SpvImageOperandsMinLodShift = 7, - SpvImageOperandsMakeTexelAvailableShift = 8, - SpvImageOperandsMakeTexelAvailableKHRShift = 8, - SpvImageOperandsMakeTexelVisibleShift = 9, - SpvImageOperandsMakeTexelVisibleKHRShift = 9, - SpvImageOperandsNonPrivateTexelShift = 10, - SpvImageOperandsNonPrivateTexelKHRShift = 10, - SpvImageOperandsVolatileTexelShift = 11, - SpvImageOperandsVolatileTexelKHRShift = 11, - SpvImageOperandsSignExtendShift = 12, - SpvImageOperandsZeroExtendShift = 13, - SpvImageOperandsMax = 0x7fffffff, -} SpvImageOperandsShift; - -typedef enum SpvImageOperandsMask_ { - SpvImageOperandsMaskNone = 0, - SpvImageOperandsBiasMask = 0x00000001, - SpvImageOperandsLodMask = 0x00000002, - SpvImageOperandsGradMask = 0x00000004, - SpvImageOperandsConstOffsetMask = 0x00000008, - SpvImageOperandsOffsetMask = 0x00000010, - SpvImageOperandsConstOffsetsMask = 0x00000020, - SpvImageOperandsSampleMask = 0x00000040, - SpvImageOperandsMinLodMask = 0x00000080, - SpvImageOperandsMakeTexelAvailableMask = 0x00000100, - SpvImageOperandsMakeTexelAvailableKHRMask = 0x00000100, - SpvImageOperandsMakeTexelVisibleMask = 0x00000200, - SpvImageOperandsMakeTexelVisibleKHRMask = 0x00000200, - SpvImageOperandsNonPrivateTexelMask = 0x00000400, - SpvImageOperandsNonPrivateTexelKHRMask = 0x00000400, - SpvImageOperandsVolatileTexelMask = 0x00000800, - SpvImageOperandsVolatileTexelKHRMask = 0x00000800, - SpvImageOperandsSignExtendMask = 0x00001000, - SpvImageOperandsZeroExtendMask = 0x00002000, -} SpvImageOperandsMask; - -typedef enum SpvFPFastMathModeShift_ { - SpvFPFastMathModeNotNaNShift = 0, - SpvFPFastMathModeNotInfShift = 1, - SpvFPFastMathModeNSZShift = 2, - SpvFPFastMathModeAllowRecipShift = 3, - SpvFPFastMathModeFastShift = 4, - SpvFPFastMathModeMax = 0x7fffffff, -} SpvFPFastMathModeShift; - -typedef enum SpvFPFastMathModeMask_ { - SpvFPFastMathModeMaskNone = 0, - SpvFPFastMathModeNotNaNMask = 0x00000001, - SpvFPFastMathModeNotInfMask = 0x00000002, - SpvFPFastMathModeNSZMask = 0x00000004, - SpvFPFastMathModeAllowRecipMask = 0x00000008, - SpvFPFastMathModeFastMask = 0x00000010, -} SpvFPFastMathModeMask; - -typedef enum SpvFPRoundingMode_ { - SpvFPRoundingModeRTE = 0, - SpvFPRoundingModeRTZ = 1, - SpvFPRoundingModeRTP = 2, - SpvFPRoundingModeRTN = 3, - SpvFPRoundingModeMax = 0x7fffffff, -} SpvFPRoundingMode; - -typedef enum SpvLinkageType_ { - SpvLinkageTypeExport = 0, - SpvLinkageTypeImport = 1, - SpvLinkageTypeMax = 0x7fffffff, -} SpvLinkageType; - -typedef enum SpvAccessQualifier_ { - SpvAccessQualifierReadOnly = 0, - SpvAccessQualifierWriteOnly = 1, - SpvAccessQualifierReadWrite = 2, - SpvAccessQualifierMax = 0x7fffffff, -} SpvAccessQualifier; - -typedef enum SpvFunctionParameterAttribute_ { - SpvFunctionParameterAttributeZext = 0, - SpvFunctionParameterAttributeSext = 1, - SpvFunctionParameterAttributeByVal = 2, - SpvFunctionParameterAttributeSret = 3, - SpvFunctionParameterAttributeNoAlias = 4, - SpvFunctionParameterAttributeNoCapture = 5, - SpvFunctionParameterAttributeNoWrite = 6, - SpvFunctionParameterAttributeNoReadWrite = 7, - SpvFunctionParameterAttributeMax = 0x7fffffff, -} SpvFunctionParameterAttribute; - -typedef enum SpvDecoration_ { - SpvDecorationRelaxedPrecision = 0, - SpvDecorationSpecId = 1, - SpvDecorationBlock = 2, - SpvDecorationBufferBlock = 3, - SpvDecorationRowMajor = 4, - SpvDecorationColMajor = 5, - SpvDecorationArrayStride = 6, - SpvDecorationMatrixStride = 7, - SpvDecorationGLSLShared = 8, - SpvDecorationGLSLPacked = 9, - SpvDecorationCPacked = 10, - SpvDecorationBuiltIn = 11, - SpvDecorationNoPerspective = 13, - SpvDecorationFlat = 14, - SpvDecorationPatch = 15, - SpvDecorationCentroid = 16, - SpvDecorationSample = 17, - SpvDecorationInvariant = 18, - SpvDecorationRestrict = 19, - SpvDecorationAliased = 20, - SpvDecorationVolatile = 21, - SpvDecorationConstant = 22, - SpvDecorationCoherent = 23, - SpvDecorationNonWritable = 24, - SpvDecorationNonReadable = 25, - SpvDecorationUniform = 26, - SpvDecorationUniformId = 27, - SpvDecorationSaturatedConversion = 28, - SpvDecorationStream = 29, - SpvDecorationLocation = 30, - SpvDecorationComponent = 31, - SpvDecorationIndex = 32, - SpvDecorationBinding = 33, - SpvDecorationDescriptorSet = 34, - SpvDecorationOffset = 35, - SpvDecorationXfbBuffer = 36, - SpvDecorationXfbStride = 37, - SpvDecorationFuncParamAttr = 38, - SpvDecorationFPRoundingMode = 39, - SpvDecorationFPFastMathMode = 40, - SpvDecorationLinkageAttributes = 41, - SpvDecorationNoContraction = 42, - SpvDecorationInputAttachmentIndex = 43, - SpvDecorationAlignment = 44, - SpvDecorationMaxByteOffset = 45, - SpvDecorationAlignmentId = 46, - SpvDecorationMaxByteOffsetId = 47, - SpvDecorationNoSignedWrap = 4469, - SpvDecorationNoUnsignedWrap = 4470, - SpvDecorationExplicitInterpAMD = 4999, - SpvDecorationOverrideCoverageNV = 5248, - SpvDecorationPassthroughNV = 5250, - SpvDecorationViewportRelativeNV = 5252, - SpvDecorationSecondaryViewportRelativeNV = 5256, - SpvDecorationPerPrimitiveNV = 5271, - SpvDecorationPerViewNV = 5272, - SpvDecorationPerTaskNV = 5273, - SpvDecorationPerVertexNV = 5285, - SpvDecorationNonUniform = 5300, - SpvDecorationNonUniformEXT = 5300, - SpvDecorationRestrictPointer = 5355, - SpvDecorationRestrictPointerEXT = 5355, - SpvDecorationAliasedPointer = 5356, - SpvDecorationAliasedPointerEXT = 5356, - SpvDecorationReferencedIndirectlyINTEL = 5602, - SpvDecorationCounterBuffer = 5634, - SpvDecorationHlslCounterBufferGOOGLE = 5634, - SpvDecorationHlslSemanticGOOGLE = 5635, - SpvDecorationUserSemantic = 5635, - SpvDecorationUserTypeGOOGLE = 5636, - SpvDecorationRegisterINTEL = 5825, - SpvDecorationMemoryINTEL = 5826, - SpvDecorationNumbanksINTEL = 5827, - SpvDecorationBankwidthINTEL = 5828, - SpvDecorationMaxPrivateCopiesINTEL = 5829, - SpvDecorationSinglepumpINTEL = 5830, - SpvDecorationDoublepumpINTEL = 5831, - SpvDecorationMaxReplicatesINTEL = 5832, - SpvDecorationSimpleDualPortINTEL = 5833, - SpvDecorationMergeINTEL = 5834, - SpvDecorationBankBitsINTEL = 5835, - SpvDecorationForcePow2DepthINTEL = 5836, - SpvDecorationMax = 0x7fffffff, -} SpvDecoration; - -typedef enum SpvBuiltIn_ { - SpvBuiltInPosition = 0, - SpvBuiltInPointSize = 1, - SpvBuiltInClipDistance = 3, - SpvBuiltInCullDistance = 4, - SpvBuiltInVertexId = 5, - SpvBuiltInInstanceId = 6, - SpvBuiltInPrimitiveId = 7, - SpvBuiltInInvocationId = 8, - SpvBuiltInLayer = 9, - SpvBuiltInViewportIndex = 10, - SpvBuiltInTessLevelOuter = 11, - SpvBuiltInTessLevelInner = 12, - SpvBuiltInTessCoord = 13, - SpvBuiltInPatchVertices = 14, - SpvBuiltInFragCoord = 15, - SpvBuiltInPointCoord = 16, - SpvBuiltInFrontFacing = 17, - SpvBuiltInSampleId = 18, - SpvBuiltInSamplePosition = 19, - SpvBuiltInSampleMask = 20, - SpvBuiltInFragDepth = 22, - SpvBuiltInHelperInvocation = 23, - SpvBuiltInNumWorkgroups = 24, - SpvBuiltInWorkgroupSize = 25, - SpvBuiltInWorkgroupId = 26, - SpvBuiltInLocalInvocationId = 27, - SpvBuiltInGlobalInvocationId = 28, - SpvBuiltInLocalInvocationIndex = 29, - SpvBuiltInWorkDim = 30, - SpvBuiltInGlobalSize = 31, - SpvBuiltInEnqueuedWorkgroupSize = 32, - SpvBuiltInGlobalOffset = 33, - SpvBuiltInGlobalLinearId = 34, - SpvBuiltInSubgroupSize = 36, - SpvBuiltInSubgroupMaxSize = 37, - SpvBuiltInNumSubgroups = 38, - SpvBuiltInNumEnqueuedSubgroups = 39, - SpvBuiltInSubgroupId = 40, - SpvBuiltInSubgroupLocalInvocationId = 41, - SpvBuiltInVertexIndex = 42, - SpvBuiltInInstanceIndex = 43, - SpvBuiltInSubgroupEqMask = 4416, - SpvBuiltInSubgroupEqMaskKHR = 4416, - SpvBuiltInSubgroupGeMask = 4417, - SpvBuiltInSubgroupGeMaskKHR = 4417, - SpvBuiltInSubgroupGtMask = 4418, - SpvBuiltInSubgroupGtMaskKHR = 4418, - SpvBuiltInSubgroupLeMask = 4419, - SpvBuiltInSubgroupLeMaskKHR = 4419, - SpvBuiltInSubgroupLtMask = 4420, - SpvBuiltInSubgroupLtMaskKHR = 4420, - SpvBuiltInBaseVertex = 4424, - SpvBuiltInBaseInstance = 4425, - SpvBuiltInDrawIndex = 4426, - SpvBuiltInDeviceIndex = 4438, - SpvBuiltInViewIndex = 4440, - SpvBuiltInBaryCoordNoPerspAMD = 4992, - SpvBuiltInBaryCoordNoPerspCentroidAMD = 4993, - SpvBuiltInBaryCoordNoPerspSampleAMD = 4994, - SpvBuiltInBaryCoordSmoothAMD = 4995, - SpvBuiltInBaryCoordSmoothCentroidAMD = 4996, - SpvBuiltInBaryCoordSmoothSampleAMD = 4997, - SpvBuiltInBaryCoordPullModelAMD = 4998, - SpvBuiltInFragStencilRefEXT = 5014, - SpvBuiltInViewportMaskNV = 5253, - SpvBuiltInSecondaryPositionNV = 5257, - SpvBuiltInSecondaryViewportMaskNV = 5258, - SpvBuiltInPositionPerViewNV = 5261, - SpvBuiltInViewportMaskPerViewNV = 5262, - SpvBuiltInFullyCoveredEXT = 5264, - SpvBuiltInTaskCountNV = 5274, - SpvBuiltInPrimitiveCountNV = 5275, - SpvBuiltInPrimitiveIndicesNV = 5276, - SpvBuiltInClipDistancePerViewNV = 5277, - SpvBuiltInCullDistancePerViewNV = 5278, - SpvBuiltInLayerPerViewNV = 5279, - SpvBuiltInMeshViewCountNV = 5280, - SpvBuiltInMeshViewIndicesNV = 5281, - SpvBuiltInBaryCoordNV = 5286, - SpvBuiltInBaryCoordNoPerspNV = 5287, - SpvBuiltInFragSizeEXT = 5292, - SpvBuiltInFragmentSizeNV = 5292, - SpvBuiltInFragInvocationCountEXT = 5293, - SpvBuiltInInvocationsPerPixelNV = 5293, - SpvBuiltInLaunchIdKHR = 5319, - SpvBuiltInLaunchIdNV = 5319, - SpvBuiltInLaunchSizeKHR = 5320, - SpvBuiltInLaunchSizeNV = 5320, - SpvBuiltInWorldRayOriginKHR = 5321, - SpvBuiltInWorldRayOriginNV = 5321, - SpvBuiltInWorldRayDirectionKHR = 5322, - SpvBuiltInWorldRayDirectionNV = 5322, - SpvBuiltInObjectRayOriginKHR = 5323, - SpvBuiltInObjectRayOriginNV = 5323, - SpvBuiltInObjectRayDirectionKHR = 5324, - SpvBuiltInObjectRayDirectionNV = 5324, - SpvBuiltInRayTminKHR = 5325, - SpvBuiltInRayTminNV = 5325, - SpvBuiltInRayTmaxKHR = 5326, - SpvBuiltInRayTmaxNV = 5326, - SpvBuiltInInstanceCustomIndexKHR = 5327, - SpvBuiltInInstanceCustomIndexNV = 5327, - SpvBuiltInObjectToWorldKHR = 5330, - SpvBuiltInObjectToWorldNV = 5330, - SpvBuiltInWorldToObjectKHR = 5331, - SpvBuiltInWorldToObjectNV = 5331, - SpvBuiltInHitTKHR = 5332, - SpvBuiltInHitTNV = 5332, - SpvBuiltInHitKindKHR = 5333, - SpvBuiltInHitKindNV = 5333, - SpvBuiltInIncomingRayFlagsKHR = 5351, - SpvBuiltInIncomingRayFlagsNV = 5351, - SpvBuiltInRayGeometryIndexKHR = 5352, - SpvBuiltInWarpsPerSMNV = 5374, - SpvBuiltInSMCountNV = 5375, - SpvBuiltInWarpIDNV = 5376, - SpvBuiltInSMIDNV = 5377, - SpvBuiltInMax = 0x7fffffff, -} SpvBuiltIn; - -typedef enum SpvSelectionControlShift_ { - SpvSelectionControlFlattenShift = 0, - SpvSelectionControlDontFlattenShift = 1, - SpvSelectionControlMax = 0x7fffffff, -} SpvSelectionControlShift; - -typedef enum SpvSelectionControlMask_ { - SpvSelectionControlMaskNone = 0, - SpvSelectionControlFlattenMask = 0x00000001, - SpvSelectionControlDontFlattenMask = 0x00000002, -} SpvSelectionControlMask; - -typedef enum SpvLoopControlShift_ { - SpvLoopControlUnrollShift = 0, - SpvLoopControlDontUnrollShift = 1, - SpvLoopControlDependencyInfiniteShift = 2, - SpvLoopControlDependencyLengthShift = 3, - SpvLoopControlMinIterationsShift = 4, - SpvLoopControlMaxIterationsShift = 5, - SpvLoopControlIterationMultipleShift = 6, - SpvLoopControlPeelCountShift = 7, - SpvLoopControlPartialCountShift = 8, - SpvLoopControlInitiationIntervalINTELShift = 16, - SpvLoopControlMaxConcurrencyINTELShift = 17, - SpvLoopControlDependencyArrayINTELShift = 18, - SpvLoopControlPipelineEnableINTELShift = 19, - SpvLoopControlLoopCoalesceINTELShift = 20, - SpvLoopControlMaxInterleavingINTELShift = 21, - SpvLoopControlSpeculatedIterationsINTELShift = 22, - SpvLoopControlMax = 0x7fffffff, -} SpvLoopControlShift; - -typedef enum SpvLoopControlMask_ { - SpvLoopControlMaskNone = 0, - SpvLoopControlUnrollMask = 0x00000001, - SpvLoopControlDontUnrollMask = 0x00000002, - SpvLoopControlDependencyInfiniteMask = 0x00000004, - SpvLoopControlDependencyLengthMask = 0x00000008, - SpvLoopControlMinIterationsMask = 0x00000010, - SpvLoopControlMaxIterationsMask = 0x00000020, - SpvLoopControlIterationMultipleMask = 0x00000040, - SpvLoopControlPeelCountMask = 0x00000080, - SpvLoopControlPartialCountMask = 0x00000100, - SpvLoopControlInitiationIntervalINTELMask = 0x00010000, - SpvLoopControlMaxConcurrencyINTELMask = 0x00020000, - SpvLoopControlDependencyArrayINTELMask = 0x00040000, - SpvLoopControlPipelineEnableINTELMask = 0x00080000, - SpvLoopControlLoopCoalesceINTELMask = 0x00100000, - SpvLoopControlMaxInterleavingINTELMask = 0x00200000, - SpvLoopControlSpeculatedIterationsINTELMask = 0x00400000, -} SpvLoopControlMask; - -typedef enum SpvFunctionControlShift_ { - SpvFunctionControlInlineShift = 0, - SpvFunctionControlDontInlineShift = 1, - SpvFunctionControlPureShift = 2, - SpvFunctionControlConstShift = 3, - SpvFunctionControlMax = 0x7fffffff, -} SpvFunctionControlShift; - -typedef enum SpvFunctionControlMask_ { - SpvFunctionControlMaskNone = 0, - SpvFunctionControlInlineMask = 0x00000001, - SpvFunctionControlDontInlineMask = 0x00000002, - SpvFunctionControlPureMask = 0x00000004, - SpvFunctionControlConstMask = 0x00000008, -} SpvFunctionControlMask; - -typedef enum SpvMemorySemanticsShift_ { - SpvMemorySemanticsAcquireShift = 1, - SpvMemorySemanticsReleaseShift = 2, - SpvMemorySemanticsAcquireReleaseShift = 3, - SpvMemorySemanticsSequentiallyConsistentShift = 4, - SpvMemorySemanticsUniformMemoryShift = 6, - SpvMemorySemanticsSubgroupMemoryShift = 7, - SpvMemorySemanticsWorkgroupMemoryShift = 8, - SpvMemorySemanticsCrossWorkgroupMemoryShift = 9, - SpvMemorySemanticsAtomicCounterMemoryShift = 10, - SpvMemorySemanticsImageMemoryShift = 11, - SpvMemorySemanticsOutputMemoryShift = 12, - SpvMemorySemanticsOutputMemoryKHRShift = 12, - SpvMemorySemanticsMakeAvailableShift = 13, - SpvMemorySemanticsMakeAvailableKHRShift = 13, - SpvMemorySemanticsMakeVisibleShift = 14, - SpvMemorySemanticsMakeVisibleKHRShift = 14, - SpvMemorySemanticsVolatileShift = 15, - SpvMemorySemanticsMax = 0x7fffffff, -} SpvMemorySemanticsShift; - -typedef enum SpvMemorySemanticsMask_ { - SpvMemorySemanticsMaskNone = 0, - SpvMemorySemanticsAcquireMask = 0x00000002, - SpvMemorySemanticsReleaseMask = 0x00000004, - SpvMemorySemanticsAcquireReleaseMask = 0x00000008, - SpvMemorySemanticsSequentiallyConsistentMask = 0x00000010, - SpvMemorySemanticsUniformMemoryMask = 0x00000040, - SpvMemorySemanticsSubgroupMemoryMask = 0x00000080, - SpvMemorySemanticsWorkgroupMemoryMask = 0x00000100, - SpvMemorySemanticsCrossWorkgroupMemoryMask = 0x00000200, - SpvMemorySemanticsAtomicCounterMemoryMask = 0x00000400, - SpvMemorySemanticsImageMemoryMask = 0x00000800, - SpvMemorySemanticsOutputMemoryMask = 0x00001000, - SpvMemorySemanticsOutputMemoryKHRMask = 0x00001000, - SpvMemorySemanticsMakeAvailableMask = 0x00002000, - SpvMemorySemanticsMakeAvailableKHRMask = 0x00002000, - SpvMemorySemanticsMakeVisibleMask = 0x00004000, - SpvMemorySemanticsMakeVisibleKHRMask = 0x00004000, - SpvMemorySemanticsVolatileMask = 0x00008000, -} SpvMemorySemanticsMask; - -typedef enum SpvMemoryAccessShift_ { - SpvMemoryAccessVolatileShift = 0, - SpvMemoryAccessAlignedShift = 1, - SpvMemoryAccessNontemporalShift = 2, - SpvMemoryAccessMakePointerAvailableShift = 3, - SpvMemoryAccessMakePointerAvailableKHRShift = 3, - SpvMemoryAccessMakePointerVisibleShift = 4, - SpvMemoryAccessMakePointerVisibleKHRShift = 4, - SpvMemoryAccessNonPrivatePointerShift = 5, - SpvMemoryAccessNonPrivatePointerKHRShift = 5, - SpvMemoryAccessMax = 0x7fffffff, -} SpvMemoryAccessShift; - -typedef enum SpvMemoryAccessMask_ { - SpvMemoryAccessMaskNone = 0, - SpvMemoryAccessVolatileMask = 0x00000001, - SpvMemoryAccessAlignedMask = 0x00000002, - SpvMemoryAccessNontemporalMask = 0x00000004, - SpvMemoryAccessMakePointerAvailableMask = 0x00000008, - SpvMemoryAccessMakePointerAvailableKHRMask = 0x00000008, - SpvMemoryAccessMakePointerVisibleMask = 0x00000010, - SpvMemoryAccessMakePointerVisibleKHRMask = 0x00000010, - SpvMemoryAccessNonPrivatePointerMask = 0x00000020, - SpvMemoryAccessNonPrivatePointerKHRMask = 0x00000020, -} SpvMemoryAccessMask; - -typedef enum SpvScope_ { - SpvScopeCrossDevice = 0, - SpvScopeDevice = 1, - SpvScopeWorkgroup = 2, - SpvScopeSubgroup = 3, - SpvScopeInvocation = 4, - SpvScopeQueueFamily = 5, - SpvScopeQueueFamilyKHR = 5, - SpvScopeShaderCallKHR = 6, - SpvScopeMax = 0x7fffffff, -} SpvScope; - -typedef enum SpvGroupOperation_ { - SpvGroupOperationReduce = 0, - SpvGroupOperationInclusiveScan = 1, - SpvGroupOperationExclusiveScan = 2, - SpvGroupOperationClusteredReduce = 3, - SpvGroupOperationPartitionedReduceNV = 6, - SpvGroupOperationPartitionedInclusiveScanNV = 7, - SpvGroupOperationPartitionedExclusiveScanNV = 8, - SpvGroupOperationMax = 0x7fffffff, -} SpvGroupOperation; - -typedef enum SpvKernelEnqueueFlags_ { - SpvKernelEnqueueFlagsNoWait = 0, - SpvKernelEnqueueFlagsWaitKernel = 1, - SpvKernelEnqueueFlagsWaitWorkGroup = 2, - SpvKernelEnqueueFlagsMax = 0x7fffffff, -} SpvKernelEnqueueFlags; - -typedef enum SpvKernelProfilingInfoShift_ { - SpvKernelProfilingInfoCmdExecTimeShift = 0, - SpvKernelProfilingInfoMax = 0x7fffffff, -} SpvKernelProfilingInfoShift; - -typedef enum SpvKernelProfilingInfoMask_ { - SpvKernelProfilingInfoMaskNone = 0, - SpvKernelProfilingInfoCmdExecTimeMask = 0x00000001, -} SpvKernelProfilingInfoMask; - -typedef enum SpvCapability_ { - SpvCapabilityMatrix = 0, - SpvCapabilityShader = 1, - SpvCapabilityGeometry = 2, - SpvCapabilityTessellation = 3, - SpvCapabilityAddresses = 4, - SpvCapabilityLinkage = 5, - SpvCapabilityKernel = 6, - SpvCapabilityVector16 = 7, - SpvCapabilityFloat16Buffer = 8, - SpvCapabilityFloat16 = 9, - SpvCapabilityFloat64 = 10, - SpvCapabilityInt64 = 11, - SpvCapabilityInt64Atomics = 12, - SpvCapabilityImageBasic = 13, - SpvCapabilityImageReadWrite = 14, - SpvCapabilityImageMipmap = 15, - SpvCapabilityPipes = 17, - SpvCapabilityGroups = 18, - SpvCapabilityDeviceEnqueue = 19, - SpvCapabilityLiteralSampler = 20, - SpvCapabilityAtomicStorage = 21, - SpvCapabilityInt16 = 22, - SpvCapabilityTessellationPointSize = 23, - SpvCapabilityGeometryPointSize = 24, - SpvCapabilityImageGatherExtended = 25, - SpvCapabilityStorageImageMultisample = 27, - SpvCapabilityUniformBufferArrayDynamicIndexing = 28, - SpvCapabilitySampledImageArrayDynamicIndexing = 29, - SpvCapabilityStorageBufferArrayDynamicIndexing = 30, - SpvCapabilityStorageImageArrayDynamicIndexing = 31, - SpvCapabilityClipDistance = 32, - SpvCapabilityCullDistance = 33, - SpvCapabilityImageCubeArray = 34, - SpvCapabilitySampleRateShading = 35, - SpvCapabilityImageRect = 36, - SpvCapabilitySampledRect = 37, - SpvCapabilityGenericPointer = 38, - SpvCapabilityInt8 = 39, - SpvCapabilityInputAttachment = 40, - SpvCapabilitySparseResidency = 41, - SpvCapabilityMinLod = 42, - SpvCapabilitySampled1D = 43, - SpvCapabilityImage1D = 44, - SpvCapabilitySampledCubeArray = 45, - SpvCapabilitySampledBuffer = 46, - SpvCapabilityImageBuffer = 47, - SpvCapabilityImageMSArray = 48, - SpvCapabilityStorageImageExtendedFormats = 49, - SpvCapabilityImageQuery = 50, - SpvCapabilityDerivativeControl = 51, - SpvCapabilityInterpolationFunction = 52, - SpvCapabilityTransformFeedback = 53, - SpvCapabilityGeometryStreams = 54, - SpvCapabilityStorageImageReadWithoutFormat = 55, - SpvCapabilityStorageImageWriteWithoutFormat = 56, - SpvCapabilityMultiViewport = 57, - SpvCapabilitySubgroupDispatch = 58, - SpvCapabilityNamedBarrier = 59, - SpvCapabilityPipeStorage = 60, - SpvCapabilityGroupNonUniform = 61, - SpvCapabilityGroupNonUniformVote = 62, - SpvCapabilityGroupNonUniformArithmetic = 63, - SpvCapabilityGroupNonUniformBallot = 64, - SpvCapabilityGroupNonUniformShuffle = 65, - SpvCapabilityGroupNonUniformShuffleRelative = 66, - SpvCapabilityGroupNonUniformClustered = 67, - SpvCapabilityGroupNonUniformQuad = 68, - SpvCapabilityShaderLayer = 69, - SpvCapabilityShaderViewportIndex = 70, - SpvCapabilitySubgroupBallotKHR = 4423, - SpvCapabilityDrawParameters = 4427, - SpvCapabilitySubgroupVoteKHR = 4431, - SpvCapabilityStorageBuffer16BitAccess = 4433, - SpvCapabilityStorageUniformBufferBlock16 = 4433, - SpvCapabilityStorageUniform16 = 4434, - SpvCapabilityUniformAndStorageBuffer16BitAccess = 4434, - SpvCapabilityStoragePushConstant16 = 4435, - SpvCapabilityStorageInputOutput16 = 4436, - SpvCapabilityDeviceGroup = 4437, - SpvCapabilityMultiView = 4439, - SpvCapabilityVariablePointersStorageBuffer = 4441, - SpvCapabilityVariablePointers = 4442, - SpvCapabilityAtomicStorageOps = 4445, - SpvCapabilitySampleMaskPostDepthCoverage = 4447, - SpvCapabilityStorageBuffer8BitAccess = 4448, - SpvCapabilityUniformAndStorageBuffer8BitAccess = 4449, - SpvCapabilityStoragePushConstant8 = 4450, - SpvCapabilityDenormPreserve = 4464, - SpvCapabilityDenormFlushToZero = 4465, - SpvCapabilitySignedZeroInfNanPreserve = 4466, - SpvCapabilityRoundingModeRTE = 4467, - SpvCapabilityRoundingModeRTZ = 4468, - SpvCapabilityRayQueryProvisionalKHR = 4471, - SpvCapabilityRayTraversalPrimitiveCullingProvisionalKHR = 4478, - SpvCapabilityFloat16ImageAMD = 5008, - SpvCapabilityImageGatherBiasLodAMD = 5009, - SpvCapabilityFragmentMaskAMD = 5010, - SpvCapabilityStencilExportEXT = 5013, - SpvCapabilityImageReadWriteLodAMD = 5015, - SpvCapabilityShaderClockKHR = 5055, - SpvCapabilitySampleMaskOverrideCoverageNV = 5249, - SpvCapabilityGeometryShaderPassthroughNV = 5251, - SpvCapabilityShaderViewportIndexLayerEXT = 5254, - SpvCapabilityShaderViewportIndexLayerNV = 5254, - SpvCapabilityShaderViewportMaskNV = 5255, - SpvCapabilityShaderStereoViewNV = 5259, - SpvCapabilityPerViewAttributesNV = 5260, - SpvCapabilityFragmentFullyCoveredEXT = 5265, - SpvCapabilityMeshShadingNV = 5266, - SpvCapabilityImageFootprintNV = 5282, - SpvCapabilityFragmentBarycentricNV = 5284, - SpvCapabilityComputeDerivativeGroupQuadsNV = 5288, - SpvCapabilityFragmentDensityEXT = 5291, - SpvCapabilityShadingRateNV = 5291, - SpvCapabilityGroupNonUniformPartitionedNV = 5297, - SpvCapabilityShaderNonUniform = 5301, - SpvCapabilityShaderNonUniformEXT = 5301, - SpvCapabilityRuntimeDescriptorArray = 5302, - SpvCapabilityRuntimeDescriptorArrayEXT = 5302, - SpvCapabilityInputAttachmentArrayDynamicIndexing = 5303, - SpvCapabilityInputAttachmentArrayDynamicIndexingEXT = 5303, - SpvCapabilityUniformTexelBufferArrayDynamicIndexing = 5304, - SpvCapabilityUniformTexelBufferArrayDynamicIndexingEXT = 5304, - SpvCapabilityStorageTexelBufferArrayDynamicIndexing = 5305, - SpvCapabilityStorageTexelBufferArrayDynamicIndexingEXT = 5305, - SpvCapabilityUniformBufferArrayNonUniformIndexing = 5306, - SpvCapabilityUniformBufferArrayNonUniformIndexingEXT = 5306, - SpvCapabilitySampledImageArrayNonUniformIndexing = 5307, - SpvCapabilitySampledImageArrayNonUniformIndexingEXT = 5307, - SpvCapabilityStorageBufferArrayNonUniformIndexing = 5308, - SpvCapabilityStorageBufferArrayNonUniformIndexingEXT = 5308, - SpvCapabilityStorageImageArrayNonUniformIndexing = 5309, - SpvCapabilityStorageImageArrayNonUniformIndexingEXT = 5309, - SpvCapabilityInputAttachmentArrayNonUniformIndexing = 5310, - SpvCapabilityInputAttachmentArrayNonUniformIndexingEXT = 5310, - SpvCapabilityUniformTexelBufferArrayNonUniformIndexing = 5311, - SpvCapabilityUniformTexelBufferArrayNonUniformIndexingEXT = 5311, - SpvCapabilityStorageTexelBufferArrayNonUniformIndexing = 5312, - SpvCapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312, - SpvCapabilityRayTracingNV = 5340, - SpvCapabilityVulkanMemoryModel = 5345, - SpvCapabilityVulkanMemoryModelKHR = 5345, - SpvCapabilityVulkanMemoryModelDeviceScope = 5346, - SpvCapabilityVulkanMemoryModelDeviceScopeKHR = 5346, - SpvCapabilityPhysicalStorageBufferAddresses = 5347, - SpvCapabilityPhysicalStorageBufferAddressesEXT = 5347, - SpvCapabilityComputeDerivativeGroupLinearNV = 5350, - SpvCapabilityRayTracingProvisionalKHR = 5353, - SpvCapabilityCooperativeMatrixNV = 5357, - SpvCapabilityFragmentShaderSampleInterlockEXT = 5363, - SpvCapabilityFragmentShaderShadingRateInterlockEXT = 5372, - SpvCapabilityShaderSMBuiltinsNV = 5373, - SpvCapabilityFragmentShaderPixelInterlockEXT = 5378, - SpvCapabilityDemoteToHelperInvocationEXT = 5379, - SpvCapabilitySubgroupShuffleINTEL = 5568, - SpvCapabilitySubgroupBufferBlockIOINTEL = 5569, - SpvCapabilitySubgroupImageBlockIOINTEL = 5570, - SpvCapabilitySubgroupImageMediaBlockIOINTEL = 5579, - SpvCapabilityIntegerFunctions2INTEL = 5584, - SpvCapabilityFunctionPointersINTEL = 5603, - SpvCapabilityIndirectReferencesINTEL = 5604, - SpvCapabilitySubgroupAvcMotionEstimationINTEL = 5696, - SpvCapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697, - SpvCapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698, - SpvCapabilityFPGAMemoryAttributesINTEL = 5824, - SpvCapabilityUnstructuredLoopControlsINTEL = 5886, - SpvCapabilityFPGALoopControlsINTEL = 5888, - SpvCapabilityKernelAttributesINTEL = 5892, - SpvCapabilityFPGAKernelAttributesINTEL = 5897, - SpvCapabilityBlockingPipesINTEL = 5945, - SpvCapabilityFPGARegINTEL = 5948, - SpvCapabilityAtomicFloat32AddEXT = 6033, - SpvCapabilityAtomicFloat64AddEXT = 6034, - SpvCapabilityMax = 0x7fffffff, -} SpvCapability; - -typedef enum SpvRayFlagsShift_ { - SpvRayFlagsOpaqueKHRShift = 0, - SpvRayFlagsNoOpaqueKHRShift = 1, - SpvRayFlagsTerminateOnFirstHitKHRShift = 2, - SpvRayFlagsSkipClosestHitShaderKHRShift = 3, - SpvRayFlagsCullBackFacingTrianglesKHRShift = 4, - SpvRayFlagsCullFrontFacingTrianglesKHRShift = 5, - SpvRayFlagsCullOpaqueKHRShift = 6, - SpvRayFlagsCullNoOpaqueKHRShift = 7, - SpvRayFlagsSkipTrianglesKHRShift = 8, - SpvRayFlagsSkipAABBsKHRShift = 9, - SpvRayFlagsMax = 0x7fffffff, -} SpvRayFlagsShift; - -typedef enum SpvRayFlagsMask_ { - SpvRayFlagsMaskNone = 0, - SpvRayFlagsOpaqueKHRMask = 0x00000001, - SpvRayFlagsNoOpaqueKHRMask = 0x00000002, - SpvRayFlagsTerminateOnFirstHitKHRMask = 0x00000004, - SpvRayFlagsSkipClosestHitShaderKHRMask = 0x00000008, - SpvRayFlagsCullBackFacingTrianglesKHRMask = 0x00000010, - SpvRayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020, - SpvRayFlagsCullOpaqueKHRMask = 0x00000040, - SpvRayFlagsCullNoOpaqueKHRMask = 0x00000080, - SpvRayFlagsSkipTrianglesKHRMask = 0x00000100, - SpvRayFlagsSkipAABBsKHRMask = 0x00000200, -} SpvRayFlagsMask; - -typedef enum SpvRayQueryIntersection_ { - SpvRayQueryIntersectionRayQueryCandidateIntersectionKHR = 0, - SpvRayQueryIntersectionRayQueryCommittedIntersectionKHR = 1, - SpvRayQueryIntersectionMax = 0x7fffffff, -} SpvRayQueryIntersection; - -typedef enum SpvRayQueryCommittedIntersectionType_ { - SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR = 0, - SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR = 1, - SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR = 2, - SpvRayQueryCommittedIntersectionTypeMax = 0x7fffffff, -} SpvRayQueryCommittedIntersectionType; - -typedef enum SpvRayQueryCandidateIntersectionType_ { - SpvRayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR = 0, - SpvRayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR = 1, - SpvRayQueryCandidateIntersectionTypeMax = 0x7fffffff, -} SpvRayQueryCandidateIntersectionType; - -typedef enum SpvOp_ { - SpvOpNop = 0, - SpvOpUndef = 1, - SpvOpSourceContinued = 2, - SpvOpSource = 3, - SpvOpSourceExtension = 4, - SpvOpName = 5, - SpvOpMemberName = 6, - SpvOpString = 7, - SpvOpLine = 8, - SpvOpExtension = 10, - SpvOpExtInstImport = 11, - SpvOpExtInst = 12, - SpvOpMemoryModel = 14, - SpvOpEntryPoint = 15, - SpvOpExecutionMode = 16, - SpvOpCapability = 17, - SpvOpTypeVoid = 19, - SpvOpTypeBool = 20, - SpvOpTypeInt = 21, - SpvOpTypeFloat = 22, - SpvOpTypeVector = 23, - SpvOpTypeMatrix = 24, - SpvOpTypeImage = 25, - SpvOpTypeSampler = 26, - SpvOpTypeSampledImage = 27, - SpvOpTypeArray = 28, - SpvOpTypeRuntimeArray = 29, - SpvOpTypeStruct = 30, - SpvOpTypeOpaque = 31, - SpvOpTypePointer = 32, - SpvOpTypeFunction = 33, - SpvOpTypeEvent = 34, - SpvOpTypeDeviceEvent = 35, - SpvOpTypeReserveId = 36, - SpvOpTypeQueue = 37, - SpvOpTypePipe = 38, - SpvOpTypeForwardPointer = 39, - SpvOpConstantTrue = 41, - SpvOpConstantFalse = 42, - SpvOpConstant = 43, - SpvOpConstantComposite = 44, - SpvOpConstantSampler = 45, - SpvOpConstantNull = 46, - SpvOpSpecConstantTrue = 48, - SpvOpSpecConstantFalse = 49, - SpvOpSpecConstant = 50, - SpvOpSpecConstantComposite = 51, - SpvOpSpecConstantOp = 52, - SpvOpFunction = 54, - SpvOpFunctionParameter = 55, - SpvOpFunctionEnd = 56, - SpvOpFunctionCall = 57, - SpvOpVariable = 59, - SpvOpImageTexelPointer = 60, - SpvOpLoad = 61, - SpvOpStore = 62, - SpvOpCopyMemory = 63, - SpvOpCopyMemorySized = 64, - SpvOpAccessChain = 65, - SpvOpInBoundsAccessChain = 66, - SpvOpPtrAccessChain = 67, - SpvOpArrayLength = 68, - SpvOpGenericPtrMemSemantics = 69, - SpvOpInBoundsPtrAccessChain = 70, - SpvOpDecorate = 71, - SpvOpMemberDecorate = 72, - SpvOpDecorationGroup = 73, - SpvOpGroupDecorate = 74, - SpvOpGroupMemberDecorate = 75, - SpvOpVectorExtractDynamic = 77, - SpvOpVectorInsertDynamic = 78, - SpvOpVectorShuffle = 79, - SpvOpCompositeConstruct = 80, - SpvOpCompositeExtract = 81, - SpvOpCompositeInsert = 82, - SpvOpCopyObject = 83, - SpvOpTranspose = 84, - SpvOpSampledImage = 86, - SpvOpImageSampleImplicitLod = 87, - SpvOpImageSampleExplicitLod = 88, - SpvOpImageSampleDrefImplicitLod = 89, - SpvOpImageSampleDrefExplicitLod = 90, - SpvOpImageSampleProjImplicitLod = 91, - SpvOpImageSampleProjExplicitLod = 92, - SpvOpImageSampleProjDrefImplicitLod = 93, - SpvOpImageSampleProjDrefExplicitLod = 94, - SpvOpImageFetch = 95, - SpvOpImageGather = 96, - SpvOpImageDrefGather = 97, - SpvOpImageRead = 98, - SpvOpImageWrite = 99, - SpvOpImage = 100, - SpvOpImageQueryFormat = 101, - SpvOpImageQueryOrder = 102, - SpvOpImageQuerySizeLod = 103, - SpvOpImageQuerySize = 104, - SpvOpImageQueryLod = 105, - SpvOpImageQueryLevels = 106, - SpvOpImageQuerySamples = 107, - SpvOpConvertFToU = 109, - SpvOpConvertFToS = 110, - SpvOpConvertSToF = 111, - SpvOpConvertUToF = 112, - SpvOpUConvert = 113, - SpvOpSConvert = 114, - SpvOpFConvert = 115, - SpvOpQuantizeToF16 = 116, - SpvOpConvertPtrToU = 117, - SpvOpSatConvertSToU = 118, - SpvOpSatConvertUToS = 119, - SpvOpConvertUToPtr = 120, - SpvOpPtrCastToGeneric = 121, - SpvOpGenericCastToPtr = 122, - SpvOpGenericCastToPtrExplicit = 123, - SpvOpBitcast = 124, - SpvOpSNegate = 126, - SpvOpFNegate = 127, - SpvOpIAdd = 128, - SpvOpFAdd = 129, - SpvOpISub = 130, - SpvOpFSub = 131, - SpvOpIMul = 132, - SpvOpFMul = 133, - SpvOpUDiv = 134, - SpvOpSDiv = 135, - SpvOpFDiv = 136, - SpvOpUMod = 137, - SpvOpSRem = 138, - SpvOpSMod = 139, - SpvOpFRem = 140, - SpvOpFMod = 141, - SpvOpVectorTimesScalar = 142, - SpvOpMatrixTimesScalar = 143, - SpvOpVectorTimesMatrix = 144, - SpvOpMatrixTimesVector = 145, - SpvOpMatrixTimesMatrix = 146, - SpvOpOuterProduct = 147, - SpvOpDot = 148, - SpvOpIAddCarry = 149, - SpvOpISubBorrow = 150, - SpvOpUMulExtended = 151, - SpvOpSMulExtended = 152, - SpvOpAny = 154, - SpvOpAll = 155, - SpvOpIsNan = 156, - SpvOpIsInf = 157, - SpvOpIsFinite = 158, - SpvOpIsNormal = 159, - SpvOpSignBitSet = 160, - SpvOpLessOrGreater = 161, - SpvOpOrdered = 162, - SpvOpUnordered = 163, - SpvOpLogicalEqual = 164, - SpvOpLogicalNotEqual = 165, - SpvOpLogicalOr = 166, - SpvOpLogicalAnd = 167, - SpvOpLogicalNot = 168, - SpvOpSelect = 169, - SpvOpIEqual = 170, - SpvOpINotEqual = 171, - SpvOpUGreaterThan = 172, - SpvOpSGreaterThan = 173, - SpvOpUGreaterThanEqual = 174, - SpvOpSGreaterThanEqual = 175, - SpvOpULessThan = 176, - SpvOpSLessThan = 177, - SpvOpULessThanEqual = 178, - SpvOpSLessThanEqual = 179, - SpvOpFOrdEqual = 180, - SpvOpFUnordEqual = 181, - SpvOpFOrdNotEqual = 182, - SpvOpFUnordNotEqual = 183, - SpvOpFOrdLessThan = 184, - SpvOpFUnordLessThan = 185, - SpvOpFOrdGreaterThan = 186, - SpvOpFUnordGreaterThan = 187, - SpvOpFOrdLessThanEqual = 188, - SpvOpFUnordLessThanEqual = 189, - SpvOpFOrdGreaterThanEqual = 190, - SpvOpFUnordGreaterThanEqual = 191, - SpvOpShiftRightLogical = 194, - SpvOpShiftRightArithmetic = 195, - SpvOpShiftLeftLogical = 196, - SpvOpBitwiseOr = 197, - SpvOpBitwiseXor = 198, - SpvOpBitwiseAnd = 199, - SpvOpNot = 200, - SpvOpBitFieldInsert = 201, - SpvOpBitFieldSExtract = 202, - SpvOpBitFieldUExtract = 203, - SpvOpBitReverse = 204, - SpvOpBitCount = 205, - SpvOpDPdx = 207, - SpvOpDPdy = 208, - SpvOpFwidth = 209, - SpvOpDPdxFine = 210, - SpvOpDPdyFine = 211, - SpvOpFwidthFine = 212, - SpvOpDPdxCoarse = 213, - SpvOpDPdyCoarse = 214, - SpvOpFwidthCoarse = 215, - SpvOpEmitVertex = 218, - SpvOpEndPrimitive = 219, - SpvOpEmitStreamVertex = 220, - SpvOpEndStreamPrimitive = 221, - SpvOpControlBarrier = 224, - SpvOpMemoryBarrier = 225, - SpvOpAtomicLoad = 227, - SpvOpAtomicStore = 228, - SpvOpAtomicExchange = 229, - SpvOpAtomicCompareExchange = 230, - SpvOpAtomicCompareExchangeWeak = 231, - SpvOpAtomicIIncrement = 232, - SpvOpAtomicIDecrement = 233, - SpvOpAtomicIAdd = 234, - SpvOpAtomicISub = 235, - SpvOpAtomicSMin = 236, - SpvOpAtomicUMin = 237, - SpvOpAtomicSMax = 238, - SpvOpAtomicUMax = 239, - SpvOpAtomicAnd = 240, - SpvOpAtomicOr = 241, - SpvOpAtomicXor = 242, - SpvOpPhi = 245, - SpvOpLoopMerge = 246, - SpvOpSelectionMerge = 247, - SpvOpLabel = 248, - SpvOpBranch = 249, - SpvOpBranchConditional = 250, - SpvOpSwitch = 251, - SpvOpKill = 252, - SpvOpReturn = 253, - SpvOpReturnValue = 254, - SpvOpUnreachable = 255, - SpvOpLifetimeStart = 256, - SpvOpLifetimeStop = 257, - SpvOpGroupAsyncCopy = 259, - SpvOpGroupWaitEvents = 260, - SpvOpGroupAll = 261, - SpvOpGroupAny = 262, - SpvOpGroupBroadcast = 263, - SpvOpGroupIAdd = 264, - SpvOpGroupFAdd = 265, - SpvOpGroupFMin = 266, - SpvOpGroupUMin = 267, - SpvOpGroupSMin = 268, - SpvOpGroupFMax = 269, - SpvOpGroupUMax = 270, - SpvOpGroupSMax = 271, - SpvOpReadPipe = 274, - SpvOpWritePipe = 275, - SpvOpReservedReadPipe = 276, - SpvOpReservedWritePipe = 277, - SpvOpReserveReadPipePackets = 278, - SpvOpReserveWritePipePackets = 279, - SpvOpCommitReadPipe = 280, - SpvOpCommitWritePipe = 281, - SpvOpIsValidReserveId = 282, - SpvOpGetNumPipePackets = 283, - SpvOpGetMaxPipePackets = 284, - SpvOpGroupReserveReadPipePackets = 285, - SpvOpGroupReserveWritePipePackets = 286, - SpvOpGroupCommitReadPipe = 287, - SpvOpGroupCommitWritePipe = 288, - SpvOpEnqueueMarker = 291, - SpvOpEnqueueKernel = 292, - SpvOpGetKernelNDrangeSubGroupCount = 293, - SpvOpGetKernelNDrangeMaxSubGroupSize = 294, - SpvOpGetKernelWorkGroupSize = 295, - SpvOpGetKernelPreferredWorkGroupSizeMultiple = 296, - SpvOpRetainEvent = 297, - SpvOpReleaseEvent = 298, - SpvOpCreateUserEvent = 299, - SpvOpIsValidEvent = 300, - SpvOpSetUserEventStatus = 301, - SpvOpCaptureEventProfilingInfo = 302, - SpvOpGetDefaultQueue = 303, - SpvOpBuildNDRange = 304, - SpvOpImageSparseSampleImplicitLod = 305, - SpvOpImageSparseSampleExplicitLod = 306, - SpvOpImageSparseSampleDrefImplicitLod = 307, - SpvOpImageSparseSampleDrefExplicitLod = 308, - SpvOpImageSparseSampleProjImplicitLod = 309, - SpvOpImageSparseSampleProjExplicitLod = 310, - SpvOpImageSparseSampleProjDrefImplicitLod = 311, - SpvOpImageSparseSampleProjDrefExplicitLod = 312, - SpvOpImageSparseFetch = 313, - SpvOpImageSparseGather = 314, - SpvOpImageSparseDrefGather = 315, - SpvOpImageSparseTexelsResident = 316, - SpvOpNoLine = 317, - SpvOpAtomicFlagTestAndSet = 318, - SpvOpAtomicFlagClear = 319, - SpvOpImageSparseRead = 320, - SpvOpSizeOf = 321, - SpvOpTypePipeStorage = 322, - SpvOpConstantPipeStorage = 323, - SpvOpCreatePipeFromPipeStorage = 324, - SpvOpGetKernelLocalSizeForSubgroupCount = 325, - SpvOpGetKernelMaxNumSubgroups = 326, - SpvOpTypeNamedBarrier = 327, - SpvOpNamedBarrierInitialize = 328, - SpvOpMemoryNamedBarrier = 329, - SpvOpModuleProcessed = 330, - SpvOpExecutionModeId = 331, - SpvOpDecorateId = 332, - SpvOpGroupNonUniformElect = 333, - SpvOpGroupNonUniformAll = 334, - SpvOpGroupNonUniformAny = 335, - SpvOpGroupNonUniformAllEqual = 336, - SpvOpGroupNonUniformBroadcast = 337, - SpvOpGroupNonUniformBroadcastFirst = 338, - SpvOpGroupNonUniformBallot = 339, - SpvOpGroupNonUniformInverseBallot = 340, - SpvOpGroupNonUniformBallotBitExtract = 341, - SpvOpGroupNonUniformBallotBitCount = 342, - SpvOpGroupNonUniformBallotFindLSB = 343, - SpvOpGroupNonUniformBallotFindMSB = 344, - SpvOpGroupNonUniformShuffle = 345, - SpvOpGroupNonUniformShuffleXor = 346, - SpvOpGroupNonUniformShuffleUp = 347, - SpvOpGroupNonUniformShuffleDown = 348, - SpvOpGroupNonUniformIAdd = 349, - SpvOpGroupNonUniformFAdd = 350, - SpvOpGroupNonUniformIMul = 351, - SpvOpGroupNonUniformFMul = 352, - SpvOpGroupNonUniformSMin = 353, - SpvOpGroupNonUniformUMin = 354, - SpvOpGroupNonUniformFMin = 355, - SpvOpGroupNonUniformSMax = 356, - SpvOpGroupNonUniformUMax = 357, - SpvOpGroupNonUniformFMax = 358, - SpvOpGroupNonUniformBitwiseAnd = 359, - SpvOpGroupNonUniformBitwiseOr = 360, - SpvOpGroupNonUniformBitwiseXor = 361, - SpvOpGroupNonUniformLogicalAnd = 362, - SpvOpGroupNonUniformLogicalOr = 363, - SpvOpGroupNonUniformLogicalXor = 364, - SpvOpGroupNonUniformQuadBroadcast = 365, - SpvOpGroupNonUniformQuadSwap = 366, - SpvOpCopyLogical = 400, - SpvOpPtrEqual = 401, - SpvOpPtrNotEqual = 402, - SpvOpPtrDiff = 403, - SpvOpTerminateInvocation = 4416, - SpvOpSubgroupBallotKHR = 4421, - SpvOpSubgroupFirstInvocationKHR = 4422, - SpvOpSubgroupAllKHR = 4428, - SpvOpSubgroupAnyKHR = 4429, - SpvOpSubgroupAllEqualKHR = 4430, - SpvOpSubgroupReadInvocationKHR = 4432, - SpvOpTypeRayQueryProvisionalKHR = 4472, - SpvOpRayQueryInitializeKHR = 4473, - SpvOpRayQueryTerminateKHR = 4474, - SpvOpRayQueryGenerateIntersectionKHR = 4475, - SpvOpRayQueryConfirmIntersectionKHR = 4476, - SpvOpRayQueryProceedKHR = 4477, - SpvOpRayQueryGetIntersectionTypeKHR = 4479, - SpvOpGroupIAddNonUniformAMD = 5000, - SpvOpGroupFAddNonUniformAMD = 5001, - SpvOpGroupFMinNonUniformAMD = 5002, - SpvOpGroupUMinNonUniformAMD = 5003, - SpvOpGroupSMinNonUniformAMD = 5004, - SpvOpGroupFMaxNonUniformAMD = 5005, - SpvOpGroupUMaxNonUniformAMD = 5006, - SpvOpGroupSMaxNonUniformAMD = 5007, - SpvOpFragmentMaskFetchAMD = 5011, - SpvOpFragmentFetchAMD = 5012, - SpvOpReadClockKHR = 5056, - SpvOpImageSampleFootprintNV = 5283, - SpvOpGroupNonUniformPartitionNV = 5296, - SpvOpWritePackedPrimitiveIndices4x8NV = 5299, - SpvOpReportIntersectionKHR = 5334, - SpvOpReportIntersectionNV = 5334, - SpvOpIgnoreIntersectionKHR = 5335, - SpvOpIgnoreIntersectionNV = 5335, - SpvOpTerminateRayKHR = 5336, - SpvOpTerminateRayNV = 5336, - SpvOpTraceNV = 5337, - SpvOpTraceRayKHR = 5337, - SpvOpTypeAccelerationStructureKHR = 5341, - SpvOpTypeAccelerationStructureNV = 5341, - SpvOpExecuteCallableKHR = 5344, - SpvOpExecuteCallableNV = 5344, - SpvOpTypeCooperativeMatrixNV = 5358, - SpvOpCooperativeMatrixLoadNV = 5359, - SpvOpCooperativeMatrixStoreNV = 5360, - SpvOpCooperativeMatrixMulAddNV = 5361, - SpvOpCooperativeMatrixLengthNV = 5362, - SpvOpBeginInvocationInterlockEXT = 5364, - SpvOpEndInvocationInterlockEXT = 5365, - SpvOpDemoteToHelperInvocationEXT = 5380, - SpvOpIsHelperInvocationEXT = 5381, - SpvOpSubgroupShuffleINTEL = 5571, - SpvOpSubgroupShuffleDownINTEL = 5572, - SpvOpSubgroupShuffleUpINTEL = 5573, - SpvOpSubgroupShuffleXorINTEL = 5574, - SpvOpSubgroupBlockReadINTEL = 5575, - SpvOpSubgroupBlockWriteINTEL = 5576, - SpvOpSubgroupImageBlockReadINTEL = 5577, - SpvOpSubgroupImageBlockWriteINTEL = 5578, - SpvOpSubgroupImageMediaBlockReadINTEL = 5580, - SpvOpSubgroupImageMediaBlockWriteINTEL = 5581, - SpvOpUCountLeadingZerosINTEL = 5585, - SpvOpUCountTrailingZerosINTEL = 5586, - SpvOpAbsISubINTEL = 5587, - SpvOpAbsUSubINTEL = 5588, - SpvOpIAddSatINTEL = 5589, - SpvOpUAddSatINTEL = 5590, - SpvOpIAverageINTEL = 5591, - SpvOpUAverageINTEL = 5592, - SpvOpIAverageRoundedINTEL = 5593, - SpvOpUAverageRoundedINTEL = 5594, - SpvOpISubSatINTEL = 5595, - SpvOpUSubSatINTEL = 5596, - SpvOpIMul32x16INTEL = 5597, - SpvOpUMul32x16INTEL = 5598, - SpvOpFunctionPointerINTEL = 5600, - SpvOpFunctionPointerCallINTEL = 5601, - SpvOpDecorateString = 5632, - SpvOpDecorateStringGOOGLE = 5632, - SpvOpMemberDecorateString = 5633, - SpvOpMemberDecorateStringGOOGLE = 5633, - SpvOpVmeImageINTEL = 5699, - SpvOpTypeVmeImageINTEL = 5700, - SpvOpTypeAvcImePayloadINTEL = 5701, - SpvOpTypeAvcRefPayloadINTEL = 5702, - SpvOpTypeAvcSicPayloadINTEL = 5703, - SpvOpTypeAvcMcePayloadINTEL = 5704, - SpvOpTypeAvcMceResultINTEL = 5705, - SpvOpTypeAvcImeResultINTEL = 5706, - SpvOpTypeAvcImeResultSingleReferenceStreamoutINTEL = 5707, - SpvOpTypeAvcImeResultDualReferenceStreamoutINTEL = 5708, - SpvOpTypeAvcImeSingleReferenceStreaminINTEL = 5709, - SpvOpTypeAvcImeDualReferenceStreaminINTEL = 5710, - SpvOpTypeAvcRefResultINTEL = 5711, - SpvOpTypeAvcSicResultINTEL = 5712, - SpvOpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL = 5713, - SpvOpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL = 5714, - SpvOpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL = 5715, - SpvOpSubgroupAvcMceSetInterShapePenaltyINTEL = 5716, - SpvOpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL = 5717, - SpvOpSubgroupAvcMceSetInterDirectionPenaltyINTEL = 5718, - SpvOpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL = 5719, - SpvOpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL = 5720, - SpvOpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL = 5721, - SpvOpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL = 5722, - SpvOpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL = 5723, - SpvOpSubgroupAvcMceSetMotionVectorCostFunctionINTEL = 5724, - SpvOpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL = 5725, - SpvOpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL = 5726, - SpvOpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL = 5727, - SpvOpSubgroupAvcMceSetAcOnlyHaarINTEL = 5728, - SpvOpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL = 5729, - SpvOpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL = 5730, - SpvOpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL = 5731, - SpvOpSubgroupAvcMceConvertToImePayloadINTEL = 5732, - SpvOpSubgroupAvcMceConvertToImeResultINTEL = 5733, - SpvOpSubgroupAvcMceConvertToRefPayloadINTEL = 5734, - SpvOpSubgroupAvcMceConvertToRefResultINTEL = 5735, - SpvOpSubgroupAvcMceConvertToSicPayloadINTEL = 5736, - SpvOpSubgroupAvcMceConvertToSicResultINTEL = 5737, - SpvOpSubgroupAvcMceGetMotionVectorsINTEL = 5738, - SpvOpSubgroupAvcMceGetInterDistortionsINTEL = 5739, - SpvOpSubgroupAvcMceGetBestInterDistortionsINTEL = 5740, - SpvOpSubgroupAvcMceGetInterMajorShapeINTEL = 5741, - SpvOpSubgroupAvcMceGetInterMinorShapeINTEL = 5742, - SpvOpSubgroupAvcMceGetInterDirectionsINTEL = 5743, - SpvOpSubgroupAvcMceGetInterMotionVectorCountINTEL = 5744, - SpvOpSubgroupAvcMceGetInterReferenceIdsINTEL = 5745, - SpvOpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL = 5746, - SpvOpSubgroupAvcImeInitializeINTEL = 5747, - SpvOpSubgroupAvcImeSetSingleReferenceINTEL = 5748, - SpvOpSubgroupAvcImeSetDualReferenceINTEL = 5749, - SpvOpSubgroupAvcImeRefWindowSizeINTEL = 5750, - SpvOpSubgroupAvcImeAdjustRefOffsetINTEL = 5751, - SpvOpSubgroupAvcImeConvertToMcePayloadINTEL = 5752, - SpvOpSubgroupAvcImeSetMaxMotionVectorCountINTEL = 5753, - SpvOpSubgroupAvcImeSetUnidirectionalMixDisableINTEL = 5754, - SpvOpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL = 5755, - SpvOpSubgroupAvcImeSetWeightedSadINTEL = 5756, - SpvOpSubgroupAvcImeEvaluateWithSingleReferenceINTEL = 5757, - SpvOpSubgroupAvcImeEvaluateWithDualReferenceINTEL = 5758, - SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL = 5759, - SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL = 5760, - SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL = 5761, - SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL = 5762, - SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL = 5763, - SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL = 5764, - SpvOpSubgroupAvcImeConvertToMceResultINTEL = 5765, - SpvOpSubgroupAvcImeGetSingleReferenceStreaminINTEL = 5766, - SpvOpSubgroupAvcImeGetDualReferenceStreaminINTEL = 5767, - SpvOpSubgroupAvcImeStripSingleReferenceStreamoutINTEL = 5768, - SpvOpSubgroupAvcImeStripDualReferenceStreamoutINTEL = 5769, - SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL = 5770, - SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL = 5771, - SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL = 5772, - SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL = 5773, - SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL = 5774, - SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL = 5775, - SpvOpSubgroupAvcImeGetBorderReachedINTEL = 5776, - SpvOpSubgroupAvcImeGetTruncatedSearchIndicationINTEL = 5777, - SpvOpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL = 5778, - SpvOpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL = 5779, - SpvOpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL = 5780, - SpvOpSubgroupAvcFmeInitializeINTEL = 5781, - SpvOpSubgroupAvcBmeInitializeINTEL = 5782, - SpvOpSubgroupAvcRefConvertToMcePayloadINTEL = 5783, - SpvOpSubgroupAvcRefSetBidirectionalMixDisableINTEL = 5784, - SpvOpSubgroupAvcRefSetBilinearFilterEnableINTEL = 5785, - SpvOpSubgroupAvcRefEvaluateWithSingleReferenceINTEL = 5786, - SpvOpSubgroupAvcRefEvaluateWithDualReferenceINTEL = 5787, - SpvOpSubgroupAvcRefEvaluateWithMultiReferenceINTEL = 5788, - SpvOpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL = 5789, - SpvOpSubgroupAvcRefConvertToMceResultINTEL = 5790, - SpvOpSubgroupAvcSicInitializeINTEL = 5791, - SpvOpSubgroupAvcSicConfigureSkcINTEL = 5792, - SpvOpSubgroupAvcSicConfigureIpeLumaINTEL = 5793, - SpvOpSubgroupAvcSicConfigureIpeLumaChromaINTEL = 5794, - SpvOpSubgroupAvcSicGetMotionVectorMaskINTEL = 5795, - SpvOpSubgroupAvcSicConvertToMcePayloadINTEL = 5796, - SpvOpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL = 5797, - SpvOpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL = 5798, - SpvOpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL = 5799, - SpvOpSubgroupAvcSicSetBilinearFilterEnableINTEL = 5800, - SpvOpSubgroupAvcSicSetSkcForwardTransformEnableINTEL = 5801, - SpvOpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL = 5802, - SpvOpSubgroupAvcSicEvaluateIpeINTEL = 5803, - SpvOpSubgroupAvcSicEvaluateWithSingleReferenceINTEL = 5804, - SpvOpSubgroupAvcSicEvaluateWithDualReferenceINTEL = 5805, - SpvOpSubgroupAvcSicEvaluateWithMultiReferenceINTEL = 5806, - SpvOpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL = 5807, - SpvOpSubgroupAvcSicConvertToMceResultINTEL = 5808, - SpvOpSubgroupAvcSicGetIpeLumaShapeINTEL = 5809, - SpvOpSubgroupAvcSicGetBestIpeLumaDistortionINTEL = 5810, - SpvOpSubgroupAvcSicGetBestIpeChromaDistortionINTEL = 5811, - SpvOpSubgroupAvcSicGetPackedIpeLumaModesINTEL = 5812, - SpvOpSubgroupAvcSicGetIpeChromaModeINTEL = 5813, - SpvOpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, - SpvOpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, - SpvOpSubgroupAvcSicGetInterRawSadsINTEL = 5816, - SpvOpLoopControlINTEL = 5887, - SpvOpReadPipeBlockingINTEL = 5946, - SpvOpWritePipeBlockingINTEL = 5947, - SpvOpFPGARegINTEL = 5949, - SpvOpRayQueryGetRayTMinKHR = 6016, - SpvOpRayQueryGetRayFlagsKHR = 6017, - SpvOpRayQueryGetIntersectionTKHR = 6018, - SpvOpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019, - SpvOpRayQueryGetIntersectionInstanceIdKHR = 6020, - SpvOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021, - SpvOpRayQueryGetIntersectionGeometryIndexKHR = 6022, - SpvOpRayQueryGetIntersectionPrimitiveIndexKHR = 6023, - SpvOpRayQueryGetIntersectionBarycentricsKHR = 6024, - SpvOpRayQueryGetIntersectionFrontFaceKHR = 6025, - SpvOpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026, - SpvOpRayQueryGetIntersectionObjectRayDirectionKHR = 6027, - SpvOpRayQueryGetIntersectionObjectRayOriginKHR = 6028, - SpvOpRayQueryGetWorldRayDirectionKHR = 6029, - SpvOpRayQueryGetWorldRayOriginKHR = 6030, - SpvOpRayQueryGetIntersectionObjectToWorldKHR = 6031, - SpvOpRayQueryGetIntersectionWorldToObjectKHR = 6032, - SpvOpAtomicFAddEXT = 6035, - SpvOpMax = 0x7fffffff, -} SpvOp; - -#ifdef SPV_ENABLE_UTILITY_CODE -inline void SpvHasResultAndType(SpvOp opcode, bool *hasResult, bool *hasResultType) { - *hasResult = *hasResultType = false; - switch (opcode) { - default: /* unknown opcode */ break; - case SpvOpNop: *hasResult = false; *hasResultType = false; break; - case SpvOpUndef: *hasResult = true; *hasResultType = true; break; - case SpvOpSourceContinued: *hasResult = false; *hasResultType = false; break; - case SpvOpSource: *hasResult = false; *hasResultType = false; break; - case SpvOpSourceExtension: *hasResult = false; *hasResultType = false; break; - case SpvOpName: *hasResult = false; *hasResultType = false; break; - case SpvOpMemberName: *hasResult = false; *hasResultType = false; break; - case SpvOpString: *hasResult = true; *hasResultType = false; break; - case SpvOpLine: *hasResult = false; *hasResultType = false; break; - case SpvOpExtension: *hasResult = false; *hasResultType = false; break; - case SpvOpExtInstImport: *hasResult = true; *hasResultType = false; break; - case SpvOpExtInst: *hasResult = true; *hasResultType = true; break; - case SpvOpMemoryModel: *hasResult = false; *hasResultType = false; break; - case SpvOpEntryPoint: *hasResult = false; *hasResultType = false; break; - case SpvOpExecutionMode: *hasResult = false; *hasResultType = false; break; - case SpvOpCapability: *hasResult = false; *hasResultType = false; break; - case SpvOpTypeVoid: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeBool: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeInt: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeFloat: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeVector: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeMatrix: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeImage: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeSampler: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeSampledImage: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeArray: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeRuntimeArray: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeStruct: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeOpaque: *hasResult = true; *hasResultType = false; break; - case SpvOpTypePointer: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeFunction: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeEvent: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeDeviceEvent: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeReserveId: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeQueue: *hasResult = true; *hasResultType = false; break; - case SpvOpTypePipe: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeForwardPointer: *hasResult = false; *hasResultType = false; break; - case SpvOpConstantTrue: *hasResult = true; *hasResultType = true; break; - case SpvOpConstantFalse: *hasResult = true; *hasResultType = true; break; - case SpvOpConstant: *hasResult = true; *hasResultType = true; break; - case SpvOpConstantComposite: *hasResult = true; *hasResultType = true; break; - case SpvOpConstantSampler: *hasResult = true; *hasResultType = true; break; - case SpvOpConstantNull: *hasResult = true; *hasResultType = true; break; - case SpvOpSpecConstantTrue: *hasResult = true; *hasResultType = true; break; - case SpvOpSpecConstantFalse: *hasResult = true; *hasResultType = true; break; - case SpvOpSpecConstant: *hasResult = true; *hasResultType = true; break; - case SpvOpSpecConstantComposite: *hasResult = true; *hasResultType = true; break; - case SpvOpSpecConstantOp: *hasResult = true; *hasResultType = true; break; - case SpvOpFunction: *hasResult = true; *hasResultType = true; break; - case SpvOpFunctionParameter: *hasResult = true; *hasResultType = true; break; - case SpvOpFunctionEnd: *hasResult = false; *hasResultType = false; break; - case SpvOpFunctionCall: *hasResult = true; *hasResultType = true; break; - case SpvOpVariable: *hasResult = true; *hasResultType = true; break; - case SpvOpImageTexelPointer: *hasResult = true; *hasResultType = true; break; - case SpvOpLoad: *hasResult = true; *hasResultType = true; break; - case SpvOpStore: *hasResult = false; *hasResultType = false; break; - case SpvOpCopyMemory: *hasResult = false; *hasResultType = false; break; - case SpvOpCopyMemorySized: *hasResult = false; *hasResultType = false; break; - case SpvOpAccessChain: *hasResult = true; *hasResultType = true; break; - case SpvOpInBoundsAccessChain: *hasResult = true; *hasResultType = true; break; - case SpvOpPtrAccessChain: *hasResult = true; *hasResultType = true; break; - case SpvOpArrayLength: *hasResult = true; *hasResultType = true; break; - case SpvOpGenericPtrMemSemantics: *hasResult = true; *hasResultType = true; break; - case SpvOpInBoundsPtrAccessChain: *hasResult = true; *hasResultType = true; break; - case SpvOpDecorate: *hasResult = false; *hasResultType = false; break; - case SpvOpMemberDecorate: *hasResult = false; *hasResultType = false; break; - case SpvOpDecorationGroup: *hasResult = true; *hasResultType = false; break; - case SpvOpGroupDecorate: *hasResult = false; *hasResultType = false; break; - case SpvOpGroupMemberDecorate: *hasResult = false; *hasResultType = false; break; - case SpvOpVectorExtractDynamic: *hasResult = true; *hasResultType = true; break; - case SpvOpVectorInsertDynamic: *hasResult = true; *hasResultType = true; break; - case SpvOpVectorShuffle: *hasResult = true; *hasResultType = true; break; - case SpvOpCompositeConstruct: *hasResult = true; *hasResultType = true; break; - case SpvOpCompositeExtract: *hasResult = true; *hasResultType = true; break; - case SpvOpCompositeInsert: *hasResult = true; *hasResultType = true; break; - case SpvOpCopyObject: *hasResult = true; *hasResultType = true; break; - case SpvOpTranspose: *hasResult = true; *hasResultType = true; break; - case SpvOpSampledImage: *hasResult = true; *hasResultType = true; break; - case SpvOpImageSampleImplicitLod: *hasResult = true; *hasResultType = true; break; - case SpvOpImageSampleExplicitLod: *hasResult = true; *hasResultType = true; break; - case SpvOpImageSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; - case SpvOpImageSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; - case SpvOpImageSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; - case SpvOpImageSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; - case SpvOpImageSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; - case SpvOpImageSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; - case SpvOpImageFetch: *hasResult = true; *hasResultType = true; break; - case SpvOpImageGather: *hasResult = true; *hasResultType = true; break; - case SpvOpImageDrefGather: *hasResult = true; *hasResultType = true; break; - case SpvOpImageRead: *hasResult = true; *hasResultType = true; break; - case SpvOpImageWrite: *hasResult = false; *hasResultType = false; break; - case SpvOpImage: *hasResult = true; *hasResultType = true; break; - case SpvOpImageQueryFormat: *hasResult = true; *hasResultType = true; break; - case SpvOpImageQueryOrder: *hasResult = true; *hasResultType = true; break; - case SpvOpImageQuerySizeLod: *hasResult = true; *hasResultType = true; break; - case SpvOpImageQuerySize: *hasResult = true; *hasResultType = true; break; - case SpvOpImageQueryLod: *hasResult = true; *hasResultType = true; break; - case SpvOpImageQueryLevels: *hasResult = true; *hasResultType = true; break; - case SpvOpImageQuerySamples: *hasResult = true; *hasResultType = true; break; - case SpvOpConvertFToU: *hasResult = true; *hasResultType = true; break; - case SpvOpConvertFToS: *hasResult = true; *hasResultType = true; break; - case SpvOpConvertSToF: *hasResult = true; *hasResultType = true; break; - case SpvOpConvertUToF: *hasResult = true; *hasResultType = true; break; - case SpvOpUConvert: *hasResult = true; *hasResultType = true; break; - case SpvOpSConvert: *hasResult = true; *hasResultType = true; break; - case SpvOpFConvert: *hasResult = true; *hasResultType = true; break; - case SpvOpQuantizeToF16: *hasResult = true; *hasResultType = true; break; - case SpvOpConvertPtrToU: *hasResult = true; *hasResultType = true; break; - case SpvOpSatConvertSToU: *hasResult = true; *hasResultType = true; break; - case SpvOpSatConvertUToS: *hasResult = true; *hasResultType = true; break; - case SpvOpConvertUToPtr: *hasResult = true; *hasResultType = true; break; - case SpvOpPtrCastToGeneric: *hasResult = true; *hasResultType = true; break; - case SpvOpGenericCastToPtr: *hasResult = true; *hasResultType = true; break; - case SpvOpGenericCastToPtrExplicit: *hasResult = true; *hasResultType = true; break; - case SpvOpBitcast: *hasResult = true; *hasResultType = true; break; - case SpvOpSNegate: *hasResult = true; *hasResultType = true; break; - case SpvOpFNegate: *hasResult = true; *hasResultType = true; break; - case SpvOpIAdd: *hasResult = true; *hasResultType = true; break; - case SpvOpFAdd: *hasResult = true; *hasResultType = true; break; - case SpvOpISub: *hasResult = true; *hasResultType = true; break; - case SpvOpFSub: *hasResult = true; *hasResultType = true; break; - case SpvOpIMul: *hasResult = true; *hasResultType = true; break; - case SpvOpFMul: *hasResult = true; *hasResultType = true; break; - case SpvOpUDiv: *hasResult = true; *hasResultType = true; break; - case SpvOpSDiv: *hasResult = true; *hasResultType = true; break; - case SpvOpFDiv: *hasResult = true; *hasResultType = true; break; - case SpvOpUMod: *hasResult = true; *hasResultType = true; break; - case SpvOpSRem: *hasResult = true; *hasResultType = true; break; - case SpvOpSMod: *hasResult = true; *hasResultType = true; break; - case SpvOpFRem: *hasResult = true; *hasResultType = true; break; - case SpvOpFMod: *hasResult = true; *hasResultType = true; break; - case SpvOpVectorTimesScalar: *hasResult = true; *hasResultType = true; break; - case SpvOpMatrixTimesScalar: *hasResult = true; *hasResultType = true; break; - case SpvOpVectorTimesMatrix: *hasResult = true; *hasResultType = true; break; - case SpvOpMatrixTimesVector: *hasResult = true; *hasResultType = true; break; - case SpvOpMatrixTimesMatrix: *hasResult = true; *hasResultType = true; break; - case SpvOpOuterProduct: *hasResult = true; *hasResultType = true; break; - case SpvOpDot: *hasResult = true; *hasResultType = true; break; - case SpvOpIAddCarry: *hasResult = true; *hasResultType = true; break; - case SpvOpISubBorrow: *hasResult = true; *hasResultType = true; break; - case SpvOpUMulExtended: *hasResult = true; *hasResultType = true; break; - case SpvOpSMulExtended: *hasResult = true; *hasResultType = true; break; - case SpvOpAny: *hasResult = true; *hasResultType = true; break; - case SpvOpAll: *hasResult = true; *hasResultType = true; break; - case SpvOpIsNan: *hasResult = true; *hasResultType = true; break; - case SpvOpIsInf: *hasResult = true; *hasResultType = true; break; - case SpvOpIsFinite: *hasResult = true; *hasResultType = true; break; - case SpvOpIsNormal: *hasResult = true; *hasResultType = true; break; - case SpvOpSignBitSet: *hasResult = true; *hasResultType = true; break; - case SpvOpLessOrGreater: *hasResult = true; *hasResultType = true; break; - case SpvOpOrdered: *hasResult = true; *hasResultType = true; break; - case SpvOpUnordered: *hasResult = true; *hasResultType = true; break; - case SpvOpLogicalEqual: *hasResult = true; *hasResultType = true; break; - case SpvOpLogicalNotEqual: *hasResult = true; *hasResultType = true; break; - case SpvOpLogicalOr: *hasResult = true; *hasResultType = true; break; - case SpvOpLogicalAnd: *hasResult = true; *hasResultType = true; break; - case SpvOpLogicalNot: *hasResult = true; *hasResultType = true; break; - case SpvOpSelect: *hasResult = true; *hasResultType = true; break; - case SpvOpIEqual: *hasResult = true; *hasResultType = true; break; - case SpvOpINotEqual: *hasResult = true; *hasResultType = true; break; - case SpvOpUGreaterThan: *hasResult = true; *hasResultType = true; break; - case SpvOpSGreaterThan: *hasResult = true; *hasResultType = true; break; - case SpvOpUGreaterThanEqual: *hasResult = true; *hasResultType = true; break; - case SpvOpSGreaterThanEqual: *hasResult = true; *hasResultType = true; break; - case SpvOpULessThan: *hasResult = true; *hasResultType = true; break; - case SpvOpSLessThan: *hasResult = true; *hasResultType = true; break; - case SpvOpULessThanEqual: *hasResult = true; *hasResultType = true; break; - case SpvOpSLessThanEqual: *hasResult = true; *hasResultType = true; break; - case SpvOpFOrdEqual: *hasResult = true; *hasResultType = true; break; - case SpvOpFUnordEqual: *hasResult = true; *hasResultType = true; break; - case SpvOpFOrdNotEqual: *hasResult = true; *hasResultType = true; break; - case SpvOpFUnordNotEqual: *hasResult = true; *hasResultType = true; break; - case SpvOpFOrdLessThan: *hasResult = true; *hasResultType = true; break; - case SpvOpFUnordLessThan: *hasResult = true; *hasResultType = true; break; - case SpvOpFOrdGreaterThan: *hasResult = true; *hasResultType = true; break; - case SpvOpFUnordGreaterThan: *hasResult = true; *hasResultType = true; break; - case SpvOpFOrdLessThanEqual: *hasResult = true; *hasResultType = true; break; - case SpvOpFUnordLessThanEqual: *hasResult = true; *hasResultType = true; break; - case SpvOpFOrdGreaterThanEqual: *hasResult = true; *hasResultType = true; break; - case SpvOpFUnordGreaterThanEqual: *hasResult = true; *hasResultType = true; break; - case SpvOpShiftRightLogical: *hasResult = true; *hasResultType = true; break; - case SpvOpShiftRightArithmetic: *hasResult = true; *hasResultType = true; break; - case SpvOpShiftLeftLogical: *hasResult = true; *hasResultType = true; break; - case SpvOpBitwiseOr: *hasResult = true; *hasResultType = true; break; - case SpvOpBitwiseXor: *hasResult = true; *hasResultType = true; break; - case SpvOpBitwiseAnd: *hasResult = true; *hasResultType = true; break; - case SpvOpNot: *hasResult = true; *hasResultType = true; break; - case SpvOpBitFieldInsert: *hasResult = true; *hasResultType = true; break; - case SpvOpBitFieldSExtract: *hasResult = true; *hasResultType = true; break; - case SpvOpBitFieldUExtract: *hasResult = true; *hasResultType = true; break; - case SpvOpBitReverse: *hasResult = true; *hasResultType = true; break; - case SpvOpBitCount: *hasResult = true; *hasResultType = true; break; - case SpvOpDPdx: *hasResult = true; *hasResultType = true; break; - case SpvOpDPdy: *hasResult = true; *hasResultType = true; break; - case SpvOpFwidth: *hasResult = true; *hasResultType = true; break; - case SpvOpDPdxFine: *hasResult = true; *hasResultType = true; break; - case SpvOpDPdyFine: *hasResult = true; *hasResultType = true; break; - case SpvOpFwidthFine: *hasResult = true; *hasResultType = true; break; - case SpvOpDPdxCoarse: *hasResult = true; *hasResultType = true; break; - case SpvOpDPdyCoarse: *hasResult = true; *hasResultType = true; break; - case SpvOpFwidthCoarse: *hasResult = true; *hasResultType = true; break; - case SpvOpEmitVertex: *hasResult = false; *hasResultType = false; break; - case SpvOpEndPrimitive: *hasResult = false; *hasResultType = false; break; - case SpvOpEmitStreamVertex: *hasResult = false; *hasResultType = false; break; - case SpvOpEndStreamPrimitive: *hasResult = false; *hasResultType = false; break; - case SpvOpControlBarrier: *hasResult = false; *hasResultType = false; break; - case SpvOpMemoryBarrier: *hasResult = false; *hasResultType = false; break; - case SpvOpAtomicLoad: *hasResult = true; *hasResultType = true; break; - case SpvOpAtomicStore: *hasResult = false; *hasResultType = false; break; - case SpvOpAtomicExchange: *hasResult = true; *hasResultType = true; break; - case SpvOpAtomicCompareExchange: *hasResult = true; *hasResultType = true; break; - case SpvOpAtomicCompareExchangeWeak: *hasResult = true; *hasResultType = true; break; - case SpvOpAtomicIIncrement: *hasResult = true; *hasResultType = true; break; - case SpvOpAtomicIDecrement: *hasResult = true; *hasResultType = true; break; - case SpvOpAtomicIAdd: *hasResult = true; *hasResultType = true; break; - case SpvOpAtomicISub: *hasResult = true; *hasResultType = true; break; - case SpvOpAtomicSMin: *hasResult = true; *hasResultType = true; break; - case SpvOpAtomicUMin: *hasResult = true; *hasResultType = true; break; - case SpvOpAtomicSMax: *hasResult = true; *hasResultType = true; break; - case SpvOpAtomicUMax: *hasResult = true; *hasResultType = true; break; - case SpvOpAtomicAnd: *hasResult = true; *hasResultType = true; break; - case SpvOpAtomicOr: *hasResult = true; *hasResultType = true; break; - case SpvOpAtomicXor: *hasResult = true; *hasResultType = true; break; - case SpvOpPhi: *hasResult = true; *hasResultType = true; break; - case SpvOpLoopMerge: *hasResult = false; *hasResultType = false; break; - case SpvOpSelectionMerge: *hasResult = false; *hasResultType = false; break; - case SpvOpLabel: *hasResult = true; *hasResultType = false; break; - case SpvOpBranch: *hasResult = false; *hasResultType = false; break; - case SpvOpBranchConditional: *hasResult = false; *hasResultType = false; break; - case SpvOpSwitch: *hasResult = false; *hasResultType = false; break; - case SpvOpKill: *hasResult = false; *hasResultType = false; break; - case SpvOpReturn: *hasResult = false; *hasResultType = false; break; - case SpvOpReturnValue: *hasResult = false; *hasResultType = false; break; - case SpvOpUnreachable: *hasResult = false; *hasResultType = false; break; - case SpvOpLifetimeStart: *hasResult = false; *hasResultType = false; break; - case SpvOpLifetimeStop: *hasResult = false; *hasResultType = false; break; - case SpvOpGroupAsyncCopy: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupWaitEvents: *hasResult = false; *hasResultType = false; break; - case SpvOpGroupAll: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupAny: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupBroadcast: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupIAdd: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupFAdd: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupFMin: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupUMin: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupSMin: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupFMax: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupUMax: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupSMax: *hasResult = true; *hasResultType = true; break; - case SpvOpReadPipe: *hasResult = true; *hasResultType = true; break; - case SpvOpWritePipe: *hasResult = true; *hasResultType = true; break; - case SpvOpReservedReadPipe: *hasResult = true; *hasResultType = true; break; - case SpvOpReservedWritePipe: *hasResult = true; *hasResultType = true; break; - case SpvOpReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; - case SpvOpReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; - case SpvOpCommitReadPipe: *hasResult = false; *hasResultType = false; break; - case SpvOpCommitWritePipe: *hasResult = false; *hasResultType = false; break; - case SpvOpIsValidReserveId: *hasResult = true; *hasResultType = true; break; - case SpvOpGetNumPipePackets: *hasResult = true; *hasResultType = true; break; - case SpvOpGetMaxPipePackets: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupCommitReadPipe: *hasResult = false; *hasResultType = false; break; - case SpvOpGroupCommitWritePipe: *hasResult = false; *hasResultType = false; break; - case SpvOpEnqueueMarker: *hasResult = true; *hasResultType = true; break; - case SpvOpEnqueueKernel: *hasResult = true; *hasResultType = true; break; - case SpvOpGetKernelNDrangeSubGroupCount: *hasResult = true; *hasResultType = true; break; - case SpvOpGetKernelNDrangeMaxSubGroupSize: *hasResult = true; *hasResultType = true; break; - case SpvOpGetKernelWorkGroupSize: *hasResult = true; *hasResultType = true; break; - case SpvOpGetKernelPreferredWorkGroupSizeMultiple: *hasResult = true; *hasResultType = true; break; - case SpvOpRetainEvent: *hasResult = false; *hasResultType = false; break; - case SpvOpReleaseEvent: *hasResult = false; *hasResultType = false; break; - case SpvOpCreateUserEvent: *hasResult = true; *hasResultType = true; break; - case SpvOpIsValidEvent: *hasResult = true; *hasResultType = true; break; - case SpvOpSetUserEventStatus: *hasResult = false; *hasResultType = false; break; - case SpvOpCaptureEventProfilingInfo: *hasResult = false; *hasResultType = false; break; - case SpvOpGetDefaultQueue: *hasResult = true; *hasResultType = true; break; - case SpvOpBuildNDRange: *hasResult = true; *hasResultType = true; break; - case SpvOpImageSparseSampleImplicitLod: *hasResult = true; *hasResultType = true; break; - case SpvOpImageSparseSampleExplicitLod: *hasResult = true; *hasResultType = true; break; - case SpvOpImageSparseSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; - case SpvOpImageSparseSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; - case SpvOpImageSparseSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; - case SpvOpImageSparseSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; - case SpvOpImageSparseSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; - case SpvOpImageSparseSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; - case SpvOpImageSparseFetch: *hasResult = true; *hasResultType = true; break; - case SpvOpImageSparseGather: *hasResult = true; *hasResultType = true; break; - case SpvOpImageSparseDrefGather: *hasResult = true; *hasResultType = true; break; - case SpvOpImageSparseTexelsResident: *hasResult = true; *hasResultType = true; break; - case SpvOpNoLine: *hasResult = false; *hasResultType = false; break; - case SpvOpAtomicFlagTestAndSet: *hasResult = true; *hasResultType = true; break; - case SpvOpAtomicFlagClear: *hasResult = false; *hasResultType = false; break; - case SpvOpImageSparseRead: *hasResult = true; *hasResultType = true; break; - case SpvOpSizeOf: *hasResult = true; *hasResultType = true; break; - case SpvOpTypePipeStorage: *hasResult = true; *hasResultType = false; break; - case SpvOpConstantPipeStorage: *hasResult = true; *hasResultType = true; break; - case SpvOpCreatePipeFromPipeStorage: *hasResult = true; *hasResultType = true; break; - case SpvOpGetKernelLocalSizeForSubgroupCount: *hasResult = true; *hasResultType = true; break; - case SpvOpGetKernelMaxNumSubgroups: *hasResult = true; *hasResultType = true; break; - case SpvOpTypeNamedBarrier: *hasResult = true; *hasResultType = false; break; - case SpvOpNamedBarrierInitialize: *hasResult = true; *hasResultType = true; break; - case SpvOpMemoryNamedBarrier: *hasResult = false; *hasResultType = false; break; - case SpvOpModuleProcessed: *hasResult = false; *hasResultType = false; break; - case SpvOpExecutionModeId: *hasResult = false; *hasResultType = false; break; - case SpvOpDecorateId: *hasResult = false; *hasResultType = false; break; - case SpvOpGroupNonUniformElect: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformAll: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformAny: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformAllEqual: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformBroadcast: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformBroadcastFirst: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformBallot: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformInverseBallot: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformBallotBitExtract: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformBallotBitCount: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformBallotFindLSB: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformBallotFindMSB: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformShuffle: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformShuffleXor: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformShuffleUp: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformShuffleDown: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformIAdd: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformFAdd: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformIMul: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformFMul: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformSMin: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformUMin: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformFMin: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformSMax: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformUMax: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformFMax: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformBitwiseAnd: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformBitwiseOr: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformBitwiseXor: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformLogicalAnd: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformLogicalOr: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformLogicalXor: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformQuadBroadcast: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformQuadSwap: *hasResult = true; *hasResultType = true; break; - case SpvOpCopyLogical: *hasResult = true; *hasResultType = true; break; - case SpvOpPtrEqual: *hasResult = true; *hasResultType = true; break; - case SpvOpPtrNotEqual: *hasResult = true; *hasResultType = true; break; - case SpvOpPtrDiff: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break; - case SpvOpTerminateInvocation: *hasResult = false; *hasResultType = false; break; - case SpvOpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break; - case SpvOpTypeRayQueryProvisionalKHR: *hasResult = true; *hasResultType = false; break; - case SpvOpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break; - case SpvOpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break; - case SpvOpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break; - case SpvOpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break; - case SpvOpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break; - case SpvOpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupIAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupFAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupFMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupUMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupSMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupFMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupUMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupSMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; - case SpvOpFragmentMaskFetchAMD: *hasResult = true; *hasResultType = true; break; - case SpvOpFragmentFetchAMD: *hasResult = true; *hasResultType = true; break; - case SpvOpReadClockKHR: *hasResult = true; *hasResultType = true; break; - case SpvOpImageSampleFootprintNV: *hasResult = true; *hasResultType = true; break; - case SpvOpGroupNonUniformPartitionNV: *hasResult = true; *hasResultType = true; break; - case SpvOpWritePackedPrimitiveIndices4x8NV: *hasResult = false; *hasResultType = false; break; - case SpvOpReportIntersectionNV: *hasResult = true; *hasResultType = true; break; - case SpvOpIgnoreIntersectionNV: *hasResult = false; *hasResultType = false; break; - case SpvOpTerminateRayNV: *hasResult = false; *hasResultType = false; break; - case SpvOpTraceNV: *hasResult = false; *hasResultType = false; break; - case SpvOpTypeAccelerationStructureNV: *hasResult = true; *hasResultType = false; break; - case SpvOpExecuteCallableNV: *hasResult = false; *hasResultType = false; break; - case SpvOpTypeCooperativeMatrixNV: *hasResult = true; *hasResultType = false; break; - case SpvOpCooperativeMatrixLoadNV: *hasResult = true; *hasResultType = true; break; - case SpvOpCooperativeMatrixStoreNV: *hasResult = false; *hasResultType = false; break; - case SpvOpCooperativeMatrixMulAddNV: *hasResult = true; *hasResultType = true; break; - case SpvOpCooperativeMatrixLengthNV: *hasResult = true; *hasResultType = true; break; - case SpvOpBeginInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; - case SpvOpEndInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; - case SpvOpDemoteToHelperInvocationEXT: *hasResult = false; *hasResultType = false; break; - case SpvOpIsHelperInvocationEXT: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupShuffleINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupShuffleDownINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupShuffleUpINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupShuffleXorINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupBlockReadINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; - case SpvOpSubgroupImageBlockReadINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupImageBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; - case SpvOpSubgroupImageMediaBlockReadINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupImageMediaBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; - case SpvOpUCountLeadingZerosINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpUCountTrailingZerosINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpAbsISubINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpAbsUSubINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpIAddSatINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpUAddSatINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpIAverageINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpUAverageINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpIAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpUAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpISubSatINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpUSubSatINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpFunctionPointerINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpFunctionPointerCallINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpDecorateString: *hasResult = false; *hasResultType = false; break; - case SpvOpMemberDecorateString: *hasResult = false; *hasResultType = false; break; - case SpvOpVmeImageINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpTypeVmeImageINTEL: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeAvcImePayloadINTEL: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeAvcRefPayloadINTEL: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeAvcSicPayloadINTEL: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeAvcMcePayloadINTEL: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeAvcMceResultINTEL: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeAvcImeResultINTEL: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeAvcImeResultSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeAvcImeResultDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeAvcImeSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeAvcImeDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeAvcRefResultINTEL: *hasResult = true; *hasResultType = false; break; - case SpvOpTypeAvcSicResultINTEL: *hasResult = true; *hasResultType = false; break; - case SpvOpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceSetInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceSetInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceSetMotionVectorCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceSetAcOnlyHaarINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceConvertToImePayloadINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceConvertToImeResultINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceConvertToRefPayloadINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceConvertToRefResultINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceConvertToSicPayloadINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceConvertToSicResultINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceGetMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceGetInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceGetBestInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceGetInterMajorShapeINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceGetInterMinorShapeINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceGetInterDirectionsINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceGetInterMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceGetInterReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeInitializeINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeSetSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeSetDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeRefWindowSizeINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeAdjustRefOffsetINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeSetMaxMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeSetUnidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeSetWeightedSadINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeGetSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeGetDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeStripSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeStripDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeGetBorderReachedINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeGetTruncatedSearchIndicationINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcFmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcBmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcRefConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcRefSetBidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcRefSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcRefEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcRefEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcRefEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcRefConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcSicInitializeINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcSicConfigureSkcINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcSicConfigureIpeLumaINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcSicConfigureIpeLumaChromaINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcSicGetMotionVectorMaskINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcSicConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcSicSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcSicSetSkcForwardTransformEnableINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcSicEvaluateIpeINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcSicEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcSicEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcSicEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcSicConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcSicGetIpeLumaShapeINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcSicGetBestIpeLumaDistortionINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcSicGetBestIpeChromaDistortionINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcSicGetPackedIpeLumaModesINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcSicGetIpeChromaModeINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpLoopControlINTEL: *hasResult = false; *hasResultType = false; break; - case SpvOpReadPipeBlockingINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpWritePipeBlockingINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpFPGARegINTEL: *hasResult = true; *hasResultType = true; break; - case SpvOpRayQueryGetRayTMinKHR: *hasResult = true; *hasResultType = true; break; - case SpvOpRayQueryGetRayFlagsKHR: *hasResult = true; *hasResultType = true; break; - case SpvOpRayQueryGetIntersectionTKHR: *hasResult = true; *hasResultType = true; break; - case SpvOpRayQueryGetIntersectionInstanceCustomIndexKHR: *hasResult = true; *hasResultType = true; break; - case SpvOpRayQueryGetIntersectionInstanceIdKHR: *hasResult = true; *hasResultType = true; break; - case SpvOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: *hasResult = true; *hasResultType = true; break; - case SpvOpRayQueryGetIntersectionGeometryIndexKHR: *hasResult = true; *hasResultType = true; break; - case SpvOpRayQueryGetIntersectionPrimitiveIndexKHR: *hasResult = true; *hasResultType = true; break; - case SpvOpRayQueryGetIntersectionBarycentricsKHR: *hasResult = true; *hasResultType = true; break; - case SpvOpRayQueryGetIntersectionFrontFaceKHR: *hasResult = true; *hasResultType = true; break; - case SpvOpRayQueryGetIntersectionCandidateAABBOpaqueKHR: *hasResult = true; *hasResultType = true; break; - case SpvOpRayQueryGetIntersectionObjectRayDirectionKHR: *hasResult = true; *hasResultType = true; break; - case SpvOpRayQueryGetIntersectionObjectRayOriginKHR: *hasResult = true; *hasResultType = true; break; - case SpvOpRayQueryGetWorldRayDirectionKHR: *hasResult = true; *hasResultType = true; break; - case SpvOpRayQueryGetWorldRayOriginKHR: *hasResult = true; *hasResultType = true; break; - case SpvOpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break; - case SpvOpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break; - case SpvOpAtomicFAddEXT: *hasResult = true; *hasResultType = true; break; - } -} -#endif /* SPV_ENABLE_UTILITY_CODE */ - -#endif - From c1d183833605476656900c8f0dd32157067b04e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 31 Mar 2021 10:21:35 +0200 Subject: [PATCH 088/278] ShaderLang: Proof of concept (add support for a lot of things) --- include/Nazara/Shader.hpp | 2 +- include/Nazara/Shader/Ast/Attribute.hpp | 24 + include/Nazara/Shader/Ast/ExpressionType.hpp | 96 ++++ include/Nazara/Shader/Ast/ExpressionType.inl | 111 +++++ include/Nazara/Shader/GlslWriter.hpp | 19 +- include/Nazara/Shader/ShaderAstCache.hpp | 15 +- include/Nazara/Shader/ShaderAstCache.inl | 10 +- include/Nazara/Shader/ShaderAstCloner.hpp | 4 + .../Nazara/Shader/ShaderAstExpressionType.hpp | 11 +- .../Nazara/Shader/ShaderAstExpressionType.inl | 2 +- include/Nazara/Shader/ShaderAstNodes.hpp | 1 + .../Shader/ShaderAstRecursiveVisitor.hpp | 1 + include/Nazara/Shader/ShaderAstSerializer.hpp | 8 +- include/Nazara/Shader/ShaderAstTypes.hpp | 40 -- include/Nazara/Shader/ShaderAstTypes.inl | 104 ---- include/Nazara/Shader/ShaderAstValidator.hpp | 7 +- include/Nazara/Shader/ShaderBuilder.hpp | 41 +- include/Nazara/Shader/ShaderBuilder.inl | 72 ++- include/Nazara/Shader/ShaderEnums.hpp | 35 +- include/Nazara/Shader/ShaderEnums.inl | 45 -- include/Nazara/Shader/ShaderLangParser.hpp | 27 +- include/Nazara/Shader/ShaderLangTokenList.hpp | 8 + include/Nazara/Shader/ShaderNodes.hpp | 34 +- include/Nazara/Shader/SpirvConstantCache.hpp | 17 +- include/Nazara/Shader/SpirvWriter.hpp | 10 +- src/Nazara/Shader/GlslWriter.cpp | 470 +++++++++++++++--- src/Nazara/Shader/ShaderAstCloner.cpp | 32 +- src/Nazara/Shader/ShaderAstExpressionType.cpp | 158 ++++-- src/Nazara/Shader/ShaderAstOptimizer.cpp | 4 +- .../Shader/ShaderAstRecursiveVisitor.cpp | 5 + src/Nazara/Shader/ShaderAstSerializer.cpp | 248 ++++++++- src/Nazara/Shader/ShaderAstValidator.cpp | 354 +++++++++---- src/Nazara/Shader/ShaderLangLexer.cpp | 62 ++- src/Nazara/Shader/ShaderLangParser.cpp | 447 +++++++++++++++-- src/Nazara/Shader/SpirvAstVisitor.cpp | 442 ++++++++-------- src/Nazara/Shader/SpirvConstantCache.cpp | 152 +++--- src/Nazara/Shader/SpirvWriter.cpp | 49 +- 37 files changed, 2259 insertions(+), 908 deletions(-) create mode 100644 include/Nazara/Shader/Ast/Attribute.hpp create mode 100644 include/Nazara/Shader/Ast/ExpressionType.hpp create mode 100644 include/Nazara/Shader/Ast/ExpressionType.inl delete mode 100644 include/Nazara/Shader/ShaderAstTypes.hpp delete mode 100644 include/Nazara/Shader/ShaderAstTypes.inl diff --git a/include/Nazara/Shader.hpp b/include/Nazara/Shader.hpp index 9c59a649d..cef4eada9 100644 --- a/include/Nazara/Shader.hpp +++ b/include/Nazara/Shader.hpp @@ -37,12 +37,12 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include #include diff --git a/include/Nazara/Shader/Ast/Attribute.hpp b/include/Nazara/Shader/Ast/Attribute.hpp new file mode 100644 index 000000000..9c1e0dca5 --- /dev/null +++ b/include/Nazara/Shader/Ast/Attribute.hpp @@ -0,0 +1,24 @@ +// 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_SHADERAST_ATTRIBUTES_HPP +#define NAZARA_SHADERAST_ATTRIBUTES_HPP + +#include +#include + +namespace Nz::ShaderAst +{ + struct Attribute + { + using Param = std::variant; + + AttributeType type; + Param args; + }; +} + +#endif diff --git a/include/Nazara/Shader/Ast/ExpressionType.hpp b/include/Nazara/Shader/Ast/ExpressionType.hpp new file mode 100644 index 000000000..f42776fc3 --- /dev/null +++ b/include/Nazara/Shader/Ast/ExpressionType.hpp @@ -0,0 +1,96 @@ +// 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_EXPRESSIONTYPE_HPP +#define NAZARA_SHADER_AST_EXPRESSIONTYPE_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace Nz::ShaderAst +{ + struct IdentifierType //< Alias or struct + { + std::string name; + + inline bool operator==(const IdentifierType& rhs) const; + inline bool operator!=(const IdentifierType& rhs) const; + }; + + struct MatrixType + { + std::size_t columnCount; + std::size_t rowCount; + PrimitiveType type; + + inline bool operator==(const MatrixType& rhs) const; + inline bool operator!=(const MatrixType& rhs) const; + }; + + struct NoType + { + inline bool operator==(const NoType& rhs) const; + inline bool operator!=(const NoType& rhs) const; + }; + + struct SamplerType + { + ImageType dim; + PrimitiveType sampledType; + + inline bool operator==(const SamplerType& rhs) const; + inline bool operator!=(const SamplerType& rhs) const; + }; + + struct UniformType + { + IdentifierType containedType; + + inline bool operator==(const UniformType& rhs) const; + inline bool operator!=(const UniformType& rhs) const; + }; + + struct VectorType + { + std::size_t componentCount; + PrimitiveType type; + + inline bool operator==(const VectorType& rhs) const; + inline bool operator!=(const VectorType& rhs) const; + }; + + using ExpressionType = std::variant; + + struct StructDescription + { + struct StructMember + { + std::string name; + std::vector attributes; + ExpressionType type; + }; + + std::string name; + std::vector members; + }; + + inline bool IsIdentifierType(const ExpressionType& type); + inline bool IsMatrixType(const ExpressionType& type); + inline bool IsNoType(const ExpressionType& type); + inline bool IsPrimitiveType(const ExpressionType& type); + inline bool IsSamplerType(const ExpressionType& type); + inline bool IsUniformType(const ExpressionType& type); + inline bool IsVectorType(const ExpressionType& type); +} + +#include + +#endif diff --git a/include/Nazara/Shader/Ast/ExpressionType.inl b/include/Nazara/Shader/Ast/ExpressionType.inl new file mode 100644 index 000000000..b9b7734e7 --- /dev/null +++ b/include/Nazara/Shader/Ast/ExpressionType.inl @@ -0,0 +1,111 @@ +// 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 +#include +#include + +namespace Nz::ShaderAst +{ + inline bool IdentifierType::operator==(const IdentifierType& rhs) const + { + return name == rhs.name; + } + + inline bool IdentifierType::operator!=(const IdentifierType& rhs) const + { + return !operator==(rhs); + } + + + inline bool MatrixType::operator==(const MatrixType& rhs) const + { + return columnCount == rhs.columnCount && rowCount == rhs.rowCount && type == rhs.type; + } + + inline bool MatrixType::operator!=(const MatrixType& rhs) const + { + return !operator==(rhs); + } + + + inline bool NoType::operator==(const NoType& /*rhs*/) const + { + return true; + } + + inline bool NoType::operator!=(const NoType& /*rhs*/) const + { + return false; + } + + + inline bool SamplerType::operator==(const SamplerType& rhs) const + { + return dim == rhs.dim && sampledType == rhs.sampledType; + } + + inline bool SamplerType::operator!=(const SamplerType& rhs) const + { + return !operator==(rhs); + } + + inline bool UniformType::operator==(const UniformType& rhs) const + { + return containedType == rhs.containedType; + } + + inline bool UniformType::operator!=(const UniformType& rhs) const + { + return !operator==(rhs); + } + + inline bool VectorType::operator==(const VectorType& rhs) const + { + return componentCount == rhs.componentCount && type == rhs.type; + } + + inline bool VectorType::operator!=(const VectorType& rhs) const + { + return !operator==(rhs); + } + + + inline bool IsIdentifierType(const ExpressionType& type) + { + return std::holds_alternative(type); + } + + inline bool IsMatrixType(const ExpressionType& type) + { + return std::holds_alternative(type); + } + + inline bool IsNoType(const ExpressionType& type) + { + return std::holds_alternative(type); + } + + inline bool IsPrimitiveType(const ExpressionType& type) + { + return std::holds_alternative(type); + } + + inline bool IsSamplerType(const ExpressionType& type) + { + return std::holds_alternative(type); + } + + bool IsUniformType(const ExpressionType& type) + { + return std::holds_alternative(type); + } + + bool IsVectorType(const ExpressionType& type) + { + return std::holds_alternative(type); + } +} + +#include diff --git a/include/Nazara/Shader/GlslWriter.hpp b/include/Nazara/Shader/GlslWriter.hpp index fd3c299ce..aab8f06c5 100644 --- a/include/Nazara/Shader/GlslWriter.hpp +++ b/include/Nazara/Shader/GlslWriter.hpp @@ -28,7 +28,7 @@ namespace Nz GlslWriter(GlslWriter&&) = delete; ~GlslWriter() = default; - std::string Generate(ShaderAst::StatementPtr& shader, const States& conditions = {}); + std::string Generate(ShaderStageType shaderStage, ShaderAst::StatementPtr& shader, const States& conditions = {}); void SetEnv(Environment environment); @@ -44,17 +44,26 @@ namespace Nz static const char* GetFlipYUniformName(); private: - void Append(ShaderAst::ShaderExpressionType type); + void Append(const ShaderAst::ExpressionType& type); void Append(ShaderAst::BuiltinEntry builtin); - void Append(ShaderAst::BasicType type); + void Append(const ShaderAst::IdentifierType& identifierType); + void Append(const ShaderAst::MatrixType& matrixType); void Append(ShaderAst::MemoryLayout layout); + void Append(ShaderAst::NoType); + void Append(ShaderAst::PrimitiveType type); + void Append(const ShaderAst::SamplerType& samplerType); + void Append(const ShaderAst::UniformType& uniformType); + void Append(const ShaderAst::VectorType& vecType); template void Append(const T& param); + template void Append(const T1& firstParam, const T2& secondParam, Args&&... params); void AppendCommentSection(const std::string& section); + void AppendEntryPoint(ShaderStageType shaderStage); void AppendField(std::size_t scopeId, const std::string& structName, const std::string* memberIdentifier, std::size_t remainingMembers); void AppendLine(const std::string& txt = {}); + template void AppendLine(Args&&... params); void EnterScope(); - void LeaveScope(); + void LeaveScope(bool skipLine = true); void Visit(ShaderAst::ExpressionPtr& expr, bool encloseIfRequired = false); @@ -70,7 +79,9 @@ namespace Nz void Visit(ShaderAst::BranchStatement& node) override; void Visit(ShaderAst::ConditionalStatement& node) override; + void Visit(ShaderAst::DeclareExternalStatement& node) override; void Visit(ShaderAst::DeclareFunctionStatement& node) override; + void Visit(ShaderAst::DeclareStructStatement& node) override; void Visit(ShaderAst::DeclareVariableStatement& node) override; void Visit(ShaderAst::DiscardStatement& node) override; void Visit(ShaderAst::ExpressionStatement& node) override; diff --git a/include/Nazara/Shader/ShaderAstCache.hpp b/include/Nazara/Shader/ShaderAstCache.hpp index 6e1b0a144..2a18b173d 100644 --- a/include/Nazara/Shader/ShaderAstCache.hpp +++ b/include/Nazara/Shader/ShaderAstCache.hpp @@ -16,15 +16,22 @@ namespace Nz::ShaderAst { struct AstCache { + struct Identifier; + + struct Alias + { + std::variant value; + }; + struct Variable { - ShaderExpressionType type; + ExpressionType type; }; struct Identifier { std::string name; - std::variant value; + std::variant value; }; struct Scope @@ -33,12 +40,12 @@ namespace Nz::ShaderAst std::vector identifiers; }; + inline void Clear(); inline const Identifier* FindIdentifier(std::size_t startingScopeId, const std::string& identifierName) const; inline std::size_t GetScopeId(const Node* node) const; - ShaderStageType stageType = ShaderStageType::Undefined; std::array entryFunctions = {}; - std::unordered_map nodeExpressionType; + std::unordered_map nodeExpressionType; std::unordered_map scopeIdByNode; std::vector scopes; }; diff --git a/include/Nazara/Shader/ShaderAstCache.inl b/include/Nazara/Shader/ShaderAstCache.inl index 48cd769f9..f254eac0c 100644 --- a/include/Nazara/Shader/ShaderAstCache.inl +++ b/include/Nazara/Shader/ShaderAstCache.inl @@ -7,6 +7,14 @@ namespace Nz::ShaderAst { + inline void AstCache::Clear() + { + entryFunctions.fill(nullptr); + nodeExpressionType.clear(); + scopeIdByNode.clear(); + scopes.clear(); + } + inline auto AstCache::FindIdentifier(std::size_t startingScopeId, const std::string& identifierName) const -> const Identifier* { assert(startingScopeId < scopes.size()); @@ -28,7 +36,7 @@ namespace Nz::ShaderAst inline std::size_t AstCache::GetScopeId(const Node* node) const { auto it = scopeIdByNode.find(node); - assert(it == scopeIdByNode.end()); + assert(it != scopeIdByNode.end()); return it->second; } diff --git a/include/Nazara/Shader/ShaderAstCloner.hpp b/include/Nazara/Shader/ShaderAstCloner.hpp index 23e69234a..a2ee45f44 100644 --- a/include/Nazara/Shader/ShaderAstCloner.hpp +++ b/include/Nazara/Shader/ShaderAstCloner.hpp @@ -33,6 +33,8 @@ namespace Nz::ShaderAst ExpressionPtr CloneExpression(ExpressionPtr& expr); StatementPtr CloneStatement(StatementPtr& statement); + virtual std::unique_ptr Clone(DeclareFunctionStatement& node); + using AstExpressionVisitor::Visit; using AstStatementVisitor::Visit; @@ -45,8 +47,10 @@ namespace Nz::ShaderAst void Visit(IdentifierExpression& node) override; void Visit(IntrinsicExpression& node) override; void Visit(SwizzleExpression& node) override; + void Visit(BranchStatement& node) override; void Visit(ConditionalStatement& node) override; + void Visit(DeclareExternalStatement& node) override; void Visit(DeclareFunctionStatement& node) override; void Visit(DeclareStructStatement& node) override; void Visit(DeclareVariableStatement& node) override; diff --git a/include/Nazara/Shader/ShaderAstExpressionType.hpp b/include/Nazara/Shader/ShaderAstExpressionType.hpp index 4ad7731e8..095b5e5ea 100644 --- a/include/Nazara/Shader/ShaderAstExpressionType.hpp +++ b/include/Nazara/Shader/ShaderAstExpressionType.hpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include namespace Nz::ShaderAst @@ -25,13 +25,14 @@ namespace Nz::ShaderAst ExpressionTypeVisitor(ExpressionTypeVisitor&&) = delete; ~ExpressionTypeVisitor() = default; - ShaderExpressionType GetExpressionType(Expression& expression, AstCache* cache); + ExpressionType GetExpressionType(Expression& expression, AstCache* cache); ExpressionTypeVisitor& operator=(const ExpressionTypeVisitor&) = delete; ExpressionTypeVisitor& operator=(ExpressionTypeVisitor&&) = delete; private: - ShaderExpressionType GetExpressionTypeInternal(Expression& expression); + ExpressionType GetExpressionTypeInternal(Expression& expression); + ExpressionType ResolveAlias(Expression& expression, ExpressionType expressionType); void Visit(Expression& expression); @@ -46,10 +47,10 @@ namespace Nz::ShaderAst void Visit(SwizzleExpression& node) override; AstCache* m_cache; - std::optional m_lastExpressionType; + std::optional m_lastExpressionType; }; - inline ShaderExpressionType GetExpressionType(Expression& expression, AstCache* cache = nullptr); + inline ExpressionType GetExpressionType(Expression& expression, AstCache* cache = nullptr); } #include diff --git a/include/Nazara/Shader/ShaderAstExpressionType.inl b/include/Nazara/Shader/ShaderAstExpressionType.inl index f71146200..279a3909e 100644 --- a/include/Nazara/Shader/ShaderAstExpressionType.inl +++ b/include/Nazara/Shader/ShaderAstExpressionType.inl @@ -7,7 +7,7 @@ namespace Nz::ShaderAst { - inline ShaderExpressionType GetExpressionType(Expression& expression, AstCache* cache) + inline ExpressionType GetExpressionType(Expression& expression, AstCache* cache) { ExpressionTypeVisitor visitor; return visitor.GetExpressionType(expression, cache); diff --git a/include/Nazara/Shader/ShaderAstNodes.hpp b/include/Nazara/Shader/ShaderAstNodes.hpp index 7bbce68a9..86b19521b 100644 --- a/include/Nazara/Shader/ShaderAstNodes.hpp +++ b/include/Nazara/Shader/ShaderAstNodes.hpp @@ -37,6 +37,7 @@ NAZARA_SHADERAST_EXPRESSION(IntrinsicExpression) NAZARA_SHADERAST_EXPRESSION(SwizzleExpression) NAZARA_SHADERAST_STATEMENT(BranchStatement) NAZARA_SHADERAST_STATEMENT(ConditionalStatement) +NAZARA_SHADERAST_STATEMENT(DeclareExternalStatement) NAZARA_SHADERAST_STATEMENT(DeclareFunctionStatement) NAZARA_SHADERAST_STATEMENT(DeclareStructStatement) NAZARA_SHADERAST_STATEMENT(DeclareVariableStatement) diff --git a/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp b/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp index 68251ddc0..1bfbb65da 100644 --- a/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp +++ b/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp @@ -32,6 +32,7 @@ namespace Nz::ShaderAst void Visit(BranchStatement& node) override; void Visit(ConditionalStatement& node) override; + void Visit(DeclareExternalStatement& node) override; void Visit(DeclareFunctionStatement& node) override; void Visit(DeclareStructStatement& node) override; void Visit(DeclareVariableStatement& node) override; diff --git a/include/Nazara/Shader/ShaderAstSerializer.hpp b/include/Nazara/Shader/ShaderAstSerializer.hpp index fe09ea604..2cb0bd5f1 100644 --- a/include/Nazara/Shader/ShaderAstSerializer.hpp +++ b/include/Nazara/Shader/ShaderAstSerializer.hpp @@ -35,6 +35,7 @@ namespace Nz::ShaderAst void Serialize(BranchStatement& node); void Serialize(ConditionalStatement& node); + void Serialize(DeclareExternalStatement& node); void Serialize(DeclareFunctionStatement& node); void Serialize(DeclareStructStatement& node); void Serialize(DeclareVariableStatement& node); @@ -45,6 +46,7 @@ namespace Nz::ShaderAst void Serialize(ReturnStatement& node); protected: + void Attributes(std::vector& attributes); template void Container(T& container); template void Enum(T& enumVal); template void OptEnum(std::optional& optVal); @@ -55,7 +57,7 @@ namespace Nz::ShaderAst virtual void Node(ExpressionPtr& node) = 0; virtual void Node(StatementPtr& node) = 0; - virtual void Type(ShaderExpressionType& type) = 0; + virtual void Type(ExpressionType& type) = 0; virtual void Value(bool& val) = 0; virtual void Value(float& val) = 0; @@ -86,7 +88,7 @@ namespace Nz::ShaderAst bool IsWriting() const override; void Node(ExpressionPtr& node) override; void Node(StatementPtr& node) override; - void Type(ShaderExpressionType& type) override; + void Type(ExpressionType& type) override; void Value(bool& val) override; void Value(float& val) override; void Value(std::string& val) override; @@ -117,7 +119,7 @@ namespace Nz::ShaderAst bool IsWriting() const override; void Node(ExpressionPtr& node) override; void Node(StatementPtr& node) override; - void Type(ShaderExpressionType& type) override; + void Type(ExpressionType& type) override; void Value(bool& val) override; void Value(float& val) override; void Value(std::string& val) override; diff --git a/include/Nazara/Shader/ShaderAstTypes.hpp b/include/Nazara/Shader/ShaderAstTypes.hpp deleted file mode 100644 index e1f50d4e7..000000000 --- a/include/Nazara/Shader/ShaderAstTypes.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// 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_ASTTYPES_HPP -#define NAZARA_SHADER_ASTTYPES_HPP - -#include -#include -#include -#include -#include - -namespace Nz::ShaderAst -{ - using ShaderExpressionType = std::variant; - - struct StructDescription - { - struct StructMember - { - std::string name; - ShaderExpressionType type; - }; - - std::string name; - std::vector members; - }; - - inline bool IsBasicType(const ShaderExpressionType& type); - inline bool IsMatrixType(const ShaderExpressionType& type); - inline bool IsSamplerType(const ShaderExpressionType& type); - inline bool IsStructType(const ShaderExpressionType& type); -} - -#include - -#endif // NAZARA_SHADER_ASTTYPES_HPP diff --git a/include/Nazara/Shader/ShaderAstTypes.inl b/include/Nazara/Shader/ShaderAstTypes.inl deleted file mode 100644 index 6eed4a945..000000000 --- a/include/Nazara/Shader/ShaderAstTypes.inl +++ /dev/null @@ -1,104 +0,0 @@ -// 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 -#include -#include - -namespace Nz::ShaderAst -{ - inline bool IsBasicType(const ShaderExpressionType& type) - { - return std::visit([&](auto&& arg) - { - using T = std::decay_t; - if constexpr (std::is_same_v) - return true; - else if constexpr (std::is_same_v) - return false; - else - static_assert(AlwaysFalse::value, "non-exhaustive visitor"); - - }, type); - } - - inline bool IsMatrixType(const ShaderExpressionType& type) - { - if (!IsBasicType(type)) - return false; - - switch (std::get(type)) - { - case BasicType::Mat4x4: - return true; - - case BasicType::Boolean: - case BasicType::Float1: - case BasicType::Float2: - case BasicType::Float3: - case BasicType::Float4: - case BasicType::Int1: - case BasicType::Int2: - case BasicType::Int3: - case BasicType::Int4: - case BasicType::Sampler2D: - case BasicType::Void: - case BasicType::UInt1: - case BasicType::UInt2: - case BasicType::UInt3: - case BasicType::UInt4: - return false; - } - - return false; - } - - inline bool IsSamplerType(const ShaderExpressionType& type) - { - if (!IsBasicType(type)) - return false; - - switch (std::get(type)) - { - case BasicType::Sampler2D: - return true; - - case BasicType::Boolean: - case BasicType::Float1: - case BasicType::Float2: - case BasicType::Float3: - case BasicType::Float4: - case BasicType::Int1: - case BasicType::Int2: - case BasicType::Int3: - case BasicType::Int4: - case BasicType::Mat4x4: - case BasicType::Void: - case BasicType::UInt1: - case BasicType::UInt2: - case BasicType::UInt3: - case BasicType::UInt4: - return false; - } - - return false; - } - - inline bool IsStructType(const ShaderExpressionType& type) - { - return std::visit([&](auto&& arg) - { - using T = std::decay_t; - if constexpr (std::is_same_v) - return false; - else if constexpr (std::is_same_v) - return true; - else - static_assert(AlwaysFalse::value, "non-exhaustive visitor"); - - }, type); - } -} - -#include diff --git a/include/Nazara/Shader/ShaderAstValidator.hpp b/include/Nazara/Shader/ShaderAstValidator.hpp index 00d708d96..e3dd4d94e 100644 --- a/include/Nazara/Shader/ShaderAstValidator.hpp +++ b/include/Nazara/Shader/ShaderAstValidator.hpp @@ -29,14 +29,14 @@ namespace Nz::ShaderAst Expression& MandatoryExpr(ExpressionPtr& node); Statement& MandatoryStatement(StatementPtr& node); void TypeMustMatch(ExpressionPtr& left, ExpressionPtr& right); - void TypeMustMatch(const ShaderExpressionType& left, const ShaderExpressionType& right); + void TypeMustMatch(const ExpressionType& left, const ExpressionType& right); - ShaderExpressionType CheckField(const std::string& structName, const std::string* memberIdentifier, std::size_t remainingMembers); + ExpressionType CheckField(const std::string& structName, const std::string* memberIdentifier, std::size_t remainingMembers); AstCache::Scope& EnterScope(); void ExitScope(); - void RegisterExpressionType(Expression& node, ShaderExpressionType expressionType); + void RegisterExpressionType(Expression& node, ExpressionType expressionType); void RegisterScope(Node& node); void Visit(AccessMemberExpression& node) override; @@ -51,6 +51,7 @@ namespace Nz::ShaderAst void Visit(BranchStatement& node) override; void Visit(ConditionalStatement& node) override; + void Visit(DeclareExternalStatement& node) override; void Visit(DeclareFunctionStatement& node) override; void Visit(DeclareStructStatement& node) override; void Visit(DeclareVariableStatement& node) override; diff --git a/include/Nazara/Shader/ShaderBuilder.hpp b/include/Nazara/Shader/ShaderBuilder.hpp index 625875470..c6edb8041 100644 --- a/include/Nazara/Shader/ShaderBuilder.hpp +++ b/include/Nazara/Shader/ShaderBuilder.hpp @@ -15,6 +15,11 @@ namespace Nz::ShaderBuilder { namespace Impl { + struct Assign + { + inline std::unique_ptr operator()(ShaderAst::AssignType op, ShaderAst::ExpressionPtr left, ShaderAst::ExpressionPtr right) const; + }; + struct Binary { inline std::unique_ptr operator()(ShaderAst::BinaryType op, ShaderAst::ExpressionPtr left, ShaderAst::ExpressionPtr right) const; @@ -26,6 +31,11 @@ namespace Nz::ShaderBuilder inline std::unique_ptr operator()(std::vector condStatements, ShaderAst::StatementPtr elseStatement = nullptr) const; }; + struct Cast + { + inline std::unique_ptr operator()(ShaderAst::ExpressionType targetType, std::vector expressions) const; + }; + struct Constant { inline std::unique_ptr operator()(ShaderConstantValue value) const; @@ -33,13 +43,24 @@ namespace Nz::ShaderBuilder struct DeclareFunction { - inline std::unique_ptr operator()(std::string name, std::vector parameters, std::vector statements, ShaderAst::ShaderExpressionType returnType = ShaderAst::BasicType::Void) const; - inline std::unique_ptr operator()(std::vector attributes, std::string name, std::vector parameters, std::vector statements, ShaderAst::ShaderExpressionType returnType = ShaderAst::BasicType::Void) const; + inline std::unique_ptr operator()(std::string name, std::vector parameters, std::vector statements, ShaderAst::ExpressionType returnType = ShaderAst::NoType{}) const; + inline std::unique_ptr operator()(std::vector attributes, std::string name, std::vector parameters, std::vector statements, ShaderAst::ExpressionType returnType = ShaderAst::NoType{}) const; + }; + + struct DeclareStruct + { + inline std::unique_ptr operator()(ShaderAst::StructDescription description) const; + inline std::unique_ptr operator()(std::vector attributes, ShaderAst::StructDescription description) const; }; struct DeclareVariable { - inline std::unique_ptr operator()(std::string name, ShaderAst::ShaderExpressionType type, ShaderAst::ExpressionPtr initialValue = nullptr) const; + inline std::unique_ptr operator()(std::string name, ShaderAst::ExpressionType type, ShaderAst::ExpressionPtr initialValue = nullptr) const; + }; + + struct ExpressionStatement + { + inline std::unique_ptr operator()(ShaderAst::ExpressionPtr expression) const; }; struct Identifier @@ -47,9 +68,9 @@ namespace Nz::ShaderBuilder inline std::unique_ptr operator()(std::string name) const; }; - struct Return + struct Intrinsic { - inline std::unique_ptr operator()(ShaderAst::ExpressionPtr expr = nullptr) const; + inline std::unique_ptr operator()(ShaderAst::IntrinsicType intrinsicType, std::vector parameters) const; }; template @@ -57,15 +78,25 @@ namespace Nz::ShaderBuilder { std::unique_ptr operator()() const; }; + + struct Return + { + inline std::unique_ptr operator()(ShaderAst::ExpressionPtr expr = nullptr) const; + }; } + constexpr Impl::Assign Assign; constexpr Impl::Binary Binary; constexpr Impl::Branch Branch; + constexpr Impl::Cast Cast; constexpr Impl::Constant Constant; constexpr Impl::DeclareFunction DeclareFunction; + constexpr Impl::DeclareStruct DeclareStruct; constexpr Impl::DeclareVariable DeclareVariable; + constexpr Impl::ExpressionStatement ExpressionStatement; constexpr Impl::NoParam Discard; constexpr Impl::Identifier Identifier; + constexpr Impl::Intrinsic Intrinsic; constexpr Impl::NoParam NoOp; constexpr Impl::Return Return; } diff --git a/include/Nazara/Shader/ShaderBuilder.inl b/include/Nazara/Shader/ShaderBuilder.inl index 31fb4dcf9..feff95b8a 100644 --- a/include/Nazara/Shader/ShaderBuilder.inl +++ b/include/Nazara/Shader/ShaderBuilder.inl @@ -7,14 +7,24 @@ namespace Nz::ShaderBuilder { + inline std::unique_ptr Impl::Assign::operator()(ShaderAst::AssignType op, ShaderAst::ExpressionPtr left, ShaderAst::ExpressionPtr right) const + { + auto assignNode = std::make_unique(); + assignNode->op = op; + assignNode->left = std::move(left); + assignNode->right = std::move(right); + + return assignNode; + } + inline std::unique_ptr Impl::Binary::operator()(ShaderAst::BinaryType op, ShaderAst::ExpressionPtr left, ShaderAst::ExpressionPtr right) const { - auto constantNode = std::make_unique(); - constantNode->op = op; - constantNode->left = std::move(left); - constantNode->right = std::move(right); + auto binaryNode = std::make_unique(); + binaryNode->op = op; + binaryNode->left = std::move(left); + binaryNode->right = std::move(right); - return constantNode; + return binaryNode; } inline std::unique_ptr Impl::Branch::operator()(ShaderAst::ExpressionPtr condition, ShaderAst::StatementPtr truePath, ShaderAst::StatementPtr falsePath) const @@ -39,6 +49,18 @@ namespace Nz::ShaderBuilder return branchNode; } + inline std::unique_ptr Impl::Cast::operator()(ShaderAst::ExpressionType targetType, std::vector expressions) const + { + auto castNode = std::make_unique(); + castNode->targetType = std::move(targetType); + + assert(expressions.size() <= castNode->expressions.size()); + for (std::size_t i = 0; i < expressions.size(); ++i) + castNode->expressions[i] = std::move(expressions[i]); + + return castNode; + } + inline std::unique_ptr Impl::Constant::operator()(ShaderConstantValue value) const { auto constantNode = std::make_unique(); @@ -47,7 +69,7 @@ namespace Nz::ShaderBuilder return constantNode; } - inline std::unique_ptr Impl::DeclareFunction::operator()(std::string name, std::vector parameters, std::vector statements, ShaderAst::ShaderExpressionType returnType) const + inline std::unique_ptr Impl::DeclareFunction::operator()(std::string name, std::vector parameters, std::vector statements, ShaderAst::ExpressionType returnType) const { auto declareFunctionNode = std::make_unique(); declareFunctionNode->name = std::move(name); @@ -58,7 +80,7 @@ namespace Nz::ShaderBuilder return declareFunctionNode; } - inline std::unique_ptr Impl::DeclareFunction::operator()(std::vector attributes, std::string name, std::vector parameters, std::vector statements, ShaderAst::ShaderExpressionType returnType) const + inline std::unique_ptr Impl::DeclareFunction::operator()(std::vector attributes, std::string name, std::vector parameters, std::vector statements, ShaderAst::ExpressionType returnType) const { auto declareFunctionNode = std::make_unique(); declareFunctionNode->attributes = std::move(attributes); @@ -70,7 +92,24 @@ namespace Nz::ShaderBuilder return declareFunctionNode; } - inline std::unique_ptr Nz::ShaderBuilder::Impl::DeclareVariable::operator()(std::string name, ShaderAst::ShaderExpressionType type, ShaderAst::ExpressionPtr initialValue) const + inline std::unique_ptr Impl::DeclareStruct::operator()(ShaderAst::StructDescription description) const + { + auto declareStructNode = std::make_unique(); + declareStructNode->description = std::move(description); + + return declareStructNode; + } + + inline std::unique_ptr Impl::DeclareStruct::operator()(std::vector attributes, ShaderAst::StructDescription description) const + { + auto declareStructNode = std::make_unique(); + declareStructNode->attributes = std::move(attributes); + declareStructNode->description = std::move(description); + + return declareStructNode; + } + + inline std::unique_ptr Nz::ShaderBuilder::Impl::DeclareVariable::operator()(std::string name, ShaderAst::ExpressionType type, ShaderAst::ExpressionPtr initialValue) const { auto declareVariableNode = std::make_unique(); declareVariableNode->varName = std::move(name); @@ -80,6 +119,14 @@ namespace Nz::ShaderBuilder return declareVariableNode; } + inline std::unique_ptr Impl::ExpressionStatement::operator()(ShaderAst::ExpressionPtr expression) const + { + auto expressionStatementNode = std::make_unique(); + expressionStatementNode->expression = std::move(expression); + + return expressionStatementNode; + } + inline std::unique_ptr Impl::Identifier::operator()(std::string name) const { auto identifierNode = std::make_unique(); @@ -88,6 +135,15 @@ namespace Nz::ShaderBuilder return identifierNode; } + inline std::unique_ptr Impl::Intrinsic::operator()(ShaderAst::IntrinsicType intrinsicType, std::vector parameters) const + { + auto intrinsicExpression = std::make_unique(); + intrinsicExpression->intrinsic = intrinsicType; + intrinsicExpression->parameters = std::move(parameters); + + return intrinsicExpression; + } + inline std::unique_ptr Impl::Return::operator()(ShaderAst::ExpressionPtr expr) const { auto returnNode = std::make_unique(); diff --git a/include/Nazara/Shader/ShaderEnums.hpp b/include/Nazara/Shader/ShaderEnums.hpp index 5c2d3136d..e56e71093 100644 --- a/include/Nazara/Shader/ShaderEnums.hpp +++ b/include/Nazara/Shader/ShaderEnums.hpp @@ -18,28 +18,19 @@ namespace Nz::ShaderAst enum class AttributeType { - Entry, //< Entry point (function only) - has argument type - Layout //< Struct layout (struct only) - has argument style + Binding, //< Binding (external var only) - has argument index + Builtin, //< Builtin (struct member only) - has argument type + Entry, //< Entry point (function only) - has argument type + Layout, //< Struct layout (struct only) - has argument style + Location //< Location (struct member only) - has argument index }; - enum class BasicType + enum class PrimitiveType { - Boolean, //< bool - Float1, //< float - Float2, //< vec2 - Float3, //< vec3 - Float4, //< vec4 - Int1, //< int - Int2, //< ivec2 - Int3, //< ivec3 - Int4, //< ivec4 - Mat4x4, //< mat4 - Sampler2D, //< sampler2D - Void, //< void - UInt1, //< uint - UInt2, //< uvec2 - UInt3, //< uvec3 - UInt4 //< uvec4 + Boolean, //< bool + Float32, //< f32 + Int32, //< i32 + UInt32, //< ui32 }; enum class BinaryType @@ -71,7 +62,8 @@ namespace Nz::ShaderAst enum class IntrinsicType { CrossProduct, - DotProduct + DotProduct, + SampleTexture }; enum class MemoryLayout @@ -107,9 +99,6 @@ namespace Nz::ShaderAst ParameterVariable, UniformVariable }; - - inline std::size_t GetComponentCount(BasicType type); - inline BasicType GetComponentType(BasicType type); } #include diff --git a/include/Nazara/Shader/ShaderEnums.inl b/include/Nazara/Shader/ShaderEnums.inl index fbd01ad49..a24138a6e 100644 --- a/include/Nazara/Shader/ShaderEnums.inl +++ b/include/Nazara/Shader/ShaderEnums.inl @@ -7,51 +7,6 @@ namespace Nz::ShaderAst { - inline std::size_t GetComponentCount(BasicType type) - { - switch (type) - { - case BasicType::Float2: - case BasicType::Int2: - return 2; - - case BasicType::Float3: - case BasicType::Int3: - return 3; - - case BasicType::Float4: - case BasicType::Int4: - return 4; - - case BasicType::Mat4x4: - return 4; - - default: - return 1; - } - } - - inline BasicType GetComponentType(BasicType type) - { - switch (type) - { - case BasicType::Float2: - case BasicType::Float3: - case BasicType::Float4: - return BasicType::Float1; - - case BasicType::Int2: - case BasicType::Int3: - case BasicType::Int4: - return BasicType::Int1; - - case BasicType::Mat4x4: - return BasicType::Float4; - - default: - return type; - } - } } #include diff --git a/include/Nazara/Shader/ShaderLangParser.hpp b/include/Nazara/Shader/ShaderLangParser.hpp index ba727b73a..3c61ec888 100644 --- a/include/Nazara/Shader/ShaderLangParser.hpp +++ b/include/Nazara/Shader/ShaderLangParser.hpp @@ -19,6 +19,12 @@ namespace Nz::ShaderLang public: using exception::exception; }; + + class DuplicateIdentifier : public std::exception + { + public: + using exception::exception; + }; class ReservedKeyword : public std::exception { @@ -56,17 +62,24 @@ namespace Nz::ShaderLang // Flow control const Token& Advance(); void Consume(std::size_t count = 1); + ShaderAst::ExpressionType DecodeType(const std::string& identifier); + void EnterScope(); const Token& Expect(const Token& token, TokenType type); const Token& ExpectNot(const Token& token, TokenType type); const Token& Expect(TokenType type); + void LeaveScope(); + bool IsVariableInScope(const std::string_view& identifier) const; + void RegisterVariable(std::string identifier); const Token& Peek(std::size_t advance = 0); - void HandleAttributes(); + std::vector ParseAttributes(); // Statements + ShaderAst::StatementPtr ParseExternalBlock(std::vector attributes = {}); std::vector ParseFunctionBody(); ShaderAst::StatementPtr ParseFunctionDeclaration(std::vector attributes = {}); ShaderAst::DeclareFunctionStatement::Parameter ParseFunctionParameter(); + ShaderAst::StatementPtr ParseStructDeclaration(std::vector attributes = {}); ShaderAst::StatementPtr ParseReturnStatement(); ShaderAst::StatementPtr ParseStatement(); std::vector ParseStatementList(); @@ -75,22 +88,28 @@ namespace Nz::ShaderLang // Expressions ShaderAst::ExpressionPtr ParseBinOpRhs(int exprPrecedence, ShaderAst::ExpressionPtr lhs); ShaderAst::ExpressionPtr ParseExpression(); + ShaderAst::ExpressionPtr ParseFloatingPointExpression(bool minus = false); ShaderAst::ExpressionPtr ParseIdentifier(); - ShaderAst::ExpressionPtr ParseIntegerExpression(); + ShaderAst::ExpressionPtr ParseIntegerExpression(bool minus = false); + std::vector ParseParameters(); ShaderAst::ExpressionPtr ParseParenthesisExpression(); ShaderAst::ExpressionPtr ParsePrimaryExpression(); + ShaderAst::ExpressionPtr ParseVariableAssignation(); ShaderAst::AttributeType ParseIdentifierAsAttributeType(); const std::string& ParseIdentifierAsName(); - ShaderAst::ShaderExpressionType ParseIdentifierAsType(); + ShaderAst::PrimitiveType ParsePrimitiveType(); + ShaderAst::ExpressionType ParseType(); static int GetTokenPrecedence(TokenType token); struct Context { - std::unique_ptr root; std::size_t tokenCount; std::size_t tokenIndex = 0; + std::vector scopeSizes; + std::vector identifiersInScope; + std::unique_ptr root; const Token* tokens; }; diff --git a/include/Nazara/Shader/ShaderLangTokenList.hpp b/include/Nazara/Shader/ShaderLangTokenList.hpp index 959c5df31..9b818cd0b 100644 --- a/include/Nazara/Shader/ShaderLangTokenList.hpp +++ b/include/Nazara/Shader/ShaderLangTokenList.hpp @@ -21,15 +21,22 @@ NAZARA_SHADERLANG_TOKEN(Colon) NAZARA_SHADERLANG_TOKEN(Comma) NAZARA_SHADERLANG_TOKEN(Divide) NAZARA_SHADERLANG_TOKEN(Dot) +NAZARA_SHADERLANG_TOKEN(Equal) +NAZARA_SHADERLANG_TOKEN(External) NAZARA_SHADERLANG_TOKEN(FloatingPointValue) NAZARA_SHADERLANG_TOKEN(EndOfStream) NAZARA_SHADERLANG_TOKEN(FunctionDeclaration) NAZARA_SHADERLANG_TOKEN(FunctionReturn) +NAZARA_SHADERLANG_TOKEN(GreatherThan) +NAZARA_SHADERLANG_TOKEN(GreatherThanEqual) NAZARA_SHADERLANG_TOKEN(IntegerValue) NAZARA_SHADERLANG_TOKEN(Identifier) +NAZARA_SHADERLANG_TOKEN(LessThan) +NAZARA_SHADERLANG_TOKEN(LessThanEqual) NAZARA_SHADERLANG_TOKEN(Let) NAZARA_SHADERLANG_TOKEN(Multiply) NAZARA_SHADERLANG_TOKEN(Minus) +NAZARA_SHADERLANG_TOKEN(NotEqual) NAZARA_SHADERLANG_TOKEN(Plus) NAZARA_SHADERLANG_TOKEN(OpenAttribute) NAZARA_SHADERLANG_TOKEN(OpenCurlyBracket) @@ -37,6 +44,7 @@ NAZARA_SHADERLANG_TOKEN(OpenSquareBracket) NAZARA_SHADERLANG_TOKEN(OpenParenthesis) NAZARA_SHADERLANG_TOKEN(Semicolon) NAZARA_SHADERLANG_TOKEN(Return) +NAZARA_SHADERLANG_TOKEN(Struct) #undef NAZARA_SHADERLANG_TOKEN #undef NAZARA_SHADERLANG_TOKEN_LAST diff --git a/include/Nazara/Shader/ShaderNodes.hpp b/include/Nazara/Shader/ShaderNodes.hpp index 386f53168..bfd0ebb47 100644 --- a/include/Nazara/Shader/ShaderNodes.hpp +++ b/include/Nazara/Shader/ShaderNodes.hpp @@ -12,9 +12,10 @@ #include #include #include -#include #include #include +#include +#include #include #include #include @@ -25,12 +26,6 @@ namespace Nz::ShaderAst class AstExpressionVisitor; class AstStatementVisitor; - struct Attribute - { - AttributeType type; - std::string args; - }; - struct NAZARA_SHADER_API Node { Node() = default; @@ -97,7 +92,7 @@ namespace Nz::ShaderAst NodeType GetType() const override; void Visit(AstExpressionVisitor& visitor) override; - BasicType targetType; + ExpressionType targetType; std::array expressions; }; @@ -189,6 +184,22 @@ namespace Nz::ShaderAst StatementPtr statement; }; + struct NAZARA_SHADER_API DeclareExternalStatement : Statement + { + NodeType GetType() const override; + void Visit(AstStatementVisitor& visitor) override; + + struct ExternalVar + { + std::vector attributes; + std::string name; + ExpressionType type; + }; + + std::vector attributes; + std::vector externalVars; + }; + struct NAZARA_SHADER_API DeclareFunctionStatement : Statement { NodeType GetType() const override; @@ -197,14 +208,14 @@ namespace Nz::ShaderAst struct Parameter { std::string name; - ShaderExpressionType type; + ExpressionType type; }; std::string name; std::vector attributes; std::vector parameters; std::vector statements; - ShaderExpressionType returnType = BasicType::Void; + ExpressionType returnType; }; struct NAZARA_SHADER_API DeclareStructStatement : Statement @@ -212,6 +223,7 @@ namespace Nz::ShaderAst NodeType GetType() const override; void Visit(AstStatementVisitor& visitor) override; + std::vector attributes; StructDescription description; }; @@ -222,7 +234,7 @@ namespace Nz::ShaderAst std::string varName; ExpressionPtr initialExpression; - ShaderExpressionType varType; + ExpressionType varType; }; struct NAZARA_SHADER_API DiscardStatement : Statement diff --git a/include/Nazara/Shader/SpirvConstantCache.hpp b/include/Nazara/Shader/SpirvConstantCache.hpp index 7cc829518..5453e9f46 100644 --- a/include/Nazara/Shader/SpirvConstantCache.hpp +++ b/include/Nazara/Shader/SpirvConstantCache.hpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include @@ -172,11 +172,16 @@ namespace Nz SpirvConstantCache& operator=(SpirvConstantCache&& cache) noexcept; static ConstantPtr BuildConstant(const ShaderConstantValue& value); - static TypePtr BuildFunctionType(const ShaderAst::ShaderExpressionType& retType, const std::vector& parameters); - static TypePtr BuildPointerType(const ShaderAst::BasicType& type, SpirvStorageClass storageClass); - static TypePtr BuildPointerType(const ShaderAst::ShaderExpressionType& type, SpirvStorageClass storageClass); - static TypePtr BuildType(const ShaderAst::BasicType& type); - static TypePtr BuildType(const ShaderAst::ShaderExpressionType& type); + static TypePtr BuildFunctionType(const ShaderAst::ExpressionType& retType, const std::vector& parameters); + static TypePtr BuildPointerType(const ShaderAst::PrimitiveType& type, SpirvStorageClass storageClass); + static TypePtr BuildPointerType(const ShaderAst::ExpressionType& type, SpirvStorageClass storageClass); + static TypePtr BuildType(const ShaderAst::ExpressionType& type); + static TypePtr BuildType(const ShaderAst::IdentifierType& type); + static TypePtr BuildType(const ShaderAst::MatrixType& type); + static TypePtr BuildType(const ShaderAst::NoType& type); + static TypePtr BuildType(const ShaderAst::PrimitiveType& type); + static TypePtr BuildType(const ShaderAst::SamplerType& type); + static TypePtr BuildType(const ShaderAst::VectorType& type); private: struct DepRegisterer; diff --git a/include/Nazara/Shader/SpirvWriter.hpp b/include/Nazara/Shader/SpirvWriter.hpp index d0c5f561d..17ac7d023 100644 --- a/include/Nazara/Shader/SpirvWriter.hpp +++ b/include/Nazara/Shader/SpirvWriter.hpp @@ -62,8 +62,8 @@ namespace Nz const ExtVar& GetInputVariable(const std::string& name) const; const ExtVar& GetOutputVariable(const std::string& name) const; const ExtVar& GetUniformVariable(const std::string& name) const; - UInt32 GetPointerTypeId(const ShaderAst::ShaderExpressionType& type, SpirvStorageClass storageClass) const; - UInt32 GetTypeId(const ShaderAst::ShaderExpressionType& type) const; + UInt32 GetPointerTypeId(const ShaderAst::ExpressionType& type, SpirvStorageClass storageClass) const; + UInt32 GetTypeId(const ShaderAst::ExpressionType& type) const; inline bool IsConditionEnabled(const std::string& condition) const; @@ -80,8 +80,8 @@ namespace Nz UInt32 RegisterConstant(const ShaderConstantValue& value); UInt32 RegisterFunctionType(const ShaderAst::DeclareFunctionStatement& functionNode); - UInt32 RegisterPointerType(ShaderAst::ShaderExpressionType type, SpirvStorageClass storageClass); - UInt32 RegisterType(ShaderAst::ShaderExpressionType type); + UInt32 RegisterPointerType(ShaderAst::ExpressionType type, SpirvStorageClass storageClass); + UInt32 RegisterType(ShaderAst::ExpressionType type); void WriteLocalVariable(std::string name, UInt32 resultId); @@ -106,7 +106,7 @@ namespace Nz struct FunctionParameter { std::string name; - ShaderAst::ShaderExpressionType type; + ShaderAst::ExpressionType type; }; struct State; diff --git a/src/Nazara/Shader/GlslWriter.cpp b/src/Nazara/Shader/GlslWriter.cpp index bb9ce8433..8580fd5b0 100644 --- a/src/Nazara/Shader/GlslWriter.cpp +++ b/src/Nazara/Shader/GlslWriter.cpp @@ -20,37 +20,43 @@ namespace Nz namespace { static const char* flipYUniformName = "_NzFlipValue"; + static const char* overridenMain = "_NzMain"; struct AstAdapter : ShaderAst::AstCloner { - void Visit(ShaderAst::AssignExpression& node) override + using AstCloner::Clone; + + std::unique_ptr Clone(ShaderAst::DeclareFunctionStatement& node) override { - if (!flipYPosition) - return AstCloner::Visit(node); + auto clone = AstCloner::Clone(node); + if (clone->name == "main") + clone->name = "_NzMain"; - if (node.left->GetType() != ShaderAst::NodeType::IdentifierExpression) - return AstCloner::Visit(node); - - /* - FIXME: - const auto& identifier = static_cast(*node.left); - if (identifier.var->GetType() != ShaderAst::VariableType::BuiltinVariable) - return ShaderAstCloner::Visit(node); - - const auto& builtinVar = static_cast(*identifier.var); - if (builtinVar.entry != ShaderAst::BuiltinEntry::VertexPosition) - return ShaderAstCloner::Visit(node); - - auto flipVar = ShaderBuilder::Uniform(flipYUniformName, ShaderAst::BasicType::Float1); - - auto oneConstant = ShaderBuilder::Constant(1.f); - auto fixYValue = ShaderBuilder::Cast(oneConstant, ShaderBuilder::Identifier(flipVar), oneConstant, oneConstant); - auto mulFix = ShaderBuilder::Multiply(CloneExpression(node.right), fixYValue); - - PushExpression(ShaderAst::AssignOp::Build(node.op, CloneExpression(node.left), mulFix));*/ + return clone; } - bool flipYPosition = false; + void Visit(ShaderAst::DeclareFunctionStatement& node) + { + if (removedEntryPoints.find(&node) != removedEntryPoints.end()) + { + PushStatement(ShaderBuilder::NoOp()); + return; + } + + AstCloner::Visit(node); + } + + std::unordered_set removedEntryPoints; + }; + + struct Builtin + { + std::string identifier; + ShaderStageTypeFlags stageFlags; + }; + + std::unordered_map builtinMapping = { + { "position", { "gl_Position", ShaderStageType::Vertex } } }; } @@ -59,6 +65,7 @@ namespace Nz { const States* states = nullptr; ShaderAst::AstCache cache; + ShaderAst::DeclareFunctionStatement* entryFunc = nullptr; std::stringstream stream; unsigned int indentLevel = 0; }; @@ -69,19 +76,8 @@ namespace Nz { } - std::string GlslWriter::Generate(ShaderAst::StatementPtr& shader, const States& conditions) + std::string GlslWriter::Generate(ShaderStageType shaderStage, ShaderAst::StatementPtr& shader, const States& conditions) { - /*const ShaderAst* selectedShader = &inputShader; - std::optional modifiedShader; - if (inputShader.GetStage() == ShaderStageType::Vertex && m_environment.flipYPosition) - { - modifiedShader.emplace(inputShader); - - modifiedShader->AddUniform(flipYUniformName, ShaderAst::BasicType::Float1); - - selectedShader = &modifiedShader.value(); - }*/ - State state; m_currentState = &state; CallOnExit onExit([this]() @@ -93,6 +89,27 @@ namespace Nz if (!ShaderAst::ValidateAst(shader, &error, &state.cache)) throw std::runtime_error("Invalid shader AST: " + error); + state.entryFunc = state.cache.entryFunctions[UnderlyingCast(shaderStage)]; + if (!state.entryFunc) + throw std::runtime_error("missing entry point"); + + AstAdapter adapter; + + for (ShaderAst::DeclareFunctionStatement* entryFunc : state.cache.entryFunctions) + { + if (entryFunc != state.entryFunc) + adapter.removedEntryPoints.insert(entryFunc); + } + + ShaderAst::StatementPtr adaptedShader = adapter.Clone(shader); + + state.cache.Clear(); + if (!ShaderAst::ValidateAst(adaptedShader, &error, &state.cache)) + throw std::runtime_error("Internal error:" + error); + + state.entryFunc = state.cache.entryFunctions[UnderlyingCast(shaderStage)]; + assert(state.entryFunc); + unsigned int glslVersion; if (m_environment.glES) { @@ -141,14 +158,14 @@ namespace Nz if (!m_environment.glES && m_environment.extCallback) { // GL_ARB_shading_language_420pack (required for layout(binding = X)) - if (glslVersion < 420 && HasExplicitBinding(shader)) + if (glslVersion < 420 && HasExplicitBinding(adaptedShader)) { if (m_environment.extCallback("GL_ARB_shading_language_420pack")) requiredExtensions.emplace_back("GL_ARB_shading_language_420pack"); } // GL_ARB_separate_shader_objects (required for layout(location = X)) - if (glslVersion < 410 && HasExplicitLocation(shader)) + if (glslVersion < 410 && HasExplicitLocation(adaptedShader)) { if (m_environment.extCallback("GL_ARB_separate_shader_objects")) requiredExtensions.emplace_back("GL_ARB_separate_shader_objects"); @@ -173,7 +190,10 @@ namespace Nz AppendLine(); } - shader->Visit(*this); + adaptedShader->Visit(*this); + + // Append true GLSL entry point + AppendEntryPoint(shaderStage); return state.stream.str(); } @@ -188,7 +208,7 @@ namespace Nz return flipYUniformName; } - void GlslWriter::Append(ShaderAst::ShaderExpressionType type) + void GlslWriter::Append(const ShaderAst::ExpressionType& type) { std::visit([&](auto&& arg) { @@ -206,29 +226,82 @@ namespace Nz } } - void GlslWriter::Append(ShaderAst::BasicType type) + void GlslWriter::Append(const ShaderAst::IdentifierType& identifierType) + { + Append(identifierType.name); + } + + void GlslWriter::Append(const ShaderAst::MatrixType& matrixType) + { + if (matrixType.columnCount == matrixType.rowCount) + { + Append("mat"); + Append(matrixType.columnCount); + } + else + { + Append("mat"); + Append(matrixType.columnCount); + Append("x"); + Append(matrixType.rowCount); + } + } + + void GlslWriter::Append(ShaderAst::PrimitiveType type) { switch (type) { - case ShaderAst::BasicType::Boolean: return Append("bool"); - case ShaderAst::BasicType::Float1: return Append("float"); - case ShaderAst::BasicType::Float2: return Append("vec2"); - case ShaderAst::BasicType::Float3: return Append("vec3"); - case ShaderAst::BasicType::Float4: return Append("vec4"); - case ShaderAst::BasicType::Int1: return Append("int"); - case ShaderAst::BasicType::Int2: return Append("ivec2"); - case ShaderAst::BasicType::Int3: return Append("ivec3"); - case ShaderAst::BasicType::Int4: return Append("ivec4"); - case ShaderAst::BasicType::Mat4x4: return Append("mat4"); - case ShaderAst::BasicType::Sampler2D: return Append("sampler2D"); - case ShaderAst::BasicType::UInt1: return Append("uint"); - case ShaderAst::BasicType::UInt2: return Append("uvec2"); - case ShaderAst::BasicType::UInt3: return Append("uvec3"); - case ShaderAst::BasicType::UInt4: return Append("uvec4"); - case ShaderAst::BasicType::Void: return Append("void"); + case ShaderAst::PrimitiveType::Boolean: return Append("bool"); + case ShaderAst::PrimitiveType::Float32: return Append("float"); + case ShaderAst::PrimitiveType::Int32: return Append("ivec2"); + case ShaderAst::PrimitiveType::UInt32: return Append("uint"); } } + void GlslWriter::Append(const ShaderAst::SamplerType& samplerType) + { + switch (samplerType.sampledType) + { + case ShaderAst::PrimitiveType::Boolean: + case ShaderAst::PrimitiveType::Float32: + break; + + case ShaderAst::PrimitiveType::Int32: Append("i"); break; + case ShaderAst::PrimitiveType::UInt32: Append("u"); break; + } + + Append("sampler"); + + switch (samplerType.dim) + { + case ImageType_1D: Append("1D"); break; + case ImageType_1D_Array: Append("1DArray"); break; + case ImageType_2D: Append("2D"); break; + case ImageType_2D_Array: Append("2DArray"); break; + case ImageType_3D: Append("3D"); break; + case ImageType_Cubemap: Append("Cube"); break; + } + } + + void GlslWriter::Append(const ShaderAst::UniformType& uniformType) + { + /* TODO */ + } + + void GlslWriter::Append(const ShaderAst::VectorType& vecType) + { + switch (vecType.type) + { + case ShaderAst::PrimitiveType::Boolean: Append("b"); break; + case ShaderAst::PrimitiveType::Float32: break; + case ShaderAst::PrimitiveType::Int32: Append("i"); break; + case ShaderAst::PrimitiveType::UInt32: Append("u"); break; + } + + Append("vec"); + Append(vecType.componentCount); + } + void GlslWriter::Append(ShaderAst::MemoryLayout layout) { switch (layout) @@ -239,6 +312,11 @@ namespace Nz } } + void GlslWriter::Append(ShaderAst::NoType) + { + return Append("void"); + } + template void GlslWriter::Append(const T& param) { @@ -246,6 +324,12 @@ namespace Nz m_currentState->stream << param; } + template + void GlslWriter::Append(const T1& firstParam, const T2& secondParam, Args&&... params) + { + Append(firstParam); + Append(secondParam, std::forward(params)...); + } void GlslWriter::AppendCommentSection(const std::string& section) { @@ -256,6 +340,152 @@ namespace Nz AppendLine(); } + void GlslWriter::AppendEntryPoint(ShaderStageType shaderStage) + { + AppendLine(); + AppendLine("// Entry point handling"); + + struct InOutField + { + std::string name; + std::string targetName; + }; + + std::vector inputFields; + const ShaderAst::StructDescription* inputStruct = nullptr; + + auto HandleInOutStructs = [this, shaderStage](const ShaderAst::ExpressionType& expressionType, std::vector& fields, const char* keyword, const char* fromPrefix, const char* targetPrefix) -> const ShaderAst::StructDescription* + { + assert(IsIdentifierType(expressionType)); + + const ShaderAst::AstCache::Identifier* identifier = m_currentState->cache.FindIdentifier(0, std::get(expressionType).name); + assert(identifier); + + assert(std::holds_alternative(identifier->value)); + const auto& s = std::get(identifier->value); + + for (const auto& member : s.members) + { + bool skip = false; + std::optional builtinName; + std::optional attributeLocation; + for (const auto& [attributeType, attributeParam] : member.attributes) + { + if (attributeType == ShaderAst::AttributeType::Builtin) + { + auto it = builtinMapping.find(std::get(attributeParam)); + if (it != builtinMapping.end()) + { + const Builtin& builtin = it->second; + if (!builtin.stageFlags.Test(shaderStage)) + { + skip = true; + break; + } + + builtinName = builtin.identifier; + break; + } + } + else if (attributeType == ShaderAst::AttributeType::Location) + { + attributeLocation = std::get(attributeParam); + break; + } + } + + if (!skip && attributeLocation) + { + Append("layout(location = "); + Append(*attributeLocation); + Append(") "); + Append(keyword); + Append(" "); + Append(member.type); + Append(" "); + Append(targetPrefix); + Append(member.name); + AppendLine(";"); + + fields.push_back({ + fromPrefix + member.name, + targetPrefix + member.name + }); + } + else if (builtinName) + { + fields.push_back({ + fromPrefix + member.name, + *builtinName + }); + } + } + AppendLine(); + + return &s; + }; + + if (!m_currentState->entryFunc->parameters.empty()) + { + assert(m_currentState->entryFunc->parameters.size() == 1); + const auto& parameter = m_currentState->entryFunc->parameters.front(); + + inputStruct = HandleInOutStructs(parameter.type, inputFields, "in", "_nzInput.", "_NzIn_"); + } + + std::vector outputFields; + const ShaderAst::StructDescription* outputStruct = nullptr; + if (!IsNoType(m_currentState->entryFunc->returnType)) + outputStruct = HandleInOutStructs(m_currentState->entryFunc->returnType, outputFields, "out", "_nzOutput.", "_NzOut_"); + + if (shaderStage == ShaderStageType::Vertex && m_environment.flipYPosition) + AppendLine("uniform float ", flipYUniformName, ";"); + + AppendLine("void main()"); + EnterScope(); + { + if (inputStruct) + { + Append(inputStruct->name); + AppendLine(" _nzInput;"); + for (const auto& [name, targetName] : inputFields) + { + AppendLine(name, " = ", targetName, ";"); + } + AppendLine(); + } + + if (outputStruct) + Append(outputStruct->name, " _nzOutput = "); + + Append(m_currentState->entryFunc->name); + + Append("("); + if (m_currentState->entryFunc) + Append("_nzInput"); + Append(");"); + + if (outputStruct) + { + AppendLine(); + + for (const auto& [name, targetName] : outputFields) + { + bool isOutputPosition = (shaderStage == ShaderStageType::Vertex && m_environment.flipYPosition && targetName == "gl_Position"); + + AppendLine(); + + Append(targetName, " = ", name); + if (isOutputPosition) + Append(" * vec4(1.0, ", flipYUniformName, ", 1.0, 1.0)"); + + Append(";"); + } + } + } + LeaveScope(); + } + void GlslWriter::AppendField(std::size_t scopeId, const std::string& structName, const std::string* memberIdentifier, std::size_t remainingMembers) { Append("."); @@ -273,7 +503,7 @@ namespace Nz const auto& member = *memberIt; if (remainingMembers > 1) - AppendField(scopeId, std::get(member.type), memberIdentifier + 1, remainingMembers - 1); + AppendField(scopeId, std::get(member.type).name, memberIdentifier + 1, remainingMembers - 1); } void GlslWriter::AppendLine(const std::string& txt) @@ -283,6 +513,13 @@ namespace Nz m_currentState->stream << txt << '\n' << std::string(m_currentState->indentLevel, '\t'); } + template + void GlslWriter::AppendLine(Args&&... params) + { + (Append(std::forward(params)), ...); + AppendLine(); + } + void GlslWriter::EnterScope() { NazaraAssert(m_currentState, "This function should only be called while processing an AST"); @@ -291,13 +528,17 @@ namespace Nz AppendLine("{"); } - void GlslWriter::LeaveScope() + void GlslWriter::LeaveScope(bool skipLine) { NazaraAssert(m_currentState, "This function should only be called while processing an AST"); m_currentState->indentLevel--; AppendLine(); - AppendLine("}"); + + if (skipLine) + AppendLine("}"); + else + Append("}"); } void GlslWriter::Visit(ShaderAst::ExpressionPtr& expr, bool encloseIfRequired) @@ -317,12 +558,12 @@ namespace Nz { Visit(node.structExpr, true); - const ShaderAst::ShaderExpressionType& exprType = GetExpressionType(*node.structExpr, &m_currentState->cache); - assert(IsStructType(exprType)); + const ShaderAst::ExpressionType& exprType = GetExpressionType(*node.structExpr, &m_currentState->cache); + assert(IsIdentifierType(exprType)); std::size_t scopeId = m_currentState->cache.GetScopeId(&node); - AppendField(scopeId, std::get(exprType), node.memberIdentifiers.data(), node.memberIdentifiers.size()); + AppendField(scopeId, std::get(exprType).name, node.memberIdentifiers.data(), node.memberIdentifiers.size()); } void GlslWriter::Visit(ShaderAst::AssignExpression& node) @@ -336,7 +577,7 @@ namespace Nz break; } - node.left->Visit(*this); + node.right->Visit(*this); } void GlslWriter::Visit(ShaderAst::BranchStatement& node) @@ -455,6 +696,71 @@ namespace Nz }, node.value); } + void GlslWriter::Visit(ShaderAst::DeclareExternalStatement& node) + { + for (const auto& externalVar : node.externalVars) + { + std::optional bindingIndex; + bool isStd140 = false; + for (const auto& [attributeType, attributeParam] : externalVar.attributes) + { + if (attributeType == ShaderAst::AttributeType::Binding) + bindingIndex = std::get(attributeParam); + else if (attributeType == ShaderAst::AttributeType::Layout) + { + if (std::get(attributeParam) == "std140") + isStd140 = true; + } + } + + if (bindingIndex) + { + Append("layout(binding = "); + Append(*bindingIndex); + if (isStd140) + Append(", std140"); + + Append(") uniform "); + + if (IsUniformType(externalVar.type)) + { + Append("_NzBinding_"); + AppendLine(externalVar.name); + + EnterScope(); + { + const ShaderAst::AstCache::Identifier* identifier = m_currentState->cache.FindIdentifier(0, std::get(externalVar.type).containedType.name); + assert(identifier); + + assert(std::holds_alternative(identifier->value)); + const auto& s = std::get(identifier->value); + + bool first = true; + for (const auto& [name, attribute, type] : s.members) + { + if (!first) + AppendLine(); + + first = false; + + Append(type); + Append(" "); + Append(name); + Append(";"); + } + } + LeaveScope(false); + } + else + Append(externalVar.type); + + Append(" "); + Append(externalVar.name); + AppendLine(";"); + } + } + } + void GlslWriter::Visit(ShaderAst::DeclareFunctionStatement& node) { NazaraAssert(m_currentState, "This function should only be called while processing an AST"); @@ -475,15 +781,36 @@ namespace Nz EnterScope(); { - AstAdapter adapter; - adapter.flipYPosition = m_environment.flipYPosition; - for (auto& statement : node.statements) - adapter.Clone(statement)->Visit(*this); + statement->Visit(*this); } LeaveScope(); } + void GlslWriter::Visit(ShaderAst::DeclareStructStatement& node) + { + Append("struct "); + AppendLine(node.description.name); + EnterScope(); + { + bool first = true; + for (const auto& [name, attribute, type] : node.description.members) + { + if (!first) + AppendLine(); + + first = false; + + Append(type); + Append(" "); + Append(name); + Append(";"); + } + } + LeaveScope(false); + AppendLine(";"); + } + void GlslWriter::Visit(ShaderAst::DeclareVariableStatement& node) { Append(node.varType); @@ -506,7 +833,7 @@ namespace Nz void GlslWriter::Visit(ShaderAst::ExpressionStatement& node) { node.expression->Visit(*this); - Append(";"); + AppendLine(";"); } void GlslWriter::Visit(ShaderAst::IdentifierExpression& node) @@ -525,6 +852,10 @@ namespace Nz case ShaderAst::IntrinsicType::DotProduct: Append("dot"); break; + + case ShaderAst::IntrinsicType::SampleTexture: + Append("texture"); + break; } Append("("); @@ -624,4 +955,5 @@ namespace Nz return false; } + } diff --git a/src/Nazara/Shader/ShaderAstCloner.cpp b/src/Nazara/Shader/ShaderAstCloner.cpp index ea7ed0276..92eae1621 100644 --- a/src/Nazara/Shader/ShaderAstCloner.cpp +++ b/src/Nazara/Shader/ShaderAstCloner.cpp @@ -42,6 +42,21 @@ namespace Nz::ShaderAst return PopStatement(); } + std::unique_ptr AstCloner::Clone(DeclareFunctionStatement& node) + { + auto clone = std::make_unique(); + clone->attributes = node.attributes; + clone->name = node.name; + clone->parameters = node.parameters; + clone->returnType = node.returnType; + + clone->statements.reserve(node.statements.size()); + for (auto& statement : node.statements) + clone->statements.push_back(CloneStatement(statement)); + + return clone; + } + void AstCloner::Visit(AccessMemberExpression& node) { auto clone = std::make_unique(); @@ -162,21 +177,20 @@ namespace Nz::ShaderAst PushStatement(std::move(clone)); } - void AstCloner::Visit(DeclareFunctionStatement& node) + void AstCloner::Visit(DeclareExternalStatement& node) { - auto clone = std::make_unique(); + auto clone = std::make_unique(); clone->attributes = node.attributes; - clone->name = node.name; - clone->parameters = node.parameters; - clone->returnType = node.returnType; - - clone->statements.reserve(node.statements.size()); - for (auto& statement : node.statements) - clone->statements.push_back(CloneStatement(statement)); + clone->externalVars = node.externalVars; PushStatement(std::move(clone)); } + void AstCloner::Visit(DeclareFunctionStatement& node) + { + PushStatement(Clone(node)); + } + void AstCloner::Visit(DeclareStructStatement& node) { auto clone = std::make_unique(); diff --git a/src/Nazara/Shader/ShaderAstExpressionType.cpp b/src/Nazara/Shader/ShaderAstExpressionType.cpp index 71f831f69..bd87822f7 100644 --- a/src/Nazara/Shader/ShaderAstExpressionType.cpp +++ b/src/Nazara/Shader/ShaderAstExpressionType.cpp @@ -9,16 +9,16 @@ namespace Nz::ShaderAst { - ShaderExpressionType ExpressionTypeVisitor::GetExpressionType(Expression& expression, AstCache* cache = nullptr) + ExpressionType ExpressionTypeVisitor::GetExpressionType(Expression& expression, AstCache* cache) { m_cache = cache; - ShaderExpressionType type = GetExpressionTypeInternal(expression); + ExpressionType type = GetExpressionTypeInternal(expression); m_cache = nullptr; return type; } - ShaderExpressionType ExpressionTypeVisitor::GetExpressionTypeInternal(Expression& expression) + ExpressionType ExpressionTypeVisitor::GetExpressionTypeInternal(Expression& expression) { m_lastExpressionType.reset(); @@ -28,6 +28,33 @@ namespace Nz::ShaderAst return std::move(*m_lastExpressionType); } + ExpressionType ExpressionTypeVisitor::ResolveAlias(Expression& expression, ExpressionType expressionType) + { + if (IsIdentifierType(expressionType)) + { + auto scopeIt = m_cache->scopeIdByNode.find(&expression); + if (scopeIt == m_cache->scopeIdByNode.end()) + throw std::runtime_error("internal error"); + + const AstCache::Identifier* identifier = m_cache->FindIdentifier(scopeIt->second, std::get(expressionType).name); + if (identifier && std::holds_alternative(identifier->value)) + { + const AstCache::Alias& alias = std::get(identifier->value); + return std::visit([&](auto&& arg) -> ShaderAst::ExpressionType + { + using T = std::decay_t; + + if constexpr (std::is_same_v) + return arg; + else + static_assert(AlwaysFalse::value, "non-exhaustive visitor"); + }, alias.value); + } + } + + return expressionType; + } + void ExpressionTypeVisitor::Visit(Expression& expression) { if (m_cache) @@ -51,6 +78,16 @@ namespace Nz::ShaderAst void ExpressionTypeVisitor::Visit(AccessMemberExpression& node) { + auto scopeIt = m_cache->scopeIdByNode.find(&node); + if (scopeIt == m_cache->scopeIdByNode.end()) + throw std::runtime_error("internal error"); + + ExpressionType expressionType = ResolveAlias(node, GetExpressionTypeInternal(*node.structExpr)); + if (!IsIdentifierType(expressionType)) + throw std::runtime_error("internal error"); + + const AstCache::Identifier* identifier = m_cache->FindIdentifier(scopeIt->second, std::get(expressionType).name); + throw std::runtime_error("unhandled accessmember expression"); } @@ -70,38 +107,35 @@ namespace Nz::ShaderAst case BinaryType::Divide: case BinaryType::Multiply: { - ShaderExpressionType leftExprType = GetExpressionTypeInternal(*node.left); - assert(IsBasicType(leftExprType)); + ExpressionType leftExprType = ResolveAlias(node, GetExpressionTypeInternal(*node.left)); + ExpressionType rightExprType = ResolveAlias(node, GetExpressionTypeInternal(*node.right)); - ShaderExpressionType rightExprType = GetExpressionTypeInternal(*node.right); - assert(IsBasicType(rightExprType)); - - switch (std::get(leftExprType)) + if (IsPrimitiveType(leftExprType)) { - case BasicType::Boolean: - case BasicType::Float2: - case BasicType::Float3: - case BasicType::Float4: - case BasicType::Int2: - case BasicType::Int3: - case BasicType::Int4: - case BasicType::UInt2: - case BasicType::UInt3: - case BasicType::UInt4: - m_lastExpressionType = std::move(leftExprType); - break; + switch (std::get(leftExprType)) + { + case PrimitiveType::Boolean: + m_lastExpressionType = std::move(leftExprType); + break; - case BasicType::Float1: - case BasicType::Int1: - case BasicType::Mat4x4: - case BasicType::UInt1: - m_lastExpressionType = std::move(rightExprType); - break; - - case BasicType::Sampler2D: - case BasicType::Void: - break; + case PrimitiveType::Float32: + case PrimitiveType::Int32: + case PrimitiveType::UInt32: + m_lastExpressionType = std::move(rightExprType); + break; + } } + else if (IsMatrixType(leftExprType)) + { + if (IsVectorType(rightExprType)) + m_lastExpressionType = std::move(rightExprType); + else + m_lastExpressionType = std::move(leftExprType); + } + else if (IsVectorType(leftExprType)) + m_lastExpressionType = std::move(leftExprType); + else + throw std::runtime_error("validation failure"); break; } @@ -112,7 +146,7 @@ namespace Nz::ShaderAst case BinaryType::CompLe: case BinaryType::CompLt: case BinaryType::CompNe: - m_lastExpressionType = BasicType::Boolean; + m_lastExpressionType = PrimitiveType::Boolean; break; } } @@ -124,38 +158,38 @@ namespace Nz::ShaderAst void ExpressionTypeVisitor::Visit(ConditionalExpression& node) { - ShaderExpressionType leftExprType = GetExpressionTypeInternal(*node.truePath); - assert(leftExprType == GetExpressionTypeInternal(*node.falsePath)); + ExpressionType leftExprType = ResolveAlias(node, GetExpressionTypeInternal(*node.truePath)); + assert(leftExprType == ResolveAlias(node, GetExpressionTypeInternal(*node.falsePath))); m_lastExpressionType = std::move(leftExprType); } void ExpressionTypeVisitor::Visit(ConstantExpression& node) { - m_lastExpressionType = std::visit([&](auto&& arg) + m_lastExpressionType = std::visit([&](auto&& arg) -> ShaderAst::ExpressionType { using T = std::decay_t; if constexpr (std::is_same_v) - return BasicType::Boolean; + return PrimitiveType::Boolean; else if constexpr (std::is_same_v) - return BasicType::Float1; + return PrimitiveType::Float32; else if constexpr (std::is_same_v) - return BasicType::Int1; + return PrimitiveType::Int32; else if constexpr (std::is_same_v) - return BasicType::Int1; + return PrimitiveType::UInt32; else if constexpr (std::is_same_v) - return BasicType::Float2; + return VectorType{ 2, PrimitiveType::Float32 }; else if constexpr (std::is_same_v) - return BasicType::Float3; + return VectorType{ 3, PrimitiveType::Float32 }; else if constexpr (std::is_same_v) - return BasicType::Float4; + return VectorType{ 4, PrimitiveType::Float32 }; else if constexpr (std::is_same_v) - return BasicType::Int2; + return VectorType{ 2, PrimitiveType::Int32 }; else if constexpr (std::is_same_v) - return BasicType::Int3; + return VectorType{ 3, PrimitiveType::Int32 }; else if constexpr (std::is_same_v) - return BasicType::Int4; + return VectorType{ 4, PrimitiveType::Int32 }; else static_assert(AlwaysFalse::value, "non-exhaustive visitor"); }, node.value); @@ -173,7 +207,7 @@ namespace Nz::ShaderAst if (!identifier || !std::holds_alternative(identifier->value)) throw std::runtime_error("internal error"); - m_lastExpressionType = std::get(identifier->value).type; + m_lastExpressionType = ResolveAlias(node, std::get(identifier->value).type); } void ExpressionTypeVisitor::Visit(IntrinsicExpression& node) @@ -185,16 +219,40 @@ namespace Nz::ShaderAst break; case IntrinsicType::DotProduct: - m_lastExpressionType = BasicType::Float1; + m_lastExpressionType = PrimitiveType::Float32; break; + + case IntrinsicType::SampleTexture: + { + if (node.parameters.empty()) + throw std::runtime_error("validation failure"); + + ExpressionType firstParamType = ResolveAlias(node, GetExpressionTypeInternal(*node.parameters.front())); + + if (!IsSamplerType(firstParamType)) + throw std::runtime_error("validation failure"); + + const auto& sampler = std::get(firstParamType); + + m_lastExpressionType = VectorType{ + 4, + sampler.sampledType + }; + + break; + } } } void ExpressionTypeVisitor::Visit(SwizzleExpression& node) { - ShaderExpressionType exprType = GetExpressionTypeInternal(*node.expression); - assert(IsBasicType(exprType)); + ExpressionType exprType = GetExpressionTypeInternal(*node.expression); - m_lastExpressionType = static_cast(UnderlyingCast(GetComponentType(std::get(exprType))) + node.componentCount - 1); + if (IsMatrixType(exprType)) + m_lastExpressionType = std::get(exprType).type; + else if (IsVectorType(exprType)) + m_lastExpressionType = std::get(exprType).type; + else + throw std::runtime_error("validation failure"); } } diff --git a/src/Nazara/Shader/ShaderAstOptimizer.cpp b/src/Nazara/Shader/ShaderAstOptimizer.cpp index 33c8d3f76..c83ae1412 100644 --- a/src/Nazara/Shader/ShaderAstOptimizer.cpp +++ b/src/Nazara/Shader/ShaderAstOptimizer.cpp @@ -453,8 +453,8 @@ namespace Nz::ShaderAst { auto& constant = static_cast(*cond); - assert(IsBasicType(GetExpressionType(constant))); - assert(std::get(GetExpressionType(constant)) == BasicType::Boolean); + assert(IsPrimitiveType(GetExpressionType(constant))); + assert(std::get(GetExpressionType(constant)) == PrimitiveType::Boolean); bool cValue = std::get(constant.value); if (!cValue) diff --git a/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp b/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp index c0ef0d920..e0a87ad51 100644 --- a/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp +++ b/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp @@ -79,6 +79,11 @@ namespace Nz::ShaderAst node.statement->Visit(*this); } + void AstRecursiveVisitor::Visit(DeclareExternalStatement& node) + { + /* Nothing to do */ + } + void AstRecursiveVisitor::Visit(DeclareFunctionStatement& node) { for (auto& statement : node.statements) diff --git a/src/Nazara/Shader/ShaderAstSerializer.cpp b/src/Nazara/Shader/ShaderAstSerializer.cpp index b078a53f8..20b0b4b63 100644 --- a/src/Nazara/Shader/ShaderAstSerializer.cpp +++ b/src/Nazara/Shader/ShaderAstSerializer.cpp @@ -58,7 +58,7 @@ namespace Nz::ShaderAst void AstSerializerBase::Serialize(CastExpression& node) { - Enum(node.targetType); + Type(node.targetType); for (auto& expr : node.expressions) Node(expr); } @@ -152,17 +152,25 @@ namespace Nz::ShaderAst Node(node.statement); } + void AstSerializerBase::Serialize(DeclareExternalStatement& node) + { + Attributes(node.attributes); + + Container(node.externalVars); + for (auto& extVar : node.externalVars) + { + Attributes(extVar.attributes); + Value(extVar.name); + Type(extVar.type); + } + } + void AstSerializerBase::Serialize(DeclareFunctionStatement& node) { Value(node.name); Type(node.returnType); - Container(node.attributes); - for (auto& attribute : node.attributes) - { - Enum(attribute.type); - Value(attribute.args); - } + Attributes(node.attributes); Container(node.parameters); for (auto& parameter : node.parameters) @@ -223,6 +231,78 @@ namespace Nz::ShaderAst m_stream.FlushBits(); } + + void AstSerializerBase::Attributes(std::vector& attributes) + { + Container(attributes); + for (auto& attribute : attributes) + { + Enum(attribute.type); + + if (IsWriting()) + { + std::visit([&](auto&& arg) + { + using T = std::decay_t; + + if constexpr (std::is_same_v) + { + UInt8 typeId = 0; + Value(typeId); + } + else if constexpr (std::is_same_v) + { + UInt8 typeId = 1; + UInt64 v = UInt64(arg); + Value(typeId); + Value(v); + } + else if constexpr (std::is_same_v) + { + UInt8 typeId = 2; + Value(typeId); + Value(arg); + } + else + static_assert(AlwaysFalse::value, "non-exhaustive visitor"); + + }, attribute.args); + } + else + { + UInt8 typeId; + Value(typeId); + + switch (typeId) + { + case 0: + attribute.args.emplace(); + break; + + case 1: + { + UInt64 arg; + Value(arg); + + attribute.args = static_cast(arg); + break; + } + + case 2: + { + std::string arg; + Value(arg); + + attribute.args = std::move(arg); + break; + } + + default: + throw std::runtime_error("invalid attribute type id"); + } + } + } + } bool ShaderAstSerializer::IsWriting() const { @@ -253,20 +333,47 @@ namespace Nz::ShaderAst } } - void ShaderAstSerializer::Type(ShaderExpressionType& type) + void ShaderAstSerializer::Type(ExpressionType& type) { std::visit([&](auto&& arg) { using T = std::decay_t; - if constexpr (std::is_same_v) - { + + if constexpr (std::is_same_v) m_stream << UInt8(0); - m_stream << UInt32(arg); - } - else if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) { m_stream << UInt8(1); - m_stream << arg; + m_stream << UInt32(arg); + } + else if constexpr (std::is_same_v) + { + m_stream << UInt8(2); + m_stream << arg.name; + } + else if constexpr (std::is_same_v) + { + m_stream << UInt8(3); + m_stream << UInt32(arg.columnCount); + m_stream << UInt32(arg.rowCount); + m_stream << UInt32(arg.type); + } + else if constexpr (std::is_same_v) + { + m_stream << UInt8(4); + m_stream << UInt32(arg.dim); + m_stream << UInt32(arg.sampledType); + } + else if constexpr (std::is_same_v) + { + m_stream << UInt8(5); + m_stream << arg.containedType.name; + } + else if constexpr (std::is_same_v) + { + m_stream << UInt8(6); + m_stream << UInt32(arg.componentCount); + m_stream << UInt32(arg.type); } else static_assert(AlwaysFalse::value, "non-exhaustive visitor"); @@ -421,28 +528,123 @@ namespace Nz::ShaderAst } } - void ShaderAstUnserializer::Type(ShaderExpressionType& type) + void ShaderAstUnserializer::Type(ExpressionType& type) { UInt8 typeIndex; Value(typeIndex); switch (typeIndex) { - case 0: //< Primitive + /* + if constexpr (std::is_same_v) + m_stream << UInt8(0); + else if constexpr (std::is_same_v) { - BasicType exprType; - Enum(exprType); + m_stream << UInt8(1); + m_stream << UInt32(arg); + } + else if constexpr (std::is_same_v) + { + m_stream << UInt8(2); + m_stream << arg.name; + } + else if constexpr (std::is_same_v) + { + m_stream << UInt8(3); + m_stream << UInt32(arg.columnCount); + m_stream << UInt32(arg.rowCount); + m_stream << UInt32(arg.type); + } + else if constexpr (std::is_same_v) + { + m_stream << UInt8(4); + m_stream << UInt32(arg.dim); + m_stream << UInt32(arg.sampledType); + } + else if constexpr (std::is_same_v) + { + m_stream << UInt8(5); + m_stream << UInt32(arg.componentCount); + m_stream << UInt32(arg.type); + } + */ - type = exprType; + case 0: //< NoType + type = NoType{}; + break; + + case 1: //< PrimitiveType + { + PrimitiveType primitiveType; + Enum(primitiveType); + + type = primitiveType; break; } - case 1: //< Struct (name) + case 2: //< Identifier { - std::string structName; - Value(structName); + std::string identifier; + Value(identifier); - type = std::move(structName); + type = IdentifierType{ std::move(identifier) }; + break; + } + + case 3: //< MatrixType + { + UInt32 columnCount, rowCount; + PrimitiveType primitiveType; + Value(columnCount); + Value(rowCount); + Enum(primitiveType); + + type = MatrixType { + columnCount, + rowCount, + primitiveType + }; + break; + } + + case 4: //< SamplerType + { + ImageType dim; + PrimitiveType sampledType; + Enum(dim); + Enum(sampledType); + + type = SamplerType { + dim, + sampledType + }; + break; + } + + case 5: //< UniformType + { + std::string containedType; + Value(containedType); + + type = UniformType { + IdentifierType { + containedType + } + }; + break; + } + + case 6: //< VectorType + { + UInt32 componentCount; + PrimitiveType componentType; + Value(componentCount); + Enum(componentType); + + type = VectorType{ + componentCount, + componentType + }; break; } diff --git a/src/Nazara/Shader/ShaderAstValidator.cpp b/src/Nazara/Shader/ShaderAstValidator.cpp index 2c41cf999..8293870e9 100644 --- a/src/Nazara/Shader/ShaderAstValidator.cpp +++ b/src/Nazara/Shader/ShaderAstValidator.cpp @@ -18,7 +18,6 @@ namespace Nz::ShaderAst { "frag", ShaderStageType::Fragment }, { "vert", ShaderStageType::Vertex }, }; - } struct AstError @@ -30,6 +29,8 @@ namespace Nz::ShaderAst { //const ShaderAst::Function* currentFunction; std::optional activeScopeId; + std::unordered_set declaredExternalVar; + std::unordered_set usedBindingIndexes;; AstCache* cache; }; @@ -81,31 +82,31 @@ namespace Nz::ShaderAst return TypeMustMatch(GetExpressionType(*left, m_context->cache), GetExpressionType(*right, m_context->cache)); } - void AstValidator::TypeMustMatch(const ShaderExpressionType& left, const ShaderExpressionType& right) + void AstValidator::TypeMustMatch(const ExpressionType& left, const ExpressionType& right) { if (left != right) throw AstError{ "Left expression type must match right expression type" }; } - ShaderExpressionType AstValidator::CheckField(const std::string& structName, const std::string* memberIdentifier, std::size_t remainingMembers) + ExpressionType AstValidator::CheckField(const std::string& structName, const std::string* memberIdentifier, std::size_t remainingMembers) { const AstCache::Identifier* identifier = m_context->cache->FindIdentifier(*m_context->activeScopeId, structName); if (!identifier) throw AstError{ "unknown identifier " + structName }; - if (std::holds_alternative(identifier->value)) + if (!std::holds_alternative(identifier->value)) throw AstError{ "identifier is not a struct" }; const StructDescription& s = std::get(identifier->value); - auto memberIt = std::find_if(s.members.begin(), s.members.begin(), [&](const auto& field) { return field.name == memberIdentifier[0]; }); + auto memberIt = std::find_if(s.members.begin(), s.members.end(), [&](const auto& field) { return field.name == memberIdentifier[0]; }); if (memberIt == s.members.end()) throw AstError{ "unknown field " + memberIdentifier[0]}; const auto& member = *memberIt; if (remainingMembers > 1) - return CheckField(std::get(member.type), memberIdentifier + 1, remainingMembers - 1); + return CheckField(std::get(member.type).name, memberIdentifier + 1, remainingMembers - 1); else return member.type; } @@ -130,7 +131,7 @@ namespace Nz::ShaderAst m_context->activeScopeId = previousScope.parentScopeIndex; } - void AstValidator::RegisterExpressionType(Expression& node, ShaderExpressionType expressionType) + void AstValidator::RegisterExpressionType(Expression& node, ExpressionType expressionType) { m_context->cache->nodeExpressionType[&node] = std::move(expressionType); } @@ -145,11 +146,14 @@ namespace Nz::ShaderAst { RegisterScope(node); - ShaderExpressionType exprType = GetExpressionType(MandatoryExpr(node.structExpr), m_context->cache); - if (!IsStructType(exprType)) + // Register expressions types + AstRecursiveVisitor::Visit(node); + + ExpressionType exprType = GetExpressionType(MandatoryExpr(node.structExpr), m_context->cache); + if (!IsIdentifierType(exprType)) throw AstError{ "expression is not a structure" }; - const std::string& structName = std::get(exprType); + const std::string& structName = std::get(exprType).name; RegisterExpressionType(node, CheckField(structName, node.memberIdentifiers.data(), node.memberIdentifiers.size())); } @@ -160,12 +164,14 @@ namespace Nz::ShaderAst MandatoryExpr(node.left); MandatoryExpr(node.right); + + // Register expressions types + AstRecursiveVisitor::Visit(node); + TypeMustMatch(node.left, node.right); if (GetExpressionCategory(*node.left) != ExpressionCategory::LValue) throw AstError { "Assignation is only possible with a l-value" }; - - AstRecursiveVisitor::Visit(node); } void AstValidator::Visit(BinaryExpression& node) @@ -175,80 +181,121 @@ namespace Nz::ShaderAst // Register expression type AstRecursiveVisitor::Visit(node); - ShaderExpressionType leftExprType = GetExpressionType(MandatoryExpr(node.left), m_context->cache); - if (!IsBasicType(leftExprType)) + ExpressionType leftExprType = GetExpressionType(MandatoryExpr(node.left), m_context->cache); + if (!IsPrimitiveType(leftExprType) && !IsMatrixType(leftExprType) && !IsVectorType(leftExprType)) throw AstError{ "left expression type does not support binary operation" }; - ShaderExpressionType rightExprType = GetExpressionType(MandatoryExpr(node.right), m_context->cache); - if (!IsBasicType(rightExprType)) + ExpressionType rightExprType = GetExpressionType(MandatoryExpr(node.right), m_context->cache); + if (!IsPrimitiveType(rightExprType) && !IsMatrixType(rightExprType) && !IsVectorType(rightExprType)) throw AstError{ "right expression type does not support binary operation" }; - BasicType leftType = std::get(leftExprType); - BasicType rightType = std::get(rightExprType); - - switch (node.op) + if (IsPrimitiveType(leftExprType)) { - case BinaryType::CompGe: - case BinaryType::CompGt: - case BinaryType::CompLe: - case BinaryType::CompLt: - if (leftType == BasicType::Boolean) - throw AstError{ "this operation is not supported for booleans" }; - - [[fallthrough]]; - case BinaryType::Add: - case BinaryType::CompEq: - case BinaryType::CompNe: - case BinaryType::Subtract: - TypeMustMatch(node.left, node.right); - break; - - case BinaryType::Multiply: - case BinaryType::Divide: + PrimitiveType leftType = std::get(leftExprType); + switch (node.op) { - switch (leftType) + case BinaryType::CompGe: + case BinaryType::CompGt: + case BinaryType::CompLe: + case BinaryType::CompLt: + if (leftType == PrimitiveType::Boolean) + throw AstError{ "this operation is not supported for booleans" }; + + [[fallthrough]]; + case BinaryType::Add: + case BinaryType::CompEq: + case BinaryType::CompNe: + case BinaryType::Subtract: + TypeMustMatch(node.left, node.right); + break; + + case BinaryType::Multiply: + case BinaryType::Divide: { - case BasicType::Float1: - case BasicType::Int1: + switch (leftType) { - if (GetComponentType(rightType) != leftType) - throw AstError{ "Left expression type is not compatible with right expression type" }; - - break; - } - - case BasicType::Float2: - case BasicType::Float3: - case BasicType::Float4: - case BasicType::Int2: - case BasicType::Int3: - case BasicType::Int4: - { - if (leftType != rightType && rightType != GetComponentType(leftType)) - throw AstError{ "Left expression type is not compatible with right expression type" }; - - break; - } - - case BasicType::Mat4x4: - { - switch (rightType) + case PrimitiveType::Float32: + case PrimitiveType::Int32: + case PrimitiveType::UInt32: { - case BasicType::Float1: - case BasicType::Float4: - case BasicType::Mat4x4: - break; + if (IsMatrixType(rightExprType)) + TypeMustMatch(leftType, std::get(rightExprType).type); + else if (IsVectorType(rightExprType)) + TypeMustMatch(leftType, std::get(rightExprType).type); + else + throw AstError{ "incompatible types" }; - default: - TypeMustMatch(node.left, node.right); + break; } - break; - } + case PrimitiveType::Boolean: + throw AstError{ "this operation is not supported for booleans" }; - default: - TypeMustMatch(node.left, node.right); - break; + default: + throw AstError{ "incompatible types" }; + } + } + } + } + else if (IsMatrixType(leftExprType)) + { + const MatrixType& leftType = std::get(leftExprType); + switch (node.op) + { + case BinaryType::CompGe: + case BinaryType::CompGt: + case BinaryType::CompLe: + case BinaryType::CompLt: + case BinaryType::CompEq: + case BinaryType::CompNe: + case BinaryType::Add: + case BinaryType::Subtract: + TypeMustMatch(node.left, node.right); + break; + + case BinaryType::Multiply: + case BinaryType::Divide: + { + if (IsMatrixType(rightExprType)) + TypeMustMatch(leftExprType, rightExprType); + else if (IsPrimitiveType(rightExprType)) + TypeMustMatch(leftType.type, rightExprType); + else if (IsVectorType(rightExprType)) + { + const VectorType& rightType = std::get(rightExprType); + TypeMustMatch(leftType.type, rightType.type); + + if (leftType.columnCount != rightType.componentCount) + throw AstError{ "incompatible types" }; + } + else + throw AstError{ "incompatible types" }; + } + } + } + else if (IsVectorType(leftExprType)) + { + const MatrixType& leftType = std::get(leftExprType); + switch (node.op) + { + case BinaryType::CompGe: + case BinaryType::CompGt: + case BinaryType::CompLe: + case BinaryType::CompLt: + case BinaryType::CompEq: + case BinaryType::CompNe: + case BinaryType::Add: + case BinaryType::Subtract: + TypeMustMatch(node.left, node.right); + break; + + case BinaryType::Multiply: + case BinaryType::Divide: + { + if (IsPrimitiveType(rightExprType)) + TypeMustMatch(leftType.type, rightExprType); + else + throw AstError{ "incompatible types" }; } } } @@ -258,24 +305,35 @@ namespace Nz::ShaderAst { RegisterScope(node); + AstRecursiveVisitor::Visit(node); + + auto GetComponentCount = [](const ExpressionType& exprType) -> unsigned int + { + if (IsPrimitiveType(exprType)) + return 1; + else if (IsVectorType(exprType)) + return std::get(exprType).componentCount; + else + throw AstError{ "wut" }; + }; + unsigned int componentCount = 0; unsigned int requiredComponents = GetComponentCount(node.targetType); + for (auto& exprPtr : node.expressions) { if (!exprPtr) break; - ShaderExpressionType exprType = GetExpressionType(*exprPtr, m_context->cache); - if (!IsBasicType(exprType)) + ExpressionType exprType = GetExpressionType(*exprPtr, m_context->cache); + if (!IsPrimitiveType(exprType) && !IsVectorType(exprType)) throw AstError{ "incompatible type" }; - componentCount += GetComponentCount(std::get(exprType)); + componentCount += GetComponentCount(exprType); } if (componentCount != requiredComponents) throw AstError{ "component count doesn't match required component count" }; - - AstRecursiveVisitor::Visit(node); } void AstValidator::Visit(ConditionalExpression& node) @@ -313,34 +371,51 @@ namespace Nz::ShaderAst { RegisterScope(node); + AstRecursiveVisitor::Visit(node); + switch (node.intrinsic) { case IntrinsicType::CrossProduct: case IntrinsicType::DotProduct: { if (node.parameters.size() != 2) - throw AstError { "Expected 2 parameters" }; + throw AstError { "Expected two parameters" }; for (auto& param : node.parameters) MandatoryExpr(param); - ShaderExpressionType type = GetExpressionType(*node.parameters.front(), m_context->cache); + ExpressionType type = GetExpressionType(*node.parameters.front(), m_context->cache); for (std::size_t i = 1; i < node.parameters.size(); ++i) { - if (type != GetExpressionType(MandatoryExpr(node.parameters[i])), m_context->cache) + if (type != GetExpressionType(MandatoryExpr(node.parameters[i]), m_context->cache)) throw AstError{ "All type must match" }; } break; } + + case IntrinsicType::SampleTexture: + { + if (node.parameters.size() != 2) + throw AstError{ "Expected two parameters" }; + + for (auto& param : node.parameters) + MandatoryExpr(param); + + if (!IsSamplerType(GetExpressionType(*node.parameters[0], m_context->cache))) + throw AstError{ "First parameter must be a sampler" }; + + if (!IsVectorType(GetExpressionType(*node.parameters[1], m_context->cache))) + throw AstError{ "First parameter must be a vector" }; + } } switch (node.intrinsic) { case IntrinsicType::CrossProduct: { - if (GetExpressionType(*node.parameters[0]) != ShaderExpressionType{ BasicType::Float3 }, m_context->cache) - throw AstError{ "CrossProduct only works with Float3 expressions" }; + if (GetExpressionType(*node.parameters[0]) != ExpressionType{ VectorType{ 3, PrimitiveType::Float32 } }) + throw AstError{ "CrossProduct only works with vec3 expressions" }; break; } @@ -348,8 +423,6 @@ namespace Nz::ShaderAst case IntrinsicType::DotProduct: break; } - - AstRecursiveVisitor::Visit(node); } void AstValidator::Visit(SwizzleExpression& node) @@ -359,26 +432,10 @@ namespace Nz::ShaderAst if (node.componentCount > 4) throw AstError{ "Cannot swizzle more than four elements" }; - ShaderExpressionType exprType = GetExpressionType(MandatoryExpr(node.expression), m_context->cache); - if (!IsBasicType(exprType)) + ExpressionType exprType = GetExpressionType(MandatoryExpr(node.expression), m_context->cache); + if (!IsPrimitiveType(exprType) && !IsVectorType(exprType)) throw AstError{ "Cannot swizzle this type" }; - switch (std::get(exprType)) - { - case BasicType::Float1: - case BasicType::Float2: - case BasicType::Float3: - case BasicType::Float4: - case BasicType::Int1: - case BasicType::Int2: - case BasicType::Int3: - case BasicType::Int4: - break; - - default: - throw AstError{ "Cannot swizzle this type" }; - } - AstRecursiveVisitor::Visit(node); } @@ -388,8 +445,8 @@ namespace Nz::ShaderAst for (auto& condStatement : node.condStatements) { - ShaderExpressionType condType = GetExpressionType(MandatoryExpr(condStatement.condition), m_context->cache); - if (!IsBasicType(condType) || std::get(condType) != BasicType::Boolean) + ExpressionType condType = GetExpressionType(MandatoryExpr(condStatement.condition), m_context->cache); + if (!IsPrimitiveType(condType) || std::get(condType) != PrimitiveType::Boolean) throw AstError{ "if expression must resolve to boolean type" }; MandatoryStatement(condStatement.statement); @@ -409,6 +466,78 @@ namespace Nz::ShaderAst // throw AstError{ "condition not found" }; } + void AstValidator::Visit(DeclareExternalStatement& node) + { + RegisterScope(node); + auto& scope = m_context->cache->scopes[*m_context->activeScopeId]; + + for (const auto& [attributeType, arg] : node.attributes) + { + switch (attributeType) + { + default: + throw AstError{ "unhandled attribute for external block" }; + } + } + + for (const auto& extVar : node.externalVars) + { + bool hasBinding = false; + bool hasLayout = false; + for (const auto& [attributeType, arg] : extVar.attributes) + { + switch (attributeType) + { + case AttributeType::Binding: + { + if (hasBinding) + throw AstError{ "attribute binding must be present once" }; + + if (!std::holds_alternative(arg)) + throw AstError{ "attribute binding requires a string parameter" }; + + long long bindingIndex = std::get(arg); + if (m_context->usedBindingIndexes.find(bindingIndex) != m_context->usedBindingIndexes.end()) + throw AstError{ "Binding #" + std::to_string(bindingIndex) + " is already in use" }; + + m_context->usedBindingIndexes.insert(bindingIndex); + break; + } + + case AttributeType::Layout: + { + if (hasLayout) + throw AstError{ "attribute layout must be present once" }; + + if (!std::holds_alternative(arg)) + throw AstError{ "attribute layout requires a string parameter" }; + + if (std::get(arg) != "std140") + throw AstError{ "unknow layout type" }; + + hasLayout = true; + break; + } + + default: + throw AstError{ "unhandled attribute for external variable" }; + } + } + + if (m_context->declaredExternalVar.find(extVar.name) != m_context->declaredExternalVar.end()) + throw AstError{ "External variable " + extVar.name + " is already declared" }; + + m_context->declaredExternalVar.insert(extVar.name); + + ExpressionType subType = extVar.type; + if (IsUniformType(subType)) + subType = IdentifierType{ std::get(subType).containedType }; + + auto& identifier = scope.identifiers.emplace_back(); + identifier = AstCache::Identifier{ extVar.name, AstCache::Variable { std::move(subType) } }; + } + } + void AstValidator::Visit(DeclareFunctionStatement& node) { bool hasEntry = false; @@ -421,12 +550,14 @@ namespace Nz::ShaderAst if (hasEntry) throw AstError{ "attribute entry must be present once" }; - if (arg.empty()) - throw AstError{ "attribute entry requires a parameter" }; + if (!std::holds_alternative(arg)) + throw AstError{ "attribute entry requires a string parameter" }; - auto it = entryPoints.find(arg); + const std::string& argStr = std::get(arg); + + auto it = entryPoints.find(argStr); if (it == entryPoints.end()) - throw AstError{ "invalid parameter " + arg + " for entry attribute" }; + throw AstError{ "invalid parameter " + argStr + " for entry attribute" }; ShaderStageType stageType = it->second; @@ -435,6 +566,9 @@ namespace Nz::ShaderAst m_context->cache->entryFunctions[UnderlyingCast(it->second)] = &node; + if (node.parameters.size() > 1) + throw AstError{ "entry functions can either take one struct parameter or no parameter" }; + hasEntry = true; break; } @@ -468,6 +602,8 @@ namespace Nz::ShaderAst RegisterScope(node); + //TODO: check members attributes + auto& scope = m_context->cache->scopes[*m_context->activeScopeId]; auto& identifier = scope.identifiers.emplace_back(); diff --git a/src/Nazara/Shader/ShaderLangLexer.cpp b/src/Nazara/Shader/ShaderLangLexer.cpp index 93b6bda1c..fbede99d0 100644 --- a/src/Nazara/Shader/ShaderLangLexer.cpp +++ b/src/Nazara/Shader/ShaderLangLexer.cpp @@ -36,22 +36,24 @@ namespace Nz::ShaderLang std::vector Tokenize(const std::string_view& str) { - // Can't use std::from_chars for double thanks to libc++ and libstdc++ developers for being lazy + // Can't use std::from_chars for double, thanks to libc++ and libstdc++ developers for being lazy ForceCLocale forceCLocale; std::unordered_map reservedKeywords = { - { "false", TokenType::BoolFalse }, - { "fn", TokenType::FunctionDeclaration }, - { "let", TokenType::Let }, - { "return", TokenType::Return }, - { "true", TokenType::BoolTrue } + { "external", TokenType::External }, + { "false", TokenType::BoolFalse }, + { "fn", TokenType::FunctionDeclaration }, + { "let", TokenType::Let }, + { "return", TokenType::Return }, + { "struct", TokenType::Struct }, + { "true", TokenType::BoolTrue } }; std::size_t currentPos = 0; auto Peek = [&](std::size_t advance = 1) -> char { - if (currentPos + advance < str.size()) + if (currentPos + advance < str.size() && str[currentPos + advance] != '\0') return str[currentPos + advance]; else return char(-1); @@ -134,7 +136,10 @@ namespace Nz::ShaderLang { currentPos++; if (Peek() == '/') + { + currentPos++; break; + } } else if (next == '\n') { @@ -250,7 +255,48 @@ namespace Nz::ShaderLang break; } - case '=': tokenType = TokenType::Assign; break; + case '=': + { + char next = Peek(); + if (next == '=') + { + currentPos++; + tokenType = TokenType::Equal; + } + else + tokenType = TokenType::Assign; + + break; + } + + case '<': + { + char next = Peek(); + if (next == '=') + { + currentPos++; + tokenType = TokenType::LessThanEqual; + } + else + tokenType = TokenType::LessThan; + + break; + } + + case '>': + { + char next = Peek(); + if (next == '=') + { + currentPos++; + tokenType = TokenType::GreatherThanEqual; + } + else + tokenType = TokenType::GreatherThan; + + break; + } + case '+': tokenType = TokenType::Plus; break; case '*': tokenType = TokenType::Multiply; break; case ':': tokenType = TokenType::Colon; break; diff --git a/src/Nazara/Shader/ShaderLangParser.cpp b/src/Nazara/Shader/ShaderLangParser.cpp index c2a05aad3..3a493ab30 100644 --- a/src/Nazara/Shader/ShaderLangParser.cpp +++ b/src/Nazara/Shader/ShaderLangParser.cpp @@ -11,32 +11,24 @@ namespace Nz::ShaderLang { namespace { - std::unordered_map identifierToBasicType = { - { "bool", ShaderAst::BasicType::Boolean }, + std::unordered_map identifierToBasicType = { + { "bool", ShaderAst::PrimitiveType::Boolean }, + { "i32", ShaderAst::PrimitiveType::Int32 }, + { "f32", ShaderAst::PrimitiveType::Float32 }, + { "u32", ShaderAst::PrimitiveType::UInt32 } + }; - { "i32", ShaderAst::BasicType::Int1 }, - { "vec2i32", ShaderAst::BasicType::Int2 }, - { "vec3i32", ShaderAst::BasicType::Int3 }, - { "vec4i32", ShaderAst::BasicType::Int4 }, - - { "f32", ShaderAst::BasicType::Float1 }, - { "vec2f32", ShaderAst::BasicType::Float2 }, - { "vec3f32", ShaderAst::BasicType::Float3 }, - { "vec4f32", ShaderAst::BasicType::Float4 }, - - { "mat4x4f32", ShaderAst::BasicType::Mat4x4 }, - { "sampler2D", ShaderAst::BasicType::Sampler2D }, - { "void", ShaderAst::BasicType::Void }, - - { "u32", ShaderAst::BasicType::UInt1 }, - { "vec2u32", ShaderAst::BasicType::UInt3 }, - { "vec3u32", ShaderAst::BasicType::UInt3 }, - { "vec4u32", ShaderAst::BasicType::UInt4 }, + std::unordered_map identifierToIntrinsic = { + { "cross", ShaderAst::IntrinsicType::CrossProduct }, + { "dot", ShaderAst::IntrinsicType::DotProduct }, }; std::unordered_map identifierToAttributeType = { - { "entry", ShaderAst::AttributeType::Entry }, - { "layout", ShaderAst::AttributeType::Layout }, + { "binding", ShaderAst::AttributeType::Binding }, + { "builtin", ShaderAst::AttributeType::Builtin }, + { "entry", ShaderAst::AttributeType::Entry }, + { "layout", ShaderAst::AttributeType::Layout }, + { "location", ShaderAst::AttributeType::Location }, }; } @@ -50,22 +42,41 @@ namespace Nz::ShaderLang m_context = &context; + std::vector attributes; + + EnterScope(); + bool reachedEndOfStream = false; while (!reachedEndOfStream) { const Token& nextToken = Peek(); switch (nextToken.type) { + case TokenType::EndOfStream: + if (!attributes.empty()) + throw UnexpectedToken{}; + + reachedEndOfStream = true; + break; + + case TokenType::External: + context.root->statements.push_back(ParseExternalBlock(std::move(attributes))); + attributes.clear(); + break; + case TokenType::OpenAttribute: - HandleAttributes(); + assert(attributes.empty()); + attributes = ParseAttributes(); break; case TokenType::FunctionDeclaration: - context.root->statements.push_back(ParseFunctionDeclaration()); + context.root->statements.push_back(ParseFunctionDeclaration(std::move(attributes))); + attributes.clear(); break; - case TokenType::EndOfStream: - reachedEndOfStream = true; + case TokenType::Struct: + context.root->statements.push_back(ParseStructDeclaration(std::move(attributes))); + attributes.clear(); break; default: @@ -73,6 +84,8 @@ namespace Nz::ShaderLang } } + LeaveScope(); + return std::move(context.root); } @@ -90,6 +103,92 @@ namespace Nz::ShaderLang m_context->tokenIndex += count; } + ShaderAst::ExpressionType Parser::DecodeType(const std::string& identifier) + { + if (auto it = identifierToBasicType.find(identifier); it != identifierToBasicType.end()) + return it->second; + + //FIXME: Handle this better + if (identifier == "mat4") + { + ShaderAst::MatrixType matrixType; + matrixType.columnCount = 4; + matrixType.rowCount = 4; + + Expect(Advance(), TokenType::LessThan); //< '<' + matrixType.type = ParsePrimitiveType(); + Expect(Advance(), TokenType::GreatherThan); //< '>' + + return matrixType; + } + else if (identifier == "sampler2D") + { + ShaderAst::SamplerType samplerType; + samplerType.dim = ImageType_2D; + + Expect(Advance(), TokenType::LessThan); //< '<' + samplerType.sampledType = ParsePrimitiveType(); + Expect(Advance(), TokenType::GreatherThan); //< '>' + + return samplerType; + } + else if (identifier == "uniform") + { + ShaderAst::UniformType uniformType; + + Expect(Advance(), TokenType::LessThan); //< '<' + uniformType.containedType = ShaderAst::IdentifierType{ ParseIdentifierAsName() }; + Expect(Advance(), TokenType::GreatherThan); //< '>' + + return uniformType; + } + else if (identifier == "vec2") + { + ShaderAst::VectorType vectorType; + vectorType.componentCount = 2; + + Expect(Advance(), TokenType::LessThan); //< '<' + vectorType.type = ParsePrimitiveType(); + Expect(Advance(), TokenType::GreatherThan); //< '>' + + return vectorType; + } + else if (identifier == "vec3") + { + ShaderAst::VectorType vectorType; + vectorType.componentCount = 3; + + Expect(Advance(), TokenType::LessThan); //< '<' + vectorType.type = ParsePrimitiveType(); + Expect(Advance(), TokenType::GreatherThan); //< '>' + + return vectorType; + } + else if (identifier == "vec4") + { + ShaderAst::VectorType vectorType; + vectorType.componentCount = 4; + + Expect(Advance(), TokenType::LessThan); //< '<' + vectorType.type = ParsePrimitiveType(); + Expect(Advance(), TokenType::GreatherThan); //< '>' + + return vectorType; + } + else + { + ShaderAst::IdentifierType identifierType; + identifierType.name = identifier; + + return identifierType; + } + } + + void Parser::EnterScope() + { + m_context->scopeSizes.push_back(m_context->identifiersInScope.size()); + } + const Token& Parser::Expect(const Token& token, TokenType type) { if (token.type != type) @@ -114,13 +213,34 @@ namespace Nz::ShaderLang return token; } + void Parser::LeaveScope() + { + assert(!m_context->scopeSizes.empty()); + m_context->identifiersInScope.resize(m_context->scopeSizes.back()); + m_context->scopeSizes.pop_back(); + } + + bool Parser::IsVariableInScope(const std::string_view& identifier) const + { + return std::find(m_context->identifiersInScope.rbegin(), m_context->identifiersInScope.rend(), identifier) != m_context->identifiersInScope.rend(); + } + + void Parser::RegisterVariable(std::string identifier) + { + if (IsVariableInScope(identifier)) + throw DuplicateIdentifier{ ("identifier name " + identifier + " is already taken").c_str() }; + + assert(!m_context->scopeSizes.empty()); + m_context->identifiersInScope.push_back(std::move(identifier)); + } + const Token& Parser::Peek(std::size_t advance) { assert(m_context->tokenIndex + advance < m_context->tokenCount); return m_context->tokens[m_context->tokenIndex + advance]; } - void Parser::HandleAttributes() + std::vector Parser::ParseAttributes() { std::vector attributes; @@ -150,13 +270,22 @@ namespace Nz::ShaderLang ShaderAst::AttributeType attributeType = ParseIdentifierAsAttributeType(); - std::string arg; + ShaderAst::Attribute::Param arg; if (Peek().type == TokenType::OpenParenthesis) { Consume(); - if (Peek().type == TokenType::Identifier) - arg = std::get(Advance().data); + const Token& n = Peek(); + if (n.type == TokenType::Identifier) + { + arg = std::get(n.data); + Consume(); + } + else if (n.type == TokenType::IntegerValue) + { + arg = std::get(n.data); + Consume(); + } Expect(Advance(), TokenType::ClosingParenthesis); } @@ -171,16 +300,54 @@ namespace Nz::ShaderLang Expect(Advance(), TokenType::ClosingAttribute); - const Token& nextToken = Peek(); - switch (nextToken.type) + return attributes; + } + + ShaderAst::StatementPtr Parser::ParseExternalBlock(std::vector attributes) + { + Expect(Advance(), TokenType::External); + Expect(Advance(), TokenType::OpenCurlyBracket); + + std::unique_ptr externalStatement = std::make_unique(); + externalStatement->attributes = std::move(attributes); + + bool first = true; + + for (;;) { - case TokenType::FunctionDeclaration: - m_context->root->statements.push_back(ParseFunctionDeclaration(std::move(attributes))); + if (!first) + { + const Token& nextToken = Peek(); + if (nextToken.type == TokenType::Comma) + Consume(); + else + { + Expect(nextToken, TokenType::ClosingCurlyBracket); + break; + } + } + + first = false; + + const Token& token = Peek(); + if (token.type == TokenType::ClosingCurlyBracket) break; - default: - throw UnexpectedToken{}; + auto& extVar = externalStatement->externalVars.emplace_back(); + + if (token.type == TokenType::OpenAttribute) + extVar.attributes = ParseAttributes(); + + extVar.name = ParseIdentifierAsName(); + Expect(Advance(), TokenType::Colon); + extVar.type = ParseType(); + + RegisterVariable(extVar.name); } + + Expect(Advance(), TokenType::ClosingCurlyBracket); + + return externalStatement; } std::vector Parser::ParseFunctionBody() @@ -216,17 +383,23 @@ namespace Nz::ShaderLang Expect(Advance(), TokenType::ClosingParenthesis); - ShaderAst::ShaderExpressionType returnType = ShaderAst::BasicType::Void; + ShaderAst::ExpressionType returnType; if (Peek().type == TokenType::FunctionReturn) { Consume(); - returnType = ParseIdentifierAsType(); + returnType = ParseType(); } Expect(Advance(), TokenType::OpenCurlyBracket); + EnterScope(); + for (const auto& parameter : parameters) + RegisterVariable(parameter.name); + std::vector functionBody = ParseFunctionBody(); + LeaveScope(); + Expect(Advance(), TokenType::ClosingCurlyBracket); return ShaderBuilder::DeclareFunction(std::move(attributes), std::move(functionName), std::move(parameters), std::move(functionBody), std::move(returnType)); @@ -238,11 +411,59 @@ namespace Nz::ShaderLang Expect(Advance(), TokenType::Colon); - ShaderAst::ShaderExpressionType parameterType = ParseIdentifierAsType(); + ShaderAst::ExpressionType parameterType = ParseType(); return { parameterName, parameterType }; } + ShaderAst::StatementPtr Parser::ParseStructDeclaration(std::vector attributes) + { + Expect(Advance(), TokenType::Struct); + + ShaderAst::StructDescription description; + description.name = ParseIdentifierAsName(); + + Expect(Advance(), TokenType::OpenCurlyBracket); + + bool first = true; + + for (;;) + { + if (!first) + { + const Token& nextToken = Peek(); + if (nextToken.type == TokenType::Comma) + Consume(); + else + { + Expect(nextToken, TokenType::ClosingCurlyBracket); + break; + } + } + + first = false; + + const Token& token = Peek(); + if (token.type == TokenType::ClosingCurlyBracket) + break; + + auto& structField = description.members.emplace_back(); + + if (token.type == TokenType::OpenAttribute) + structField.attributes = ParseAttributes(); + + structField.name = ParseIdentifierAsName(); + + Expect(Advance(), TokenType::Colon); + + structField.type = ParseType(); + } + + Expect(Advance(), TokenType::ClosingCurlyBracket); + + return ShaderBuilder::DeclareStruct(std::move(attributes), std::move(description)); + } + ShaderAst::StatementPtr Parser::ParseReturnStatement() { Expect(Advance(), TokenType::Return); @@ -265,6 +486,10 @@ namespace Nz::ShaderLang statement = ParseVariableDeclaration(); break; + case TokenType::Identifier: + statement = ShaderBuilder::ExpressionStatement(ParseVariableAssignation()); + break; + case TokenType::Return: statement = ParseReturnStatement(); break; @@ -290,15 +515,26 @@ namespace Nz::ShaderLang return statements; } + ShaderAst::ExpressionPtr Parser::ParseVariableAssignation() + { + ShaderAst::ExpressionPtr left = ParseIdentifier(); + Expect(Advance(), TokenType::Assign); + + ShaderAst::ExpressionPtr right = ParseExpression(); + + return ShaderBuilder::Assign(ShaderAst::AssignType::Simple, std::move(left), std::move(right)); + } + ShaderAst::StatementPtr Parser::ParseVariableDeclaration() { Expect(Advance(), TokenType::Let); std::string variableName = ParseIdentifierAsName(); + RegisterVariable(variableName); Expect(Advance(), TokenType::Colon); - ShaderAst::ShaderExpressionType variableType = ParseIdentifierAsType(); + ShaderAst::ExpressionType variableType = ParseType(); ShaderAst::ExpressionPtr expression; if (Peek().type == TokenType::Assign) @@ -351,18 +587,61 @@ namespace Nz::ShaderLang return ParseBinOpRhs(0, ParsePrimaryExpression()); } + ShaderAst::ExpressionPtr Parser::ParseFloatingPointExpression(bool minus) + { + const Token& floatingPointToken = Expect(Advance(), TokenType::FloatingPointValue); + return ShaderBuilder::Constant(((minus) ? -1.f : 1.f) * float(std::get(floatingPointToken.data))); //< FIXME + } + ShaderAst::ExpressionPtr Parser::ParseIdentifier() { const Token& identifierToken = Expect(Advance(), TokenType::Identifier); const std::string& identifier = std::get(identifierToken.data); - return ShaderBuilder::Identifier(identifier); + ShaderAst::ExpressionPtr identifierExpr = ShaderBuilder::Identifier(identifier); + + if (Peek().type == TokenType::Dot) + { + std::unique_ptr accessMemberNode = std::make_unique(); + accessMemberNode->structExpr = std::move(identifierExpr); + + do + { + Consume(); + + accessMemberNode->memberIdentifiers.push_back(ParseIdentifierAsName()); + } while (Peek().type == TokenType::Dot); + + identifierExpr = std::move(accessMemberNode); + } + + return identifierExpr; } - ShaderAst::ExpressionPtr Parser::ParseIntegerExpression() + ShaderAst::ExpressionPtr Parser::ParseIntegerExpression(bool minus) { - const Token& integerToken = Expect(Advance(), TokenType::Identifier); - return ShaderBuilder::Constant(static_cast(std::get(integerToken.data))); + const Token& integerToken = Expect(Advance(), TokenType::IntegerValue); + return ShaderBuilder::Constant(((minus) ? -1 : 1) * static_cast(std::get(integerToken.data))); + } + + std::vector Parser::ParseParameters() + { + Expect(Advance(), TokenType::OpenParenthesis); + + std::vector parameters; + bool first = true; + while (Peek().type != TokenType::ClosingParenthesis) + { + if (!first) + Expect(Advance(), TokenType::Comma); + + first = false; + parameters.push_back(ParseExpression()); + } + + Expect(Advance(), TokenType::ClosingParenthesis); + + return parameters; } ShaderAst::ExpressionPtr Parser::ParseParenthesisExpression() @@ -388,15 +667,69 @@ namespace Nz::ShaderLang return ShaderBuilder::Constant(true); case TokenType::FloatingPointValue: - Consume(); - return ShaderBuilder::Constant(float(std::get(token.data))); //< FIXME + return ParseFloatingPointExpression(); case TokenType::Identifier: - return ParseIdentifier(); + { + const std::string& identifier = std::get(token.data); + + if (auto it = identifierToIntrinsic.find(identifier); it != identifierToIntrinsic.end()) + { + if (Peek(1).type == TokenType::OpenParenthesis) + { + Consume(); + return ShaderBuilder::Intrinsic(it->second, ParseParameters()); + } + } + + if (IsVariableInScope(identifier)) + { + auto node = ParseIdentifier(); + if (node->GetType() == ShaderAst::NodeType::AccessMemberExpression) + { + ShaderAst::AccessMemberExpression* memberExpr = static_cast(node.get()); + if (!memberExpr->memberIdentifiers.empty() && memberExpr->memberIdentifiers.front() == "Sample") + { + if (Peek().type == TokenType::OpenParenthesis) + { + auto parameters = ParseParameters(); + parameters.insert(parameters.begin(), std::move(memberExpr->structExpr)); + + return ShaderBuilder::Intrinsic(ShaderAst::IntrinsicType::SampleTexture, std::move(parameters)); + } + } + } + + return node; + } + + Consume(); + + ShaderAst::ExpressionType exprType = DecodeType(identifier); + + return ShaderBuilder::Cast(std::move(exprType), ParseParameters()); + } case TokenType::IntegerValue: return ParseIntegerExpression(); + case TokenType::Minus: + //< FIXME: Handle this with an unary node + if (Peek(1).type == TokenType::FloatingPointValue) + { + Consume(); + return ParseFloatingPointExpression(true); + } + else if (Peek(1).type == TokenType::IntegerValue) + { + Consume(); + return ParseIntegerExpression(true); + } + else + throw UnexpectedToken{}; + + break; + case TokenType::OpenParenthesis: return ParseParenthesisExpression(); @@ -429,7 +762,7 @@ namespace Nz::ShaderLang return identifier; } - ShaderAst::ShaderExpressionType Parser::ParseIdentifierAsType() + ShaderAst::PrimitiveType Parser::ParsePrimitiveType() { const Token& identifierToken = Expect(Advance(), TokenType::Identifier); const std::string& identifier = std::get(identifierToken.data); @@ -441,6 +774,23 @@ namespace Nz::ShaderLang return it->second; } + ShaderAst::ExpressionType Parser::ParseType() + { + // Handle () as no type + if (Peek().type == TokenType::OpenParenthesis) + { + Consume(); + Expect(Advance(), TokenType::ClosingParenthesis); + + return ShaderAst::NoType{}; + } + + const Token& identifierToken = Expect(Advance(), TokenType::Identifier); + const std::string& identifier = std::get(identifierToken.data); + + return DecodeType(identifier); + } + int Parser::GetTokenPrecedence(TokenType token) { switch (token) @@ -452,4 +802,5 @@ namespace Nz::ShaderLang default: return -1; } } + } diff --git a/src/Nazara/Shader/SpirvAstVisitor.cpp b/src/Nazara/Shader/SpirvAstVisitor.cpp index 0dd4737a3..d559e7965 100644 --- a/src/Nazara/Shader/SpirvAstVisitor.cpp +++ b/src/Nazara/Shader/SpirvAstVisitor.cpp @@ -39,18 +39,18 @@ namespace Nz void SpirvAstVisitor::Visit(ShaderAst::BinaryExpression& node) { - ShaderAst::ShaderExpressionType resultExprType = ShaderAst::GetExpressionType(node, m_cache); - assert(IsBasicType(resultExprType)); + ShaderAst::ExpressionType resultExprType = ShaderAst::GetExpressionType(node, m_cache); + assert(IsPrimitiveType(resultExprType)); - ShaderAst::ShaderExpressionType leftExprType = ShaderAst::GetExpressionType(*node.left, m_cache); - assert(IsBasicType(leftExprType)); + ShaderAst::ExpressionType leftExprType = ShaderAst::GetExpressionType(*node.left, m_cache); + assert(IsPrimitiveType(leftExprType)); - ShaderAst::ShaderExpressionType rightExprType = ShaderAst::GetExpressionType(*node.right, m_cache); - assert(IsBasicType(rightExprType)); + ShaderAst::ExpressionType rightExprType = ShaderAst::GetExpressionType(*node.right, m_cache); + assert(IsPrimitiveType(rightExprType)); - ShaderAst::BasicType resultType = std::get(resultExprType); - ShaderAst::BasicType leftType = std::get(leftExprType); - ShaderAst::BasicType rightType = std::get(rightExprType); + ShaderAst::PrimitiveType resultType = std::get(resultExprType); + ShaderAst::PrimitiveType leftType = std::get(leftExprType); + ShaderAst::PrimitiveType rightType = std::get(rightExprType); UInt32 leftOperand = EvaluateExpression(node.left); @@ -67,26 +67,26 @@ namespace Nz { switch (leftType) { - case ShaderAst::BasicType::Float1: - case ShaderAst::BasicType::Float2: - case ShaderAst::BasicType::Float3: - case ShaderAst::BasicType::Float4: - case ShaderAst::BasicType::Mat4x4: + case ShaderAst::PrimitiveType::Float32: +// case ShaderAst::PrimitiveType::Float2: +// case ShaderAst::PrimitiveType::Float3: +// case ShaderAst::PrimitiveType::Float4: +// case ShaderAst::PrimitiveType::Mat4x4: return SpirvOp::OpFAdd; - case ShaderAst::BasicType::Int1: - case ShaderAst::BasicType::Int2: - case ShaderAst::BasicType::Int3: - case ShaderAst::BasicType::Int4: - case ShaderAst::BasicType::UInt1: - case ShaderAst::BasicType::UInt2: - case ShaderAst::BasicType::UInt3: - case ShaderAst::BasicType::UInt4: + case ShaderAst::PrimitiveType::Int32: +// case ShaderAst::PrimitiveType::Int2: +// case ShaderAst::PrimitiveType::Int3: +// case ShaderAst::PrimitiveType::Int4: + case ShaderAst::PrimitiveType::UInt32: +// case ShaderAst::PrimitiveType::UInt2: +// case ShaderAst::PrimitiveType::UInt3: +// case ShaderAst::PrimitiveType::UInt4: return SpirvOp::OpIAdd; - case ShaderAst::BasicType::Boolean: - case ShaderAst::BasicType::Sampler2D: - case ShaderAst::BasicType::Void: + case ShaderAst::PrimitiveType::Boolean: +// case ShaderAst::PrimitiveType::Sampler2D: +// case ShaderAst::PrimitiveType::Void: break; } @@ -97,26 +97,26 @@ namespace Nz { switch (leftType) { - case ShaderAst::BasicType::Float1: - case ShaderAst::BasicType::Float2: - case ShaderAst::BasicType::Float3: - case ShaderAst::BasicType::Float4: - case ShaderAst::BasicType::Mat4x4: + case ShaderAst::PrimitiveType::Float32: +// case ShaderAst::PrimitiveType::Float2: +// case ShaderAst::PrimitiveType::Float3: +// case ShaderAst::PrimitiveType::Float4: +// case ShaderAst::PrimitiveType::Mat4x4: return SpirvOp::OpFSub; - case ShaderAst::BasicType::Int1: - case ShaderAst::BasicType::Int2: - case ShaderAst::BasicType::Int3: - case ShaderAst::BasicType::Int4: - case ShaderAst::BasicType::UInt1: - case ShaderAst::BasicType::UInt2: - case ShaderAst::BasicType::UInt3: - case ShaderAst::BasicType::UInt4: + case ShaderAst::PrimitiveType::Int32: +// case ShaderAst::PrimitiveType::Int2: +// case ShaderAst::PrimitiveType::Int3: +// case ShaderAst::PrimitiveType::Int4: + case ShaderAst::PrimitiveType::UInt32: +// case ShaderAst::PrimitiveType::UInt2: +// case ShaderAst::PrimitiveType::UInt3: +// case ShaderAst::PrimitiveType::UInt4: return SpirvOp::OpISub; - case ShaderAst::BasicType::Boolean: - case ShaderAst::BasicType::Sampler2D: - case ShaderAst::BasicType::Void: + case ShaderAst::PrimitiveType::Boolean: +// case ShaderAst::PrimitiveType::Sampler2D: +// case ShaderAst::PrimitiveType::Void: break; } @@ -127,28 +127,28 @@ namespace Nz { switch (leftType) { - case ShaderAst::BasicType::Float1: - case ShaderAst::BasicType::Float2: - case ShaderAst::BasicType::Float3: - case ShaderAst::BasicType::Float4: - case ShaderAst::BasicType::Mat4x4: + case ShaderAst::PrimitiveType::Float32: +// case ShaderAst::PrimitiveType::Float2: +// case ShaderAst::PrimitiveType::Float3: +// case ShaderAst::PrimitiveType::Float4: +// case ShaderAst::PrimitiveType::Mat4x4: return SpirvOp::OpFDiv; - case ShaderAst::BasicType::Int1: - case ShaderAst::BasicType::Int2: - case ShaderAst::BasicType::Int3: - case ShaderAst::BasicType::Int4: + case ShaderAst::PrimitiveType::Int32: +// case ShaderAst::PrimitiveType::Int2: +// case ShaderAst::PrimitiveType::Int3: +// case ShaderAst::PrimitiveType::Int4: return SpirvOp::OpSDiv; - case ShaderAst::BasicType::UInt1: - case ShaderAst::BasicType::UInt2: - case ShaderAst::BasicType::UInt3: - case ShaderAst::BasicType::UInt4: + case ShaderAst::PrimitiveType::UInt32: +// case ShaderAst::PrimitiveType::UInt2: +// case ShaderAst::PrimitiveType::UInt3: +// case ShaderAst::PrimitiveType::UInt4: return SpirvOp::OpUDiv; - case ShaderAst::BasicType::Boolean: - case ShaderAst::BasicType::Sampler2D: - case ShaderAst::BasicType::Void: + case ShaderAst::PrimitiveType::Boolean: +// case ShaderAst::PrimitiveType::Sampler2D: +// case ShaderAst::PrimitiveType::Void: break; } @@ -159,29 +159,29 @@ namespace Nz { switch (leftType) { - case ShaderAst::BasicType::Boolean: + case ShaderAst::PrimitiveType::Boolean: return SpirvOp::OpLogicalEqual; - case ShaderAst::BasicType::Float1: - case ShaderAst::BasicType::Float2: - case ShaderAst::BasicType::Float3: - case ShaderAst::BasicType::Float4: - case ShaderAst::BasicType::Mat4x4: + case ShaderAst::PrimitiveType::Float32: +// case ShaderAst::PrimitiveType::Float2: +// case ShaderAst::PrimitiveType::Float3: +// case ShaderAst::PrimitiveType::Float4: +// case ShaderAst::PrimitiveType::Mat4x4: return SpirvOp::OpFOrdEqual; - case ShaderAst::BasicType::Int1: - case ShaderAst::BasicType::Int2: - case ShaderAst::BasicType::Int3: - case ShaderAst::BasicType::Int4: - case ShaderAst::BasicType::UInt1: - case ShaderAst::BasicType::UInt2: - case ShaderAst::BasicType::UInt3: - case ShaderAst::BasicType::UInt4: + case ShaderAst::PrimitiveType::Int32: +// case ShaderAst::PrimitiveType::Int2: +// case ShaderAst::PrimitiveType::Int3: +// case ShaderAst::PrimitiveType::Int4: + case ShaderAst::PrimitiveType::UInt32: +// case ShaderAst::PrimitiveType::UInt2: +// case ShaderAst::PrimitiveType::UInt3: +// case ShaderAst::PrimitiveType::UInt4: return SpirvOp::OpIEqual; - case ShaderAst::BasicType::Sampler2D: - case ShaderAst::BasicType::Void: - break; +// case ShaderAst::PrimitiveType::Sampler2D: +// case ShaderAst::PrimitiveType::Void: +// break; } break; @@ -191,28 +191,28 @@ namespace Nz { switch (leftType) { - case ShaderAst::BasicType::Float1: - case ShaderAst::BasicType::Float2: - case ShaderAst::BasicType::Float3: - case ShaderAst::BasicType::Float4: - case ShaderAst::BasicType::Mat4x4: + case ShaderAst::PrimitiveType::Float32: +// case ShaderAst::PrimitiveType::Float2: +// case ShaderAst::PrimitiveType::Float3: +// case ShaderAst::PrimitiveType::Float4: +// case ShaderAst::PrimitiveType::Mat4x4: return SpirvOp::OpFOrdGreaterThan; - case ShaderAst::BasicType::Int1: - case ShaderAst::BasicType::Int2: - case ShaderAst::BasicType::Int3: - case ShaderAst::BasicType::Int4: + case ShaderAst::PrimitiveType::Int32: +// case ShaderAst::PrimitiveType::Int2: +// case ShaderAst::PrimitiveType::Int3: +// case ShaderAst::PrimitiveType::Int4: return SpirvOp::OpSGreaterThan; - case ShaderAst::BasicType::UInt1: - case ShaderAst::BasicType::UInt2: - case ShaderAst::BasicType::UInt3: - case ShaderAst::BasicType::UInt4: + case ShaderAst::PrimitiveType::UInt32: +// case ShaderAst::PrimitiveType::UInt2: +// case ShaderAst::PrimitiveType::UInt3: +// case ShaderAst::PrimitiveType::UInt4: return SpirvOp::OpUGreaterThan; - case ShaderAst::BasicType::Boolean: - case ShaderAst::BasicType::Sampler2D: - case ShaderAst::BasicType::Void: + case ShaderAst::PrimitiveType::Boolean: +// case ShaderAst::PrimitiveType::Sampler2D: +// case ShaderAst::PrimitiveType::Void: break; } @@ -223,28 +223,28 @@ namespace Nz { switch (leftType) { - case ShaderAst::BasicType::Float1: - case ShaderAst::BasicType::Float2: - case ShaderAst::BasicType::Float3: - case ShaderAst::BasicType::Float4: - case ShaderAst::BasicType::Mat4x4: + case ShaderAst::PrimitiveType::Float32: +// case ShaderAst::PrimitiveType::Float2: +// case ShaderAst::PrimitiveType::Float3: +// case ShaderAst::PrimitiveType::Float4: +// case ShaderAst::PrimitiveType::Mat4x4: return SpirvOp::OpFOrdGreaterThanEqual; - case ShaderAst::BasicType::Int1: - case ShaderAst::BasicType::Int2: - case ShaderAst::BasicType::Int3: - case ShaderAst::BasicType::Int4: + case ShaderAst::PrimitiveType::Int32: +// case ShaderAst::PrimitiveType::Int2: +// case ShaderAst::PrimitiveType::Int3: +// case ShaderAst::PrimitiveType::Int4: return SpirvOp::OpSGreaterThanEqual; - case ShaderAst::BasicType::UInt1: - case ShaderAst::BasicType::UInt2: - case ShaderAst::BasicType::UInt3: - case ShaderAst::BasicType::UInt4: + case ShaderAst::PrimitiveType::UInt32: +// case ShaderAst::PrimitiveType::UInt2: +// case ShaderAst::PrimitiveType::UInt3: +// case ShaderAst::PrimitiveType::UInt4: return SpirvOp::OpUGreaterThanEqual; - case ShaderAst::BasicType::Boolean: - case ShaderAst::BasicType::Sampler2D: - case ShaderAst::BasicType::Void: + case ShaderAst::PrimitiveType::Boolean: +// case ShaderAst::PrimitiveType::Sampler2D: +// case ShaderAst::PrimitiveType::Void: break; } @@ -255,28 +255,28 @@ namespace Nz { switch (leftType) { - case ShaderAst::BasicType::Float1: - case ShaderAst::BasicType::Float2: - case ShaderAst::BasicType::Float3: - case ShaderAst::BasicType::Float4: - case ShaderAst::BasicType::Mat4x4: + case ShaderAst::PrimitiveType::Float32: +// case ShaderAst::PrimitiveType::Float2: +// case ShaderAst::PrimitiveType::Float3: +// case ShaderAst::PrimitiveType::Float4: +// case ShaderAst::PrimitiveType::Mat4x4: return SpirvOp::OpFOrdLessThanEqual; - case ShaderAst::BasicType::Int1: - case ShaderAst::BasicType::Int2: - case ShaderAst::BasicType::Int3: - case ShaderAst::BasicType::Int4: + case ShaderAst::PrimitiveType::Int32: +// case ShaderAst::PrimitiveType::Int2: +// case ShaderAst::PrimitiveType::Int3: +// case ShaderAst::PrimitiveType::Int4: return SpirvOp::OpSLessThanEqual; - case ShaderAst::BasicType::UInt1: - case ShaderAst::BasicType::UInt2: - case ShaderAst::BasicType::UInt3: - case ShaderAst::BasicType::UInt4: + case ShaderAst::PrimitiveType::UInt32: +// case ShaderAst::PrimitiveType::UInt2: +// case ShaderAst::PrimitiveType::UInt3: +// case ShaderAst::PrimitiveType::UInt4: return SpirvOp::OpULessThanEqual; - case ShaderAst::BasicType::Boolean: - case ShaderAst::BasicType::Sampler2D: - case ShaderAst::BasicType::Void: + case ShaderAst::PrimitiveType::Boolean: +// case ShaderAst::PrimitiveType::Sampler2D: +// case ShaderAst::PrimitiveType::Void: break; } @@ -287,28 +287,28 @@ namespace Nz { switch (leftType) { - case ShaderAst::BasicType::Float1: - case ShaderAst::BasicType::Float2: - case ShaderAst::BasicType::Float3: - case ShaderAst::BasicType::Float4: - case ShaderAst::BasicType::Mat4x4: + case ShaderAst::PrimitiveType::Float32: +// case ShaderAst::PrimitiveType::Float2: +// case ShaderAst::PrimitiveType::Float3: +// case ShaderAst::PrimitiveType::Float4: +// case ShaderAst::PrimitiveType::Mat4x4: return SpirvOp::OpFOrdLessThan; - case ShaderAst::BasicType::Int1: - case ShaderAst::BasicType::Int2: - case ShaderAst::BasicType::Int3: - case ShaderAst::BasicType::Int4: + case ShaderAst::PrimitiveType::Int32: +// case ShaderAst::PrimitiveType::Int2: +// case ShaderAst::PrimitiveType::Int3: +// case ShaderAst::PrimitiveType::Int4: return SpirvOp::OpSLessThan; - case ShaderAst::BasicType::UInt1: - case ShaderAst::BasicType::UInt2: - case ShaderAst::BasicType::UInt3: - case ShaderAst::BasicType::UInt4: + case ShaderAst::PrimitiveType::UInt32: +// case ShaderAst::PrimitiveType::UInt2: +// case ShaderAst::PrimitiveType::UInt3: +// case ShaderAst::PrimitiveType::UInt4: return SpirvOp::OpULessThan; - case ShaderAst::BasicType::Boolean: - case ShaderAst::BasicType::Sampler2D: - case ShaderAst::BasicType::Void: + case ShaderAst::PrimitiveType::Boolean: +// case ShaderAst::PrimitiveType::Sampler2D: +// case ShaderAst::PrimitiveType::Void: break; } @@ -319,29 +319,29 @@ namespace Nz { switch (leftType) { - case ShaderAst::BasicType::Boolean: + case ShaderAst::PrimitiveType::Boolean: return SpirvOp::OpLogicalNotEqual; - case ShaderAst::BasicType::Float1: - case ShaderAst::BasicType::Float2: - case ShaderAst::BasicType::Float3: - case ShaderAst::BasicType::Float4: - case ShaderAst::BasicType::Mat4x4: + case ShaderAst::PrimitiveType::Float32: +// case ShaderAst::PrimitiveType::Float2: +// case ShaderAst::PrimitiveType::Float3: +// case ShaderAst::PrimitiveType::Float4: +// case ShaderAst::PrimitiveType::Mat4x4: return SpirvOp::OpFOrdNotEqual; - case ShaderAst::BasicType::Int1: - case ShaderAst::BasicType::Int2: - case ShaderAst::BasicType::Int3: - case ShaderAst::BasicType::Int4: - case ShaderAst::BasicType::UInt1: - case ShaderAst::BasicType::UInt2: - case ShaderAst::BasicType::UInt3: - case ShaderAst::BasicType::UInt4: + case ShaderAst::PrimitiveType::Int32: +// case ShaderAst::PrimitiveType::Int2: +// case ShaderAst::PrimitiveType::Int3: +// case ShaderAst::PrimitiveType::Int4: + case ShaderAst::PrimitiveType::UInt32: +// case ShaderAst::PrimitiveType::UInt2: +// case ShaderAst::PrimitiveType::UInt3: +// case ShaderAst::PrimitiveType::UInt4: return SpirvOp::OpINotEqual; - case ShaderAst::BasicType::Sampler2D: - case ShaderAst::BasicType::Void: - break; +// case ShaderAst::PrimitiveType::Sampler2D: +// case ShaderAst::PrimitiveType::Void: +// break; } break; @@ -351,22 +351,22 @@ namespace Nz { switch (leftType) { - case ShaderAst::BasicType::Float1: + case ShaderAst::PrimitiveType::Float32: { switch (rightType) { - case ShaderAst::BasicType::Float1: + case ShaderAst::PrimitiveType::Float32: return SpirvOp::OpFMul; - case ShaderAst::BasicType::Float2: - case ShaderAst::BasicType::Float3: - case ShaderAst::BasicType::Float4: - swapOperands = true; - return SpirvOp::OpVectorTimesScalar; - - case ShaderAst::BasicType::Mat4x4: - swapOperands = true; - return SpirvOp::OpMatrixTimesScalar; +// case ShaderAst::PrimitiveType::Float2: +// case ShaderAst::PrimitiveType::Float3: +// case ShaderAst::PrimitiveType::Float4: +// swapOperands = true; +// return SpirvOp::OpVectorTimesScalar; +// +// case ShaderAst::PrimitiveType::Mat4x4: +// swapOperands = true; +// return SpirvOp::OpMatrixTimesScalar; default: break; @@ -375,54 +375,54 @@ namespace Nz break; } - case ShaderAst::BasicType::Float2: - case ShaderAst::BasicType::Float3: - case ShaderAst::BasicType::Float4: - { - switch (rightType) - { - case ShaderAst::BasicType::Float1: - return SpirvOp::OpVectorTimesScalar; +// case ShaderAst::PrimitiveType::Float2: +// case ShaderAst::PrimitiveType::Float3: +// case ShaderAst::PrimitiveType::Float4: +// { +// switch (rightType) +// { +// case ShaderAst::PrimitiveType::Float32: +// return SpirvOp::OpVectorTimesScalar; +// +// case ShaderAst::PrimitiveType::Float2: +// case ShaderAst::PrimitiveType::Float3: +// case ShaderAst::PrimitiveType::Float4: +// return SpirvOp::OpFMul; +// +// case ShaderAst::PrimitiveType::Mat4x4: +// return SpirvOp::OpVectorTimesMatrix; +// +// default: +// break; +// } +// +// break; +// } - case ShaderAst::BasicType::Float2: - case ShaderAst::BasicType::Float3: - case ShaderAst::BasicType::Float4: - return SpirvOp::OpFMul; - - case ShaderAst::BasicType::Mat4x4: - return SpirvOp::OpVectorTimesMatrix; - - default: - break; - } - - break; - } - - case ShaderAst::BasicType::Int1: - case ShaderAst::BasicType::Int2: - case ShaderAst::BasicType::Int3: - case ShaderAst::BasicType::Int4: - case ShaderAst::BasicType::UInt1: - case ShaderAst::BasicType::UInt2: - case ShaderAst::BasicType::UInt3: - case ShaderAst::BasicType::UInt4: + case ShaderAst::PrimitiveType::Int32: +// case ShaderAst::PrimitiveType::Int2: +// case ShaderAst::PrimitiveType::Int3: +// case ShaderAst::PrimitiveType::Int4: + case ShaderAst::PrimitiveType::UInt32: +// case ShaderAst::PrimitiveType::UInt2: +// case ShaderAst::PrimitiveType::UInt3: +// case ShaderAst::PrimitiveType::UInt4: return SpirvOp::OpIMul; - case ShaderAst::BasicType::Mat4x4: - { - switch (rightType) - { - case ShaderAst::BasicType::Float1: return SpirvOp::OpMatrixTimesScalar; - case ShaderAst::BasicType::Float4: return SpirvOp::OpMatrixTimesVector; - case ShaderAst::BasicType::Mat4x4: return SpirvOp::OpMatrixTimesMatrix; - - default: - break; - } - - break; - } +// case ShaderAst::PrimitiveType::Mat4x4: +// { +// switch (rightType) +// { +// case ShaderAst::PrimitiveType::Float32: return SpirvOp::OpMatrixTimesScalar; +// case ShaderAst::PrimitiveType::Float4: return SpirvOp::OpMatrixTimesVector; +// case ShaderAst::PrimitiveType::Mat4x4: return SpirvOp::OpMatrixTimesMatrix; +// +// default: +// break; +// } +// +// break; +// } default: break; @@ -501,10 +501,10 @@ namespace Nz void SpirvAstVisitor::Visit(ShaderAst::CastExpression& node) { - const ShaderAst::ShaderExpressionType& targetExprType = node.targetType; - assert(IsBasicType(targetExprType)); + const ShaderAst::ExpressionType& targetExprType = node.targetType; + assert(IsPrimitiveType(targetExprType)); - ShaderAst::BasicType targetType = std::get(targetExprType); + ShaderAst::PrimitiveType targetType = std::get(targetExprType); StackVector exprResults = NazaraStackVector(UInt32, node.expressions.size()); @@ -582,12 +582,12 @@ namespace Nz { case ShaderAst::IntrinsicType::DotProduct: { - ShaderAst::ShaderExpressionType vecExprType = GetExpressionType(*node.parameters[0], m_cache); - assert(IsBasicType(vecExprType)); + ShaderAst::ExpressionType vecExprType = GetExpressionType(*node.parameters[0], m_cache); + assert(IsVectorType(vecExprType)); - ShaderAst::BasicType vecType = std::get(vecExprType); + const ShaderAst::VectorType& vecType = std::get(vecExprType); - UInt32 typeId = m_writer.GetTypeId(ShaderAst::GetComponentType(vecType)); + UInt32 typeId = m_writer.GetTypeId(vecType.type); UInt32 vec1 = EvaluateExpression(node.parameters[0]); UInt32 vec2 = EvaluateExpression(node.parameters[1]); @@ -626,10 +626,10 @@ namespace Nz void SpirvAstVisitor::Visit(ShaderAst::SwizzleExpression& node) { - ShaderAst::ShaderExpressionType targetExprType = ShaderAst::GetExpressionType(node, m_cache); - assert(IsBasicType(targetExprType)); + ShaderAst::ExpressionType targetExprType = ShaderAst::GetExpressionType(node, m_cache); + assert(IsPrimitiveType(targetExprType)); - ShaderAst::BasicType targetType = std::get(targetExprType); + ShaderAst::PrimitiveType targetType = std::get(targetExprType); UInt32 exprResultId = EvaluateExpression(node.expression); UInt32 resultId = m_writer.AllocateResultId(); diff --git a/src/Nazara/Shader/SpirvConstantCache.cpp b/src/Nazara/Shader/SpirvConstantCache.cpp index 6146c29e5..cc3421ac2 100644 --- a/src/Nazara/Shader/SpirvConstantCache.cpp +++ b/src/Nazara/Shader/SpirvConstantCache.cpp @@ -535,7 +535,7 @@ namespace Nz else if constexpr (std::is_same_v || std::is_same_v) { return ConstantComposite{ - BuildType((std::is_same_v) ? ShaderAst::BasicType::Float2 : ShaderAst::BasicType::Int2), + BuildType(ShaderAst::VectorType{ 2, (std::is_same_v) ? ShaderAst::PrimitiveType::Float32 : ShaderAst::PrimitiveType::Int32 }), { BuildConstant(arg.x), BuildConstant(arg.y) @@ -545,7 +545,7 @@ namespace Nz else if constexpr (std::is_same_v || std::is_same_v) { return ConstantComposite{ - BuildType((std::is_same_v) ? ShaderAst::BasicType::Float3 : ShaderAst::BasicType::Int3), + BuildType(ShaderAst::VectorType{ 3, (std::is_same_v) ? ShaderAst::PrimitiveType::Float32 : ShaderAst::PrimitiveType::Int32 }), { BuildConstant(arg.x), BuildConstant(arg.y), @@ -556,7 +556,7 @@ namespace Nz else if constexpr (std::is_same_v || std::is_same_v) { return ConstantComposite{ - BuildType((std::is_same_v) ? ShaderAst::BasicType::Float4 : ShaderAst::BasicType::Int4), + BuildType(ShaderAst::VectorType{ 4, (std::is_same_v) ? ShaderAst::PrimitiveType::Float32 : ShaderAst::PrimitiveType::Int32 }), { BuildConstant(arg.x), BuildConstant(arg.y), @@ -570,7 +570,7 @@ namespace Nz }, value)); } - auto SpirvConstantCache::BuildFunctionType(const ShaderAst::ShaderExpressionType& retType, const std::vector& parameters) -> TypePtr + auto SpirvConstantCache::BuildFunctionType(const ShaderAst::ExpressionType& retType, const std::vector& parameters) -> TypePtr { std::vector parameterTypes; parameterTypes.reserve(parameters.size()); @@ -584,7 +584,7 @@ namespace Nz }); } - auto SpirvConstantCache::BuildPointerType(const ShaderAst::BasicType& type, SpirvStorageClass storageClass) -> TypePtr + auto SpirvConstantCache::BuildPointerType(const ShaderAst::ExpressionType& type, SpirvStorageClass storageClass) -> TypePtr { return std::make_shared(Pointer{ BuildType(type), @@ -592,85 +592,22 @@ namespace Nz }); } - auto SpirvConstantCache::BuildPointerType(const ShaderAst::ShaderExpressionType& type, SpirvStorageClass storageClass) -> TypePtr + auto SpirvConstantCache::BuildPointerType(const ShaderAst::PrimitiveType& type, SpirvStorageClass storageClass) -> TypePtr { return std::make_shared(Pointer{ BuildType(type), storageClass - }); + }); } - auto SpirvConstantCache::BuildType(const ShaderAst::BasicType& type) -> TypePtr - { - return std::make_shared([&]() -> AnyType - { - switch (type) - { - case ShaderAst::BasicType::Boolean: - return Bool{}; - - case ShaderAst::BasicType::Float1: - return Float{ 32 }; - - case ShaderAst::BasicType::Int1: - return Integer{ 32, true }; - - case ShaderAst::BasicType::Float2: - case ShaderAst::BasicType::Float3: - case ShaderAst::BasicType::Float4: - case ShaderAst::BasicType::Int2: - case ShaderAst::BasicType::Int3: - case ShaderAst::BasicType::Int4: - case ShaderAst::BasicType::UInt2: - case ShaderAst::BasicType::UInt3: - case ShaderAst::BasicType::UInt4: - { - auto vecType = BuildType(ShaderAst::GetComponentType(type)); - UInt32 componentCount = ShaderAst::GetComponentCount(type); - - return Vector{ vecType, componentCount }; - } - - case ShaderAst::BasicType::Mat4x4: - return Matrix{ BuildType(ShaderAst::BasicType::Float4), 4u }; - - case ShaderAst::BasicType::UInt1: - return Integer{ 32, false }; - - case ShaderAst::BasicType::Void: - return Void{}; - - case ShaderAst::BasicType::Sampler2D: - { - auto imageType = Image{ - {}, //< qualifier - {}, //< depth - {}, //< sampled - SpirvDim::Dim2D, //< dim - SpirvImageFormat::Unknown, //< format - BuildType(ShaderAst::BasicType::Float1), //< sampledType - false, //< arrayed, - false //< multisampled - }; - - return SampledImage{ std::make_shared(imageType) }; - } - } - - throw std::runtime_error("unexpected type"); - }()); - } - - auto SpirvConstantCache::BuildType(const ShaderAst::ShaderExpressionType& type) -> TypePtr + auto SpirvConstantCache::BuildType(const ShaderAst::ExpressionType& type) -> TypePtr { return std::visit([&](auto&& arg) -> TypePtr { - using T = std::decay_t; - if constexpr (std::is_same_v) - return BuildType(arg); - else if constexpr (std::is_same_v) + return BuildType(arg); + /*else if constexpr (std::is_same_v) { - /*// Register struct members type + // Register struct members type const auto& structs = shader.GetStructs(); auto it = std::find_if(structs.begin(), structs.end(), [&](const auto& s) { return s.name == arg; }); if (it == structs.end()) @@ -688,14 +625,77 @@ namespace Nz sMembers.type = BuildType(shader, member.type); } - return std::make_shared(std::move(sType));*/ + return std::make_shared(std::move(sType)); return nullptr; } else - static_assert(AlwaysFalse::value, "non-exhaustive visitor"); + static_assert(AlwaysFalse::value, "non-exhaustive visitor");*/ }, type); } + auto SpirvConstantCache::BuildType(const ShaderAst::IdentifierType& type) -> TypePtr + { + throw std::runtime_error("unexpected type"); + } + + auto SpirvConstantCache::BuildType(const ShaderAst::PrimitiveType& type) -> TypePtr + { + return std::make_shared([&]() -> AnyType + { + switch (type) + { + case ShaderAst::PrimitiveType::Boolean: + return Bool{}; + + case ShaderAst::PrimitiveType::Float32: + return Float{ 32 }; + + case ShaderAst::PrimitiveType::Int32: + return Integer{ 32, true }; + } + + throw std::runtime_error("unexpected type"); + }()); + } + + auto SpirvConstantCache::BuildType(const ShaderAst::MatrixType& type) -> TypePtr + { + return std::make_shared( + Matrix{ + BuildType(ShaderAst::VectorType { + UInt32(type.rowCount), type.type + }), + UInt32(type.columnCount) + }); + } + + auto SpirvConstantCache::BuildType(const ShaderAst::NoType& type) -> TypePtr + { + return std::make_shared(Void{}); + } + + auto SpirvConstantCache::BuildType(const ShaderAst::SamplerType& type) -> TypePtr + { + //TODO + auto imageType = Image{ + {}, //< qualifier + {}, //< depth + {}, //< sampled + SpirvDim::Dim2D, //< dim + SpirvImageFormat::Unknown, //< format + BuildType(ShaderAst::PrimitiveType::Float32), //< sampledType + false, //< arrayed, + false //< multisampled + }; + + return std::make_shared(SampledImage{ std::make_shared(imageType) }); + } + + auto SpirvConstantCache::BuildType(const ShaderAst::VectorType& type) -> TypePtr + { + return std::make_shared(Vector{ BuildType(type.type), UInt32(type.componentCount) }); + } + void SpirvConstantCache::Write(const AnyConstant& constant, UInt32 resultId, SpirvSection& constants) { std::visit([&](auto&& arg) diff --git a/src/Nazara/Shader/SpirvWriter.cpp b/src/Nazara/Shader/SpirvWriter.cpp index eb52edeca..fb1ad3725 100644 --- a/src/Nazara/Shader/SpirvWriter.cpp +++ b/src/Nazara/Shader/SpirvWriter.cpp @@ -29,7 +29,7 @@ namespace Nz { public: using ExtInstList = std::unordered_set; - using LocalContainer = std::unordered_set; + using LocalContainer = std::unordered_set; using FunctionContainer = std::vector>; PreVisitor(ShaderAst::AstCache* cache, const SpirvWriter::States& conditions, SpirvConstantCache& constantCache) : @@ -81,7 +81,7 @@ namespace Nz { funcs.emplace_back(node); - std::vector parameterTypes; + std::vector parameterTypes; for (auto& parameter : node.parameters) parameterTypes.push_back(parameter.type); @@ -92,8 +92,17 @@ namespace Nz void Visit(ShaderAst::DeclareStructStatement& node) override { - for (auto& field : node.description.members) - m_constantCache.Register(*SpirvConstantCache::BuildType(field.type)); + SpirvConstantCache::Structure sType; + sType.name = node.description.name; + + for (const auto& [name, attribute, type] : node.description.members) + { + auto& sMembers = sType.members.emplace_back(); + sMembers.name = name; + sMembers.type = SpirvConstantCache::BuildType(type); + } + + m_constantCache.Register(SpirvConstantCache::Type{ std::move(sType) }); } void Visit(ShaderAst::DeclareVariableStatement& node) override @@ -137,26 +146,26 @@ namespace Nz }; template - constexpr ShaderAst::BasicType GetBasicType() + constexpr ShaderAst::PrimitiveType GetBasicType() { if constexpr (std::is_same_v) - return ShaderAst::BasicType::Boolean; + return ShaderAst::PrimitiveType::Boolean; else if constexpr (std::is_same_v) - return(ShaderAst::BasicType::Float1); + return(ShaderAst::PrimitiveType::Float32); else if constexpr (std::is_same_v) - return(ShaderAst::BasicType::Int1); + return(ShaderAst::PrimitiveType::Int32); else if constexpr (std::is_same_v) - return(ShaderAst::BasicType::Float2); + return(ShaderAst::PrimitiveType::Float2); else if constexpr (std::is_same_v) - return(ShaderAst::BasicType::Float3); + return(ShaderAst::PrimitiveType::Float3); else if constexpr (std::is_same_v) - return(ShaderAst::BasicType::Float4); + return(ShaderAst::PrimitiveType::Float4); else if constexpr (std::is_same_v) - return(ShaderAst::BasicType::Int2); + return(ShaderAst::PrimitiveType::Int2); else if constexpr (std::is_same_v) - return(ShaderAst::BasicType::Int3); + return(ShaderAst::PrimitiveType::Int3); else if constexpr (std::is_same_v) - return(ShaderAst::BasicType::Int4); + return(ShaderAst::PrimitiveType::Int4); else static_assert(AlwaysFalse::value, "unhandled type"); } @@ -394,7 +403,7 @@ namespace Nz if (!state.functionBlocks.back().IsTerminated()) { - assert(func.returnType == ShaderAst::ShaderExpressionType(ShaderAst::BasicType::Void)); + assert(func.returnType == ShaderAst::ExpressionType{ ShaderAst::NoType{} }); state.functionBlocks.back().Append(SpirvOp::OpReturn); } @@ -537,12 +546,12 @@ namespace Nz return it.value(); } - UInt32 SpirvWriter::GetPointerTypeId(const ShaderAst::ShaderExpressionType& type, SpirvStorageClass storageClass) const + UInt32 SpirvWriter::GetPointerTypeId(const ShaderAst::ExpressionType& type, SpirvStorageClass storageClass) const { return m_currentState->constantTypeCache.GetId(*SpirvConstantCache::BuildPointerType(type, storageClass)); } - UInt32 SpirvWriter::GetTypeId(const ShaderAst::ShaderExpressionType& type) const + UInt32 SpirvWriter::GetTypeId(const ShaderAst::ExpressionType& type) const { return m_currentState->constantTypeCache.GetId(*SpirvConstantCache::BuildType(type)); } @@ -643,12 +652,12 @@ namespace Nz return m_currentState->constantTypeCache.Register({ *BuildFunctionType(functionNode) }); } - UInt32 SpirvWriter::RegisterPointerType(ShaderAst::ShaderExpressionType type, SpirvStorageClass storageClass) + UInt32 SpirvWriter::RegisterPointerType(ShaderAst::ExpressionType type, SpirvStorageClass storageClass) { return m_currentState->constantTypeCache.Register(*SpirvConstantCache::BuildPointerType(type, storageClass)); } - UInt32 SpirvWriter::RegisterType(ShaderAst::ShaderExpressionType type) + UInt32 SpirvWriter::RegisterType(ShaderAst::ExpressionType type) { assert(m_currentState); return m_currentState->constantTypeCache.Register(*SpirvConstantCache::BuildType(type)); @@ -662,7 +671,7 @@ namespace Nz SpirvConstantCache::TypePtr SpirvWriter::BuildFunctionType(const ShaderAst::DeclareFunctionStatement& functionNode) { - std::vector parameterTypes; + std::vector parameterTypes; parameterTypes.reserve(functionNode.parameters.size()); for (const auto& parameter : functionNode.parameters) From e4aabf309eb413cc9b873d2151ee6e4d36ad5730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 31 Mar 2021 11:13:37 +0200 Subject: [PATCH 089/278] Renderer: Replace ShaderStage by ShaderModule (a module can handle multiple stages) --- include/Nazara/Graphics/MaterialSettings.hpp | 2 +- include/Nazara/Graphics/UberShader.hpp | 13 +- include/Nazara/OpenGLRenderer.hpp | 2 +- .../Nazara/OpenGLRenderer/OpenGLDevice.hpp | 4 +- .../OpenGLRenderer/OpenGLShaderModule.hpp | 45 ++++++ ...ShaderStage.inl => OpenGLShaderModule.inl} | 6 +- .../OpenGLRenderer/OpenGLShaderStage.hpp | 46 ------ include/Nazara/Renderer.hpp | 2 +- include/Nazara/Renderer/RenderDevice.hpp | 8 +- include/Nazara/Renderer/RenderPipeline.hpp | 2 +- include/Nazara/Renderer/RenderStates.hpp | 2 +- .../{ShaderStage.hpp => ShaderModule.hpp} | 10 +- .../Nazara/VulkanRenderer/VulkanDevice.hpp | 4 +- .../VulkanRenderer/VulkanShaderStage.hpp | 4 +- src/Nazara/Graphics/MaterialPipeline.cpp | 2 +- src/Nazara/Graphics/UberShader.cpp | 9 +- src/Nazara/OpenGLRenderer/OpenGLDevice.cpp | 10 +- .../OpenGLRenderer/OpenGLRenderPipeline.cpp | 9 +- .../OpenGLRenderer/OpenGLShaderModule.cpp | 136 ++++++++++++++++++ .../OpenGLRenderer/OpenGLShaderStage.cpp | 94 ------------ src/Nazara/Renderer/RenderDevice.cpp | 4 +- .../{ShaderStage.cpp => ShaderModule.cpp} | 4 +- src/Nazara/VulkanRenderer/VulkanDevice.cpp | 4 +- .../VulkanRenderer/VulkanRenderPipeline.cpp | 2 +- .../VulkanRenderer/VulkanShaderStage.cpp | 9 +- 25 files changed, 235 insertions(+), 198 deletions(-) create mode 100644 include/Nazara/OpenGLRenderer/OpenGLShaderModule.hpp rename include/Nazara/OpenGLRenderer/{OpenGLShaderStage.inl => OpenGLShaderModule.inl} (65%) delete mode 100644 include/Nazara/OpenGLRenderer/OpenGLShaderStage.hpp rename include/Nazara/Renderer/{ShaderStage.hpp => ShaderModule.hpp} (68%) create mode 100644 src/Nazara/OpenGLRenderer/OpenGLShaderModule.cpp delete mode 100644 src/Nazara/OpenGLRenderer/OpenGLShaderStage.cpp rename src/Nazara/Renderer/{ShaderStage.cpp => ShaderModule.cpp} (73%) diff --git a/include/Nazara/Graphics/MaterialSettings.hpp b/include/Nazara/Graphics/MaterialSettings.hpp index 272e478df..52c57f2af 100644 --- a/include/Nazara/Graphics/MaterialSettings.hpp +++ b/include/Nazara/Graphics/MaterialSettings.hpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/Nazara/Graphics/UberShader.hpp b/include/Nazara/Graphics/UberShader.hpp index a4b9299a2..d400ade68 100644 --- a/include/Nazara/Graphics/UberShader.hpp +++ b/include/Nazara/Graphics/UberShader.hpp @@ -10,26 +10,27 @@ #include #include #include -#include +#include #include namespace Nz { - class ShaderStage; + class ShaderModule; class NAZARA_GRAPHICS_API UberShader { public: - UberShader(ShaderAst shaderAst); + UberShader(ShaderStageType shaderStage, ShaderAst::StatementPtr shaderAst); ~UberShader() = default; UInt64 GetConditionFlagByName(const std::string_view& condition) const; - const std::shared_ptr& Get(UInt64 combination); + const std::shared_ptr& Get(UInt64 combination); private: - std::unordered_map> m_combinations; - ShaderAst m_shaderAst; + std::unordered_map> m_combinations; + ShaderAst::StatementPtr m_shaderAst; + ShaderStageType m_shaderStage; UInt64 m_combinationMask; }; } diff --git a/include/Nazara/OpenGLRenderer.hpp b/include/Nazara/OpenGLRenderer.hpp index f60b0ee85..ffcb93277 100644 --- a/include/Nazara/OpenGLRenderer.hpp +++ b/include/Nazara/OpenGLRenderer.hpp @@ -44,7 +44,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp b/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp index 1161e5667..2597b3f91 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp @@ -38,8 +38,8 @@ namespace Nz std::shared_ptr InstantiateRenderPass(std::vector attachments, std::vector subpassDescriptions, std::vector subpassDependencies) override; std::shared_ptr InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override; std::shared_ptr InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) override; - std::shared_ptr InstantiateShaderStage(const ShaderAst& shaderAst, const ShaderWriter::States& states) override; - std::shared_ptr InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) override; + std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states) override; + std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize) override; std::shared_ptr InstantiateTexture(const TextureInfo& params) override; std::shared_ptr InstantiateTextureSampler(const TextureSamplerInfo& params) override; diff --git a/include/Nazara/OpenGLRenderer/OpenGLShaderModule.hpp b/include/Nazara/OpenGLRenderer/OpenGLShaderModule.hpp new file mode 100644 index 000000000..6e0426702 --- /dev/null +++ b/include/Nazara/OpenGLRenderer/OpenGLShaderModule.hpp @@ -0,0 +1,45 @@ +// Copyright (C) 2020 Jérôme Leclercq +// This file is part of the "Nazara Engine - OpenGL Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_OPENGLRENDERER_OPENGLSHADERMODULE_HPP +#define NAZARA_OPENGLRENDERER_OPENGLSHADERMODULE_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + class NAZARA_OPENGLRENDERER_API OpenGLShaderModule : public ShaderModule + { + public: + OpenGLShaderModule(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states); + OpenGLShaderModule(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize); + OpenGLShaderModule(const OpenGLShaderModule&) = delete; + OpenGLShaderModule(OpenGLShaderModule&&) noexcept = default; + ~OpenGLShaderModule() = default; + + inline const std::vector& GetShaders() const; + + OpenGLShaderModule& operator=(const OpenGLShaderModule&) = delete; + OpenGLShaderModule& operator=(OpenGLShaderModule&&) noexcept = default; + + private: + void Create(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states); + + static void CheckCompilationStatus(GL::Shader& shader); + + std::vector m_shaders; + }; +} + +#include + +#endif // NAZARA_OPENGLRENDERER_OPENGLSHADERSTAGE_HPP diff --git a/include/Nazara/OpenGLRenderer/OpenGLShaderStage.inl b/include/Nazara/OpenGLRenderer/OpenGLShaderModule.inl similarity index 65% rename from include/Nazara/OpenGLRenderer/OpenGLShaderStage.inl rename to include/Nazara/OpenGLRenderer/OpenGLShaderModule.inl index 6d1ccb62f..7cf01b6f7 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLShaderStage.inl +++ b/include/Nazara/OpenGLRenderer/OpenGLShaderModule.inl @@ -2,14 +2,14 @@ // This file is part of the "Nazara Engine - OpenGL Renderer" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include namespace Nz { - inline const GL::Shader& OpenGLShaderStage::GetShader() const + inline const std::vector& OpenGLShaderModule::GetShaders() const { - return m_shader; + return m_shaders; } } diff --git a/include/Nazara/OpenGLRenderer/OpenGLShaderStage.hpp b/include/Nazara/OpenGLRenderer/OpenGLShaderStage.hpp deleted file mode 100644 index d917f6f14..000000000 --- a/include/Nazara/OpenGLRenderer/OpenGLShaderStage.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (C) 2020 Jérôme Leclercq -// This file is part of the "Nazara Engine - OpenGL Renderer" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_OPENGLRENDERER_OPENGLSHADERSTAGE_HPP -#define NAZARA_OPENGLRENDERER_OPENGLSHADERSTAGE_HPP - -#include -#include -#include -#include -#include -#include -#include - -namespace Nz -{ - class ShaderAst; - - class NAZARA_OPENGLRENDERER_API OpenGLShaderStage : public ShaderStage - { - public: - OpenGLShaderStage(OpenGLDevice& device, const ShaderAst& shaderAst, const ShaderWriter::States& states); - OpenGLShaderStage(OpenGLDevice& device, ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize); - OpenGLShaderStage(const OpenGLShaderStage&) = delete; - OpenGLShaderStage(OpenGLShaderStage&&) noexcept = default; - ~OpenGLShaderStage() = default; - - inline const GL::Shader& GetShader() const; - - OpenGLShaderStage& operator=(const OpenGLShaderStage&) = delete; - OpenGLShaderStage& operator=(OpenGLShaderStage&&) noexcept = default; - - private: - void CheckCompilationStatus(); - void Create(OpenGLDevice& device, const ShaderAst& shaderAst, const ShaderWriter::States& states); - - GL::Shader m_shader; - }; -} - -#include - -#endif // NAZARA_OPENGLRENDERER_OPENGLSHADERSTAGE_HPP diff --git a/include/Nazara/Renderer.hpp b/include/Nazara/Renderer.hpp index 3d3a8e027..2714ea822 100644 --- a/include/Nazara/Renderer.hpp +++ b/include/Nazara/Renderer.hpp @@ -53,7 +53,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/Nazara/Renderer/RenderDevice.hpp b/include/Nazara/Renderer/RenderDevice.hpp index feb3a153c..85cd03541 100644 --- a/include/Nazara/Renderer/RenderDevice.hpp +++ b/include/Nazara/Renderer/RenderDevice.hpp @@ -25,7 +25,7 @@ namespace Nz { class CommandPool; - class ShaderStage; + class ShaderModule; class NAZARA_RENDERER_API RenderDevice { @@ -39,9 +39,9 @@ namespace Nz virtual std::shared_ptr InstantiateRenderPass(std::vector attachments, std::vector subpassDescriptions, std::vector subpassDependencies) = 0; virtual std::shared_ptr InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) = 0; virtual std::shared_ptr InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) = 0; - virtual std::shared_ptr InstantiateShaderStage(const ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states) = 0; - virtual std::shared_ptr InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) = 0; - std::shared_ptr InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const std::filesystem::path& sourcePath); + virtual std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states) = 0; + virtual std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize) = 0; + std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const std::filesystem::path& sourcePath); virtual std::shared_ptr InstantiateTexture(const TextureInfo& params) = 0; virtual std::shared_ptr InstantiateTextureSampler(const TextureSamplerInfo& params) = 0; }; diff --git a/include/Nazara/Renderer/RenderPipeline.hpp b/include/Nazara/Renderer/RenderPipeline.hpp index 59981f831..fa73b60e4 100644 --- a/include/Nazara/Renderer/RenderPipeline.hpp +++ b/include/Nazara/Renderer/RenderPipeline.hpp @@ -22,7 +22,7 @@ namespace Nz }; std::shared_ptr pipelineLayout; - std::vector> shaderStages; + std::vector> shaderModules; std::vector vertexBuffers; }; diff --git a/include/Nazara/Renderer/RenderStates.hpp b/include/Nazara/Renderer/RenderStates.hpp index d04a2fe1e..ad5dda7ec 100644 --- a/include/Nazara/Renderer/RenderStates.hpp +++ b/include/Nazara/Renderer/RenderStates.hpp @@ -15,7 +15,7 @@ namespace Nz { - class ShaderStage; + class ShaderModule; struct RenderStates { diff --git a/include/Nazara/Renderer/ShaderStage.hpp b/include/Nazara/Renderer/ShaderModule.hpp similarity index 68% rename from include/Nazara/Renderer/ShaderStage.hpp rename to include/Nazara/Renderer/ShaderModule.hpp index c24c287ad..30608212a 100644 --- a/include/Nazara/Renderer/ShaderStage.hpp +++ b/include/Nazara/Renderer/ShaderModule.hpp @@ -4,8 +4,8 @@ #pragma once -#ifndef NAZARA_RENDERER_SHADERSTAGE_HPP -#define NAZARA_RENDERER_SHADERSTAGE_HPP +#ifndef NAZARA_RENDERER_SHADERMODULE_HPP +#define NAZARA_RENDERER_SHADERMODULE_HPP #include #include @@ -13,11 +13,11 @@ namespace Nz { - class NAZARA_RENDERER_API ShaderStage + class NAZARA_RENDERER_API ShaderModule { public: - ShaderStage() = default; - virtual ~ShaderStage(); + ShaderModule() = default; + virtual ~ShaderModule(); }; } diff --git a/include/Nazara/VulkanRenderer/VulkanDevice.hpp b/include/Nazara/VulkanRenderer/VulkanDevice.hpp index ae3439685..753488bf4 100644 --- a/include/Nazara/VulkanRenderer/VulkanDevice.hpp +++ b/include/Nazara/VulkanRenderer/VulkanDevice.hpp @@ -29,8 +29,8 @@ namespace Nz std::shared_ptr InstantiateRenderPass(std::vector attachments, std::vector subpassDescriptions, std::vector subpassDependencies) override; std::shared_ptr InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override; std::shared_ptr InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) override; - std::shared_ptr InstantiateShaderStage(const ShaderAst& shaderAst, const ShaderWriter::States& states) override; - std::shared_ptr InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) override; + std::shared_ptr InstantiateShaderModule(const ShaderAst& shaderAst, const ShaderWriter::States& states) override; + std::shared_ptr InstantiateShaderModule(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) override; std::shared_ptr InstantiateTexture(const TextureInfo& params) override; std::shared_ptr InstantiateTextureSampler(const TextureSamplerInfo& params) override; diff --git a/include/Nazara/VulkanRenderer/VulkanShaderStage.hpp b/include/Nazara/VulkanRenderer/VulkanShaderStage.hpp index a82ed6894..b019fb90c 100644 --- a/include/Nazara/VulkanRenderer/VulkanShaderStage.hpp +++ b/include/Nazara/VulkanRenderer/VulkanShaderStage.hpp @@ -9,14 +9,14 @@ #include #include -#include +#include #include #include #include namespace Nz { - class NAZARA_VULKANRENDERER_API VulkanShaderStage : public ShaderStage + class NAZARA_VULKANRENDERER_API VulkanShaderStage : public ShaderModule { public: VulkanShaderStage() = default; diff --git a/src/Nazara/Graphics/MaterialPipeline.cpp b/src/Nazara/Graphics/MaterialPipeline.cpp index 938563bee..3ed157abc 100644 --- a/src/Nazara/Graphics/MaterialPipeline.cpp +++ b/src/Nazara/Graphics/MaterialPipeline.cpp @@ -51,7 +51,7 @@ namespace Nz for (const auto& shaderEntry : m_pipelineInfo.shaders) { if (shaderEntry.uberShader) - renderPipelineInfo.shaderStages.push_back(shaderEntry.uberShader->Get(shaderEntry.enabledConditions)); + renderPipelineInfo.shaderModules.push_back(shaderEntry.uberShader->Get(shaderEntry.enabledConditions)); } renderPipelineInfo.vertexBuffers = vertexBuffers; diff --git a/src/Nazara/Graphics/UberShader.cpp b/src/Nazara/Graphics/UberShader.cpp index fc2364a24..2e211d07c 100644 --- a/src/Nazara/Graphics/UberShader.cpp +++ b/src/Nazara/Graphics/UberShader.cpp @@ -11,8 +11,9 @@ namespace Nz { - UberShader::UberShader(ShaderAst::StatementPtr shaderAst) : - m_shaderAst(std::move(shaderAst)) + UberShader::UberShader(ShaderStageType shaderStage, ShaderAst::StatementPtr shaderAst) : + m_shaderAst(std::move(shaderAst)), + m_shaderStage(shaderStage) { //std::size_t conditionCount = m_shaderAst.GetConditionCount(); std::size_t conditionCount = 0; @@ -34,7 +35,7 @@ namespace Nz return 0; } - const std::shared_ptr& UberShader::Get(UInt64 combination) + const std::shared_ptr& UberShader::Get(UInt64 combination) { combination &= m_combinationMask; @@ -44,7 +45,7 @@ namespace Nz ShaderWriter::States states; states.enabledConditions = combination; - std::shared_ptr stage = Graphics::Instance()->GetRenderDevice().InstantiateShaderStage(m_shaderAst, std::move(states)); + std::shared_ptr stage = Graphics::Instance()->GetRenderDevice().InstantiateShaderModule(m_shaderStage, m_shaderAst, std::move(states)); it = m_combinations.emplace(combination, std::move(stage)).first; } diff --git a/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp b/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp index 205099232..a6425aa9f 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include @@ -80,14 +80,14 @@ namespace Nz return std::make_shared(std::move(pipelineLayoutInfo)); } - std::shared_ptr OpenGLDevice::InstantiateShaderStage(const ShaderAst& shaderAst, const ShaderWriter::States& states) + std::shared_ptr OpenGLDevice::InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states) { - return std::make_shared(*this, shaderAst, states); + return std::make_shared(*this, shaderStages, shaderAst, states); } - std::shared_ptr OpenGLDevice::InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) + std::shared_ptr OpenGLDevice::InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize) { - return std::make_shared(*this, type, lang, source, sourceSize); + return std::make_shared(*this, shaderStages, lang, source, sourceSize); } std::shared_ptr OpenGLDevice::InstantiateTexture(const TextureInfo& params) diff --git a/src/Nazara/OpenGLRenderer/OpenGLRenderPipeline.cpp b/src/Nazara/OpenGLRenderer/OpenGLRenderPipeline.cpp index e1511a847..f6703391f 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLRenderPipeline.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLRenderPipeline.cpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include #include @@ -21,10 +21,11 @@ namespace Nz if (!m_program.Create(device)) throw std::runtime_error("failed to create program"); - for (const auto& shaderStagePtr : m_pipelineInfo.shaderStages) + for (const auto& shaderModulePtr : m_pipelineInfo.shaderModules) { - OpenGLShaderStage& shaderStage = static_cast(*shaderStagePtr); - m_program.AttachShader(shaderStage.GetShader().GetObjectId()); + OpenGLShaderModule& shaderModule = static_cast(*shaderModulePtr); + for (const GL::Shader& shader : shaderModule.GetShaders()) + m_program.AttachShader(shader.GetObjectId()); } m_program.Link(); diff --git a/src/Nazara/OpenGLRenderer/OpenGLShaderModule.cpp b/src/Nazara/OpenGLRenderer/OpenGLShaderModule.cpp new file mode 100644 index 000000000..8fe618231 --- /dev/null +++ b/src/Nazara/OpenGLRenderer/OpenGLShaderModule.cpp @@ -0,0 +1,136 @@ +// Copyright (C) 2020 Jérôme Leclercq +// This file is part of the "Nazara Engine - OpenGL Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + OpenGLShaderModule::OpenGLShaderModule(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states) + { + NazaraAssert(shaderStages != 0, "at least one shader stage must be specified"); + Create(device, shaderStages, shaderAst, states); + } + + OpenGLShaderModule::OpenGLShaderModule(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize) + { + NazaraAssert(shaderStages != 0, "at least one shader stage must be specified"); + + switch (lang) + { + case ShaderLanguage::GLSL: + { + for (std::size_t i = 0; i < ShaderStageTypeCount; ++i) + { + ShaderStageType shaderStage = static_cast(i); + if (shaderStages.Test(shaderStage)) + { + NazaraAssert(shaderStages == shaderStage, "when supplying GLSL, only one shader stage type can be specified"); + + GL::Shader shader; + if (!shader.Create(device, ToOpenGL(shaderStage))) + throw std::runtime_error("failed to create shader"); //< TODO: Handle error message + + shader.SetSource(reinterpret_cast(source), GLint(sourceSize)); + shader.Compile(); + CheckCompilationStatus(shader); + + m_shaders.emplace_back(std::move(shader)); + break; + } + } + + break; + } + + case ShaderLanguage::NazaraBinary: + { + auto shader = ShaderAst::UnserializeShader(source, sourceSize); + Create(device, shaderStages, shader, {}); + break; + } + + case ShaderLanguage::NazaraShader: + { + std::vector tokens = Nz::ShaderLang::Tokenize(std::string_view(static_cast(source), sourceSize)); + + Nz::ShaderLang::Parser parser; + Nz::ShaderAst::StatementPtr shaderAst = parser.Parse(tokens); + Create(device, shaderStages, shaderAst, {}); + break; + } + + case ShaderLanguage::SpirV: + { + throw std::runtime_error("TODO"); + + // TODO: Parse SpirV to extract entry points? + + /*if (!device.GetReferenceContext().IsExtensionSupported(GL::Extension::SpirV)) + throw std::runtime_error("SpirV is not supported by this OpenGL implementation"); + + m_shader.SetBinarySource(GL_SHADER_BINARY_FORMAT_SPIR_V_ARB, source, GLsizei(sourceSize)); + m_shader.SpecializeShader("main", 0U, nullptr, nullptr);*/ + break; + } + + default: + throw std::runtime_error("Unsupported shader language"); + } + } + + void OpenGLShaderModule::CheckCompilationStatus(GL::Shader& shader) + { + std::string errorLog; + if (!shader.GetCompilationStatus(&errorLog)) + throw std::runtime_error("Failed to compile shader: " + errorLog); + } + + void OpenGLShaderModule::Create(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states) + { + const auto& context = device.GetReferenceContext(); + const auto& contextParams = context.GetParams(); + + GlslWriter::Environment env; + env.glES = (contextParams.type == GL::ContextType::OpenGL_ES); + env.glMajorVersion = contextParams.glMajorVersion; + env.glMinorVersion = contextParams.glMinorVersion; + env.extCallback = [&](const std::string_view& ext) + { + return context.IsExtensionSupported(std::string(ext)); + }; + env.flipYPosition = true; + + GlslWriter writer; + writer.SetEnv(env); + + for (std::size_t i = 0; i < ShaderStageTypeCount; ++i) + { + ShaderStageType shaderStage = static_cast(i); + if (shaderStages.Test(shaderStage)) + { + GL::Shader shader; + + if (!shader.Create(device, ToOpenGL(shaderStage))) + throw std::runtime_error("failed to create shader"); //< TODO: Handle error message + + std::string code = writer.Generate(shaderStage, shaderAst, states); + + shader.SetSource(code.data(), code.size()); + shader.Compile(); + + CheckCompilationStatus(shader); + + m_shaders.emplace_back(std::move(shader)); + } + } + } +} diff --git a/src/Nazara/OpenGLRenderer/OpenGLShaderStage.cpp b/src/Nazara/OpenGLRenderer/OpenGLShaderStage.cpp deleted file mode 100644 index 0f24f524f..000000000 --- a/src/Nazara/OpenGLRenderer/OpenGLShaderStage.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (C) 2020 Jérôme Leclercq -// This file is part of the "Nazara Engine - OpenGL Renderer" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Nz -{ - OpenGLShaderStage::OpenGLShaderStage(OpenGLDevice& device, const ShaderAst& shaderAst, const ShaderWriter::States& states) - { - if (!m_shader.Create(device, ToOpenGL(shaderAst.GetStage()))) - throw std::runtime_error("failed to create shader"); //< TODO: Handle error message - - Create(device, shaderAst, states); - CheckCompilationStatus(); - } - - OpenGLShaderStage::OpenGLShaderStage(OpenGLDevice& device, ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) - { - if (!m_shader.Create(device, ToOpenGL(type))) - throw std::runtime_error("failed to create shader"); //< TODO: Handle error message - - switch (lang) - { - case ShaderLanguage::GLSL: - m_shader.SetSource(reinterpret_cast(source), GLint(sourceSize)); - m_shader.Compile(); - break; - - case ShaderLanguage::NazaraBinary: - { - auto shader = UnserializeShader(source, sourceSize); - if (shader.GetStage() != type) - throw std::runtime_error("incompatible shader stage"); - - Create(device, shader, {}); - break; - } - - case ShaderLanguage::SpirV: - { - if (!device.GetReferenceContext().IsExtensionSupported(GL::Extension::SpirV)) - throw std::runtime_error("SpirV is not supported by this OpenGL implementation"); - - m_shader.SetBinarySource(GL_SHADER_BINARY_FORMAT_SPIR_V_ARB, source, GLsizei(sourceSize)); - m_shader.SpecializeShader("main", 0U, nullptr, nullptr); - break; - } - - default: - throw std::runtime_error("Unsupported shader language"); - } - - CheckCompilationStatus(); - } - - void OpenGLShaderStage::CheckCompilationStatus() - { - std::string errorLog; - if (!m_shader.GetCompilationStatus(&errorLog)) - throw std::runtime_error("Failed to compile shader: " + errorLog); - } - - void OpenGLShaderStage::Create(OpenGLDevice& device, const ShaderAst& shaderAst, const ShaderWriter::States& states) - { - const auto& context = device.GetReferenceContext(); - const auto& contextParams = context.GetParams(); - - GlslWriter::Environment env; - env.glES = (contextParams.type == GL::ContextType::OpenGL_ES); - env.glMajorVersion = contextParams.glMajorVersion; - env.glMinorVersion = contextParams.glMinorVersion; - env.extCallback = [&](const std::string_view& ext) - { - return context.IsExtensionSupported(std::string(ext)); - }; - env.flipYPosition = true; - - GlslWriter writer; - writer.SetEnv(env); - - std::string code = writer.Generate(shaderAst, states); - - m_shader.SetSource(code.data(), code.size()); - m_shader.Compile(); - } -} diff --git a/src/Nazara/Renderer/RenderDevice.cpp b/src/Nazara/Renderer/RenderDevice.cpp index 0a56e5f46..0d71e5e66 100644 --- a/src/Nazara/Renderer/RenderDevice.cpp +++ b/src/Nazara/Renderer/RenderDevice.cpp @@ -11,7 +11,7 @@ namespace Nz { RenderDevice::~RenderDevice() = default; - std::shared_ptr RenderDevice::InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const std::filesystem::path& sourcePath) + std::shared_ptr RenderDevice::InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const std::filesystem::path& sourcePath) { File file(sourcePath); if (!file.Open(OpenMode_ReadOnly | OpenMode_Text)) @@ -29,6 +29,6 @@ namespace Nz return {}; } - return InstantiateShaderStage(type, lang, source.data(), source.size()); + return InstantiateShaderModule(shaderStages, lang, source.data(), source.size()); } } diff --git a/src/Nazara/Renderer/ShaderStage.cpp b/src/Nazara/Renderer/ShaderModule.cpp similarity index 73% rename from src/Nazara/Renderer/ShaderStage.cpp rename to src/Nazara/Renderer/ShaderModule.cpp index 1b2b87813..9994c1eb2 100644 --- a/src/Nazara/Renderer/ShaderStage.cpp +++ b/src/Nazara/Renderer/ShaderModule.cpp @@ -2,10 +2,10 @@ // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include namespace Nz { - ShaderStage::~ShaderStage() = default; + ShaderModule::~ShaderModule() = default; } diff --git a/src/Nazara/VulkanRenderer/VulkanDevice.cpp b/src/Nazara/VulkanRenderer/VulkanDevice.cpp index 0de3132a5..1311398af 100644 --- a/src/Nazara/VulkanRenderer/VulkanDevice.cpp +++ b/src/Nazara/VulkanRenderer/VulkanDevice.cpp @@ -51,7 +51,7 @@ namespace Nz return pipelineLayout; } - std::shared_ptr VulkanDevice::InstantiateShaderStage(const ShaderAst& shaderAst, const ShaderWriter::States& states) + std::shared_ptr VulkanDevice::InstantiateShaderModule(const ShaderAst& shaderAst, const ShaderWriter::States& states) { auto stage = std::make_shared(); if (!stage->Create(*this, shaderAst, states)) @@ -60,7 +60,7 @@ namespace Nz return stage; } - std::shared_ptr VulkanDevice::InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) + std::shared_ptr VulkanDevice::InstantiateShaderModule(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) { auto stage = std::make_shared(); if (!stage->Create(*this, type, lang, source, sourceSize)) diff --git a/src/Nazara/VulkanRenderer/VulkanRenderPipeline.cpp b/src/Nazara/VulkanRenderer/VulkanRenderPipeline.cpp index 72430f5b5..ec7295c19 100644 --- a/src/Nazara/VulkanRenderer/VulkanRenderPipeline.cpp +++ b/src/Nazara/VulkanRenderer/VulkanRenderPipeline.cpp @@ -164,7 +164,7 @@ namespace Nz { std::vector shaderStageCreateInfos; - for (auto&& stagePtr : pipelineInfo.shaderStages) + for (auto&& stagePtr : pipelineInfo.shaderModules) { Nz::VulkanShaderStage& vulkanStage = *static_cast(stagePtr.get()); diff --git a/src/Nazara/VulkanRenderer/VulkanShaderStage.cpp b/src/Nazara/VulkanRenderer/VulkanShaderStage.cpp index 2162a1c64..403699798 100644 --- a/src/Nazara/VulkanRenderer/VulkanShaderStage.cpp +++ b/src/Nazara/VulkanRenderer/VulkanShaderStage.cpp @@ -20,14 +20,7 @@ namespace Nz writer.SetEnv(env); std::vector code = writer.Generate(shader, states); - - if (!m_shaderModule.Create(device, code.data(), code.size() * sizeof(UInt32))) - { - NazaraError("Failed to create shader module"); - return false; - } - - return true; + return Create(device, m_stage, ShaderLanguage::SpirV, code.data(), code.size() * sizeof(UInt32)); } bool VulkanShaderStage::Create(Vk::Device& device, ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) From 5a63eb4d9750126b59826d3edece4587bcf1eb53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 31 Mar 2021 11:14:01 +0200 Subject: [PATCH 090/278] Update RenderTest demo with shaderlang --- examples/RenderTest/main.cpp | 74 ++++++++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 12 deletions(-) diff --git a/examples/RenderTest/main.cpp b/examples/RenderTest/main.cpp index 129a95031..d74fb15b5 100644 --- a/examples/RenderTest/main.cpp +++ b/examples/RenderTest/main.cpp @@ -8,6 +8,64 @@ #include #include +const char shaderSource[] = R"( +[[layout(std140)]] +struct Data +{ + projectionMatrix: mat4, + worldMatrix: mat4, + viewMatrix: mat4 +} + +external +{ + [[binding(0), layout(std140)]] viewerData: uniform, + [[binding(1)]] tex: sampler2D +} + +struct VertIn +{ + [[location(0)]] position: vec3, + [[location(1)]] normal: vec3, + [[location(2)]] uv: vec2 +} + +struct VertOut +{ + [[builtin(position)]] position: vec4, + [[location(0)]] normal: vec3, + [[location(1)]] uv: vec2 +} + +struct FragOut +{ + [[location(0)]] color: vec4 +} + +[[entry(frag)]] +fn main(fragIn: VertOut) -> FragOut +{ + let lightDir: vec3 = vec3(0.0, -0.707, 0.707); + let lightFactor: f32 = dot(fragIn.normal, lightDir); + + let fragOut: FragOut; + fragOut.color = lightFactor * tex.Sample(fragIn.uv); + + return fragOut; +} + +[[entry(vert)]] +fn main(vertIn: VertIn) -> VertOut +{ + let vertOut: VertOut; + vertOut.position = viewerData.projectionMatrix * viewerData.viewMatrix * viewerData.worldMatrix * vec4(vertIn.position, 1.0); + vertOut.normal = vertIn.normal; + vertOut.uv = vertIn.uv; + + return vertOut; +} +)"; + int main() { Nz::Renderer::Config rendererConfig; @@ -34,17 +92,10 @@ int main() std::shared_ptr device = window.GetRenderDevice(); - auto fragmentShader = device->InstantiateShaderStage(Nz::ShaderStageType::Fragment, Nz::ShaderLanguage::NazaraBinary, "frag.shader"); - if (!fragmentShader) + auto fragVertShader = device->InstantiateShaderModule(Nz::ShaderStageType::Fragment | Nz::ShaderStageType::Vertex, Nz::ShaderLanguage::NazaraShader, shaderSource, sizeof(shaderSource)); + if (!fragVertShader) { - std::cout << "Failed to instantiate fragment shader" << std::endl; - return __LINE__; - } - - auto vertexShader = device->InstantiateShaderStage(Nz::ShaderStageType::Vertex, Nz::ShaderLanguage::NazaraBinary, "vert.shader"); - if (!vertexShader) - { - std::cout << "Failed to instantiate fragment shader" << std::endl; + std::cout << "Failed to instantiate shader" << std::endl; return __LINE__; } @@ -146,8 +197,7 @@ int main() pipelineInfo.pipelineLayout = renderPipelineLayout; pipelineInfo.depthBuffer = true; - pipelineInfo.shaderStages.emplace_back(fragmentShader); - pipelineInfo.shaderStages.emplace_back(vertexShader); + pipelineInfo.shaderModules.emplace_back(fragVertShader); auto& vertexBuffer = pipelineInfo.vertexBuffers.emplace_back(); vertexBuffer.binding = 0; From 09df5f389e0ddb6474c15889eca9394fd248f6b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sun, 4 Apr 2021 20:29:23 +0200 Subject: [PATCH 091/278] Shader: Add SpirvDecoder --- include/Nazara/Shader/SpirvDecoder.hpp | 59 +++++++++++++ include/Nazara/Shader/SpirvDecoder.inl | 16 ++++ include/Nazara/Shader/SpirvPrinter.hpp | 8 +- include/Nazara/Shader/SpirvWriter.hpp | 4 +- src/Nazara/Shader/SpirvDecoder.cpp | 87 +++++++++++++++++++ src/Nazara/Shader/SpirvPrinter.cpp | 110 ++++++------------------- 6 files changed, 194 insertions(+), 90 deletions(-) create mode 100644 include/Nazara/Shader/SpirvDecoder.hpp create mode 100644 include/Nazara/Shader/SpirvDecoder.inl create mode 100644 src/Nazara/Shader/SpirvDecoder.cpp diff --git a/include/Nazara/Shader/SpirvDecoder.hpp b/include/Nazara/Shader/SpirvDecoder.hpp new file mode 100644 index 000000000..fc7ccd935 --- /dev/null +++ b/include/Nazara/Shader/SpirvDecoder.hpp @@ -0,0 +1,59 @@ +// 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_SPIRVDECODER_HPP +#define NAZARA_SPIRVDECODER_HPP + +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + class NAZARA_SHADER_API SpirvDecoder + { + public: + SpirvDecoder() = default; + SpirvDecoder(const SpirvDecoder&) = default; + SpirvDecoder(SpirvDecoder&&) = default; + ~SpirvDecoder() = default; + + void Decode(const UInt32* codepoints, std::size_t count); + + SpirvDecoder& operator=(const SpirvDecoder&) = default; + SpirvDecoder& operator=(SpirvDecoder&&) = default; + + protected: + struct SpirvHeader; + + inline const UInt32* GetCurrentPtr() const; + + virtual bool HandleHeader(const SpirvHeader& header); + virtual bool HandleOpcode(const SpirvInstruction& instruction, UInt32 wordCount) = 0; + + std::string ReadString(); + UInt32 ReadWord(); + + struct SpirvHeader + { + UInt32 generatorId; + UInt32 bound; + UInt32 schema; + UInt32 versionNumber; + }; + + private: + const UInt32* m_currentCodepoint; + const UInt32* m_codepointEnd; + }; +} + +#include + +#endif diff --git a/include/Nazara/Shader/SpirvDecoder.inl b/include/Nazara/Shader/SpirvDecoder.inl new file mode 100644 index 000000000..aa937bd5b --- /dev/null +++ b/include/Nazara/Shader/SpirvDecoder.inl @@ -0,0 +1,16 @@ +// 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 +#include + +namespace Nz +{ + inline const UInt32* SpirvDecoder::GetCurrentPtr() const + { + return m_currentCodepoint; + } +} + +#include diff --git a/include/Nazara/Shader/SpirvPrinter.hpp b/include/Nazara/Shader/SpirvPrinter.hpp index c7c7815f7..014fce121 100644 --- a/include/Nazara/Shader/SpirvPrinter.hpp +++ b/include/Nazara/Shader/SpirvPrinter.hpp @@ -9,12 +9,13 @@ #include #include +#include #include #include namespace Nz { - class NAZARA_SHADER_API SpirvPrinter + class NAZARA_SHADER_API SpirvPrinter : SpirvDecoder { public: struct Settings; @@ -39,9 +40,8 @@ namespace Nz }; private: - void AppendInstruction(); - std::string ReadString(); - UInt32 ReadWord(); + bool HandleHeader(const SpirvHeader& header) override; + bool HandleOpcode(const SpirvInstruction& instruction, UInt32 wordCount) override; struct State; diff --git a/include/Nazara/Shader/SpirvWriter.hpp b/include/Nazara/Shader/SpirvWriter.hpp index 17ac7d023..3b770ae87 100644 --- a/include/Nazara/Shader/SpirvWriter.hpp +++ b/include/Nazara/Shader/SpirvWriter.hpp @@ -9,8 +9,8 @@ #include #include -#include #include +#include #include #include #include @@ -90,9 +90,7 @@ namespace Nz struct Context { - ShaderAst::AstCache cache; const States* states = nullptr; - std::vector functionBlocks; }; struct ExtVar diff --git a/src/Nazara/Shader/SpirvDecoder.cpp b/src/Nazara/Shader/SpirvDecoder.cpp new file mode 100644 index 000000000..141b009f1 --- /dev/null +++ b/src/Nazara/Shader/SpirvDecoder.cpp @@ -0,0 +1,87 @@ +// 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 +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + void SpirvDecoder::Decode(const UInt32* codepoints, std::size_t count) + { + m_currentCodepoint = codepoints; + m_codepointEnd = codepoints + count; + + UInt32 magicNumber = ReadWord(); + if (magicNumber != SpirvMagicNumber) + throw std::runtime_error("invalid Spir-V: magic number didn't match"); + + UInt32 versionNumber = ReadWord(); + if (versionNumber > SpirvVersion) + throw std::runtime_error("Spir-V is more recent than decoder, dismissing"); + + SpirvHeader header; + header.generatorId = ReadWord(); + header.bound = ReadWord(); + header.schema = ReadWord(); + header.versionNumber = versionNumber; + + if (!HandleHeader(header)) + return; + + while (m_currentCodepoint < m_codepointEnd) + { + UInt32 firstWord = ReadWord(); + + UInt16 wordCount = static_cast((firstWord >> 16) & 0xFFFF); + UInt16 opcode = static_cast(firstWord & 0xFFFF); + + const SpirvInstruction* inst = GetInstructionData(opcode); + if (!inst) + throw std::runtime_error("invalid instruction"); + + if (!HandleOpcode(*inst, wordCount)) + break; + + m_currentCodepoint += wordCount - 1; + } + } + + bool SpirvDecoder::HandleHeader(const SpirvHeader& /*header*/) + { + return true; + } + + std::string SpirvDecoder::ReadString() + { + std::string str; + + for (;;) + { + UInt32 value = ReadWord(); + for (std::size_t j = 0; j < 4; ++j) + { + char c = static_cast((value >> (j * 8)) & 0xFF); + if (c == '\0') + return str; + + str.push_back(c); + } + } + } + + UInt32 SpirvDecoder::ReadWord() + { + if (m_currentCodepoint >= m_codepointEnd) + throw std::runtime_error("unexpected end of stream"); + + return *m_currentCodepoint++; + } +} diff --git a/src/Nazara/Shader/SpirvPrinter.cpp b/src/Nazara/Shader/SpirvPrinter.cpp index 01eb65cb0..cd618c8bb 100644 --- a/src/Nazara/Shader/SpirvPrinter.cpp +++ b/src/Nazara/Shader/SpirvPrinter.cpp @@ -21,10 +21,7 @@ namespace Nz { } - const UInt32* codepoints; std::size_t resultOffset; - std::size_t index = 0; - std::size_t count; std::ostringstream stream; const Settings& settings; }; @@ -32,71 +29,49 @@ namespace Nz std::string SpirvPrinter::Print(const UInt32* codepoints, std::size_t count, const Settings& settings) { State state(settings); - state.codepoints = codepoints; - state.count = count; m_currentState = &state; CallOnExit resetOnExit([&] { m_currentState = nullptr; }); - UInt32 magicNumber = ReadWord(); - if (magicNumber != SpirvMagicNumber) - throw std::runtime_error("invalid Spir-V: magic number didn't match"); - - if (m_currentState->settings.printHeader) - m_currentState->stream << "Spir-V module\n"; - - UInt32 versionNumber = ReadWord(); - if (versionNumber > SpirvVersion) - throw std::runtime_error("Spir-V is more recent than printer, dismissing"); - - UInt8 majorVersion = ((versionNumber) >> 16) & 0xFF; - UInt8 minorVersion = ((versionNumber) >> 8) & 0xFF; - - UInt32 generatorId = ReadWord(); - UInt32 bound = ReadWord(); - UInt32 schema = ReadWord(); - - state.resultOffset = std::snprintf(nullptr, 0, "%%%u = ", bound); - - if (m_currentState->settings.printHeader) - { - m_currentState->stream << "Version " + std::to_string(+majorVersion) << "." << std::to_string(+minorVersion) << "\n"; - m_currentState->stream << "Generator: " << std::to_string(generatorId) << "\n"; - m_currentState->stream << "Bound: " << std::to_string(bound) << "\n"; - m_currentState->stream << "Schema: " << std::to_string(schema) << "\n"; - } - - while (m_currentState->index < m_currentState->count) - AppendInstruction(); + Decode(codepoints, count); return m_currentState->stream.str(); } - void SpirvPrinter::AppendInstruction() + bool SpirvPrinter::HandleHeader(const SpirvHeader& header) { - std::size_t startIndex = m_currentState->index; + UInt8 majorVersion = ((header.versionNumber) >> 16) & 0xFF; + UInt8 minorVersion = ((header.versionNumber) >> 8) & 0xFF; - UInt32 firstWord = ReadWord(); + m_currentState->resultOffset = std::snprintf(nullptr, 0, "%%%u = ", header.bound); - UInt16 wordCount = static_cast((firstWord >> 16) & 0xFFFF); - UInt16 opcode = static_cast(firstWord & 0xFFFF); + if (m_currentState->settings.printHeader) + { + m_currentState->stream << "Version " + std::to_string(+majorVersion) << "." << std::to_string(+minorVersion) << "\n"; + m_currentState->stream << "Generator: " << std::to_string(header.generatorId) << "\n"; + m_currentState->stream << "Bound: " << std::to_string(header.bound) << "\n"; + m_currentState->stream << "Schema: " << std::to_string(header.schema) << "\n"; + } - const SpirvInstruction* inst = GetInstructionData(opcode); - if (!inst) - throw std::runtime_error("invalid instruction"); + return true; + } + + bool SpirvPrinter::HandleOpcode(const SpirvInstruction& instruction, UInt32 wordCount) + { + const UInt32* startPtr = GetCurrentPtr(); if (m_currentState->settings.printParameters) { std::ostringstream instructionStream; - instructionStream << inst->name; + instructionStream << instruction.name; UInt32 resultId = 0; std::size_t currentOperand = 0; - std::size_t instructionEnd = startIndex + wordCount; - while (m_currentState->index < instructionEnd) + const UInt32* endPtr = startPtr + wordCount; + while (GetCurrentPtr() < endPtr) { - const SpirvInstruction::Operand* operand = &inst->operands[currentOperand]; + const SpirvInstruction::Operand* operand = &instruction.operands[currentOperand]; if (operand->kind != SpirvOperandKind::IdResult) { @@ -181,7 +156,7 @@ namespace Nz break; } - + case SpirvOperandKind::PairLiteralIntegerIdRef: { ReadWord(); @@ -210,13 +185,12 @@ namespace Nz default: break; - } } else resultId = ReadWord(); - if (currentOperand < inst->minOperandCount - 1) + if (currentOperand < instruction.minOperandCount - 1) currentOperand++; } @@ -231,42 +205,12 @@ namespace Nz m_currentState->stream << instructionStream.str(); } else - { - m_currentState->stream << inst->name; - - m_currentState->index += wordCount - 1; - if (m_currentState->index > m_currentState->count) - throw std::runtime_error("unexpected end of stream"); - } + m_currentState->stream << instruction.name; m_currentState->stream << "\n"; - assert(m_currentState->index == startIndex + wordCount); - } + assert(GetCurrentPtr() == startPtr + wordCount); - std::string SpirvPrinter::ReadString() - { - std::string str; - - for (;;) - { - UInt32 value = ReadWord(); - for (std::size_t j = 0; j < 4; ++j) - { - char c = static_cast((value >> (j * 8)) & 0xFF); - if (c == '\0') - return str; - - str.push_back(c); - } - } - } - - UInt32 SpirvPrinter::ReadWord() - { - if (m_currentState->index >= m_currentState->count) - throw std::runtime_error("unexpected end of stream"); - - return m_currentState->codepoints[m_currentState->index++]; + return true; } } From feffcfa6e5c76848f911edf6eb4896b4140cd1db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sun, 4 Apr 2021 20:29:44 +0200 Subject: [PATCH 092/278] VulkanRenderer: Fix handling of shader modules --- .../Nazara/VulkanRenderer/VulkanDevice.hpp | 4 +- .../VulkanRenderer/VulkanShaderModule.hpp | 53 +++++++ ...ShaderStage.inl => VulkanShaderModule.inl} | 8 +- .../VulkanRenderer/VulkanShaderStage.hpp | 44 ------ src/Nazara/VulkanRenderer/VulkanDevice.cpp | 20 +-- .../VulkanRenderer/VulkanRenderPipeline.cpp | 18 ++- .../VulkanRenderer/VulkanShaderModule.cpp | 144 ++++++++++++++++++ .../VulkanRenderer/VulkanShaderStage.cpp | 64 -------- 8 files changed, 223 insertions(+), 132 deletions(-) create mode 100644 include/Nazara/VulkanRenderer/VulkanShaderModule.hpp rename include/Nazara/VulkanRenderer/{VulkanShaderStage.inl => VulkanShaderModule.inl} (59%) delete mode 100644 include/Nazara/VulkanRenderer/VulkanShaderStage.hpp create mode 100644 src/Nazara/VulkanRenderer/VulkanShaderModule.cpp delete mode 100644 src/Nazara/VulkanRenderer/VulkanShaderStage.cpp diff --git a/include/Nazara/VulkanRenderer/VulkanDevice.hpp b/include/Nazara/VulkanRenderer/VulkanDevice.hpp index 753488bf4..d8dc546b6 100644 --- a/include/Nazara/VulkanRenderer/VulkanDevice.hpp +++ b/include/Nazara/VulkanRenderer/VulkanDevice.hpp @@ -29,8 +29,8 @@ namespace Nz std::shared_ptr InstantiateRenderPass(std::vector attachments, std::vector subpassDescriptions, std::vector subpassDependencies) override; std::shared_ptr InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override; std::shared_ptr InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) override; - std::shared_ptr InstantiateShaderModule(const ShaderAst& shaderAst, const ShaderWriter::States& states) override; - std::shared_ptr InstantiateShaderModule(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) override; + std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags stages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states) override; + std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags stages, ShaderLanguage lang, const void* source, std::size_t sourceSize) override; std::shared_ptr InstantiateTexture(const TextureInfo& params) override; std::shared_ptr InstantiateTextureSampler(const TextureSamplerInfo& params) override; diff --git a/include/Nazara/VulkanRenderer/VulkanShaderModule.hpp b/include/Nazara/VulkanRenderer/VulkanShaderModule.hpp new file mode 100644 index 000000000..8813eac54 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VulkanShaderModule.hpp @@ -0,0 +1,53 @@ +// Copyright (C) 2020 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VULKANSHADERSTAGE_HPP +#define NAZARA_VULKANRENDERER_VULKANSHADERSTAGE_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + class NAZARA_VULKANRENDERER_API VulkanShaderModule : public ShaderModule + { + public: + struct Stage; + + VulkanShaderModule() = default; + VulkanShaderModule(const VulkanShaderModule&) = delete; + VulkanShaderModule(VulkanShaderModule&&) = delete; + ~VulkanShaderModule() = default; + + bool Create(Vk::Device& device, ShaderStageTypeFlags shaderStages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states); + bool Create(Vk::Device& device, ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize); + + inline const Vk::ShaderModule& GetHandle() const; + inline const std::vector& GetStages() const; + + VulkanShaderModule& operator=(const VulkanShaderModule&) = delete; + VulkanShaderModule& operator=(VulkanShaderModule&&) = delete; + + struct Stage + { + ShaderStageType stage; + std::string name; + }; + + private: + Vk::ShaderModule m_shaderModule; + std::vector m_stages; + }; +} + +#include + +#endif // NAZARA_VULKANRENDERER_VULKANSHADERSTAGE_HPP diff --git a/include/Nazara/VulkanRenderer/VulkanShaderStage.inl b/include/Nazara/VulkanRenderer/VulkanShaderModule.inl similarity index 59% rename from include/Nazara/VulkanRenderer/VulkanShaderStage.inl rename to include/Nazara/VulkanRenderer/VulkanShaderModule.inl index 04aae8d74..8c3bded08 100644 --- a/include/Nazara/VulkanRenderer/VulkanShaderStage.inl +++ b/include/Nazara/VulkanRenderer/VulkanShaderModule.inl @@ -2,19 +2,19 @@ // This file is part of the "Nazara Engine - Vulkan Renderer" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include namespace Nz { - inline const Vk::ShaderModule& VulkanShaderStage::GetHandle() const + inline const Vk::ShaderModule& VulkanShaderModule::GetHandle() const { return m_shaderModule; } - inline ShaderStageType VulkanShaderStage::GetStageType() const + inline auto VulkanShaderModule::GetStages() const -> const std::vector& { - return m_stage; + return m_stages; } } diff --git a/include/Nazara/VulkanRenderer/VulkanShaderStage.hpp b/include/Nazara/VulkanRenderer/VulkanShaderStage.hpp deleted file mode 100644 index b019fb90c..000000000 --- a/include/Nazara/VulkanRenderer/VulkanShaderStage.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (C) 2020 Jérôme Leclercq -// This file is part of the "Nazara Engine - Vulkan Renderer" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_VULKANRENDERER_VULKANSHADERSTAGE_HPP -#define NAZARA_VULKANRENDERER_VULKANSHADERSTAGE_HPP - -#include -#include -#include -#include -#include -#include - -namespace Nz -{ - class NAZARA_VULKANRENDERER_API VulkanShaderStage : public ShaderModule - { - public: - VulkanShaderStage() = default; - VulkanShaderStage(const VulkanShaderStage&) = delete; - VulkanShaderStage(VulkanShaderStage&&) = delete; - ~VulkanShaderStage() = default; - - bool Create(Vk::Device& device, const ShaderAst& shader, const ShaderWriter::States& states); - bool Create(Vk::Device& device, ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize); - - inline const Vk::ShaderModule& GetHandle() const; - inline ShaderStageType GetStageType() const; - - VulkanShaderStage& operator=(const VulkanShaderStage&) = delete; - VulkanShaderStage& operator=(VulkanShaderStage&&) = delete; - - private: - Vk::ShaderModule m_shaderModule; - ShaderStageType m_stage; - }; -} - -#include - -#endif // NAZARA_VULKANRENDERER_VULKANSHADERSTAGE_HPP diff --git a/src/Nazara/VulkanRenderer/VulkanDevice.cpp b/src/Nazara/VulkanRenderer/VulkanDevice.cpp index 1311398af..e3e2fdd2a 100644 --- a/src/Nazara/VulkanRenderer/VulkanDevice.cpp +++ b/src/Nazara/VulkanRenderer/VulkanDevice.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include @@ -46,25 +46,25 @@ namespace Nz { auto pipelineLayout = std::make_shared(); if (!pipelineLayout->Create(*this, std::move(pipelineLayoutInfo))) - return {}; + throw std::runtime_error("failed to instanciate vulkan render pipeline layout"); return pipelineLayout; } - std::shared_ptr VulkanDevice::InstantiateShaderModule(const ShaderAst& shaderAst, const ShaderWriter::States& states) + std::shared_ptr VulkanDevice::InstantiateShaderModule(ShaderStageTypeFlags stages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states) { - auto stage = std::make_shared(); - if (!stage->Create(*this, shaderAst, states)) - return {}; + auto stage = std::make_shared(); + if (!stage->Create(*this, stages, shaderAst, states)) + throw std::runtime_error("failed to instanciate vulkan shader module"); return stage; } - std::shared_ptr VulkanDevice::InstantiateShaderModule(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) + std::shared_ptr VulkanDevice::InstantiateShaderModule(ShaderStageTypeFlags stages, ShaderLanguage lang, const void* source, std::size_t sourceSize) { - auto stage = std::make_shared(); - if (!stage->Create(*this, type, lang, source, sourceSize)) - return {}; + auto stage = std::make_shared(); + if (!stage->Create(*this, stages, lang, source, sourceSize)) + throw std::runtime_error("failed to instanciate vulkan shader module"); return stage; } diff --git a/src/Nazara/VulkanRenderer/VulkanRenderPipeline.cpp b/src/Nazara/VulkanRenderer/VulkanRenderPipeline.cpp index ec7295c19..0f8b7098e 100644 --- a/src/Nazara/VulkanRenderer/VulkanRenderPipeline.cpp +++ b/src/Nazara/VulkanRenderer/VulkanRenderPipeline.cpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include @@ -166,13 +166,15 @@ namespace Nz for (auto&& stagePtr : pipelineInfo.shaderModules) { - Nz::VulkanShaderStage& vulkanStage = *static_cast(stagePtr.get()); - - VkPipelineShaderStageCreateInfo& createInfo = shaderStageCreateInfos.emplace_back(); - createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - createInfo.module = vulkanStage.GetHandle(); - createInfo.pName = "main"; - createInfo.stage = ToVulkan(vulkanStage.GetStageType()); + Nz::VulkanShaderModule& vulkanModule = *static_cast(stagePtr.get()); + for (auto& stage : vulkanModule.GetStages()) + { + VkPipelineShaderStageCreateInfo& createInfo = shaderStageCreateInfos.emplace_back(); + createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + createInfo.module = vulkanModule.GetHandle(); + createInfo.pName = stage.name.data(); + createInfo.stage = ToVulkan(stage.stage); + } } return shaderStageCreateInfos; diff --git a/src/Nazara/VulkanRenderer/VulkanShaderModule.cpp b/src/Nazara/VulkanRenderer/VulkanShaderModule.cpp new file mode 100644 index 000000000..dda59dee1 --- /dev/null +++ b/src/Nazara/VulkanRenderer/VulkanShaderModule.cpp @@ -0,0 +1,144 @@ +// Copyright (C) 2020 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + namespace + { + struct SpirvEntryPointExtractor : SpirvDecoder + { + struct EntryPoint + { + SpirvExecutionModel executionModel; + std::string name; + }; + + std::vector entryPoints; + + bool HandleOpcode(const SpirvInstruction& instruction, UInt32 wordCount) override + { + switch (instruction.op) + { + // All instructions that can appear before OpEntryPoint + case SpirvOp::OpCapability: + case SpirvOp::OpExtension: + case SpirvOp::OpExtInstImport: + case SpirvOp::OpMemoryModel: + return true; + + case SpirvOp::OpEntryPoint: + { + SpirvExecutionModel executionModel = static_cast(ReadWord()); + std::string name = ReadString(); + + entryPoints.push_back({ + executionModel, + std::move(name) + }); + + return true; + } + + // Return false for other instructions (which means OpEntryPoint will no longer appear from here) + default: + return false; + } + } + }; + } + + bool VulkanShaderModule::Create(Vk::Device& device, ShaderStageTypeFlags shaderStages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states) + { + SpirvWriter::Environment env; + + SpirvWriter writer; + writer.SetEnv(env); + + std::vector code = writer.Generate(shaderAst, states); + return Create(device, shaderStages, ShaderLanguage::SpirV, code.data(), code.size() * sizeof(UInt32)); + } + + bool VulkanShaderModule::Create(Vk::Device& device, ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize) + { + switch (lang) + { + case ShaderLanguage::GLSL: + case ShaderLanguage::HLSL: + case ShaderLanguage::MSL: + break; + + case ShaderLanguage::NazaraBinary: + { + auto shader = ShaderAst::UnserializeShader(source, sourceSize); + return Create(device, shaderStages, shader, {}); + } + + case ShaderLanguage::NazaraShader: + { + std::vector tokens = Nz::ShaderLang::Tokenize(std::string_view(static_cast(source), sourceSize)); + + Nz::ShaderLang::Parser parser; + Nz::ShaderAst::StatementPtr shaderAst = parser.Parse(tokens); + return Create(device, shaderStages, shaderAst, {}); + } + + case ShaderLanguage::SpirV: + { + SpirvEntryPointExtractor extractor; + extractor.Decode(reinterpret_cast(source), sourceSize); + + ShaderStageTypeFlags remainingStages = shaderStages; + for (auto& entryPoint : extractor.entryPoints) + { + ShaderStageType stageType; + switch (entryPoint.executionModel) + { + case SpirvExecutionModel::Fragment: + stageType = ShaderStageType::Fragment; + break; + + case SpirvExecutionModel::Vertex: + stageType = ShaderStageType::Vertex; + break; + + default: + continue; //< Ignore + } + + m_stages.push_back({ + stageType, + std::move(entryPoint.name) + }); + + remainingStages.Clear(stageType); + } + + if (remainingStages != 0) + { + NazaraError("Vulkan shader module does not handle all requested stage types"); + return false; + } + + if (!m_shaderModule.Create(device, reinterpret_cast(source), sourceSize)) + { + NazaraError("failed to create shader module"); + return false; + } + + return true; + } + } + + NazaraError("this language is not supported"); + return false; + } +} diff --git a/src/Nazara/VulkanRenderer/VulkanShaderStage.cpp b/src/Nazara/VulkanRenderer/VulkanShaderStage.cpp deleted file mode 100644 index 403699798..000000000 --- a/src/Nazara/VulkanRenderer/VulkanShaderStage.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (C) 2020 Jérôme Leclercq -// This file is part of the "Nazara Engine - Vulkan Renderer" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include -#include -#include - -namespace Nz -{ - bool VulkanShaderStage::Create(Vk::Device& device, const ShaderAst& shader, const ShaderWriter::States& states) - { - m_stage = shader.GetStage(); - - SpirvWriter::Environment env; - - SpirvWriter writer; - writer.SetEnv(env); - - std::vector code = writer.Generate(shader, states); - return Create(device, m_stage, ShaderLanguage::SpirV, code.data(), code.size() * sizeof(UInt32)); - } - - bool VulkanShaderStage::Create(Vk::Device& device, ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) - { - m_stage = type; - - switch (lang) - { - case ShaderLanguage::NazaraBinary: - { - auto shader = UnserializeShader(source, sourceSize); - if (shader.GetStage() != type) - throw std::runtime_error("incompatible shader stage"); - - if (!Create(device, shader, {})) - return false; - - break; - } - - case ShaderLanguage::SpirV: - { - if (!m_shaderModule.Create(device, reinterpret_cast(source), sourceSize)) - { - NazaraError("Failed to create shader module"); - return false; - } - - break; - } - - default: - { - NazaraError("this language is not supported"); - return false; - } - } - - return true; - } -} From f93a5bbdc143e5885f180823f0dee88ad76a1552 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sun, 4 Apr 2021 20:31:09 +0200 Subject: [PATCH 093/278] Shader: Rework scope handling --- include/Nazara/Shader.hpp | 3 - include/Nazara/Shader/GlslWriter.hpp | 8 +- include/Nazara/Shader/ShaderAstCache.hpp | 56 --- include/Nazara/Shader/ShaderAstCache.inl | 45 --- include/Nazara/Shader/ShaderAstCloner.hpp | 2 +- .../Nazara/Shader/ShaderAstExpressionType.hpp | 58 --- .../Nazara/Shader/ShaderAstExpressionType.inl | 17 - .../Nazara/Shader/ShaderAstScopedVisitor.hpp | 68 ++++ .../Nazara/Shader/ShaderAstScopedVisitor.inl | 38 ++ include/Nazara/Shader/ShaderAstValidator.hpp | 21 +- include/Nazara/Shader/ShaderNodes.hpp | 2 + include/Nazara/Shader/SpirvAstVisitor.hpp | 4 +- include/Nazara/Shader/SpirvAstVisitor.inl | 9 +- include/Nazara/Shader/SpirvConstantCache.hpp | 14 +- src/Nazara/Shader/GlslWriter.cpp | 177 ++++++--- src/Nazara/Shader/ShaderAstCloner.cpp | 20 +- src/Nazara/Shader/ShaderAstExpressionType.cpp | 258 ------------ src/Nazara/Shader/ShaderAstOptimizer.cpp | 8 +- src/Nazara/Shader/ShaderAstScopedVisitor.cpp | 110 ++++++ src/Nazara/Shader/ShaderAstValidator.cpp | 374 +++++++++--------- src/Nazara/Shader/SpirvAstVisitor.cpp | 11 +- src/Nazara/Shader/SpirvConstantCache.cpp | 72 ++-- src/Nazara/Shader/SpirvWriter.cpp | 41 +- 23 files changed, 661 insertions(+), 755 deletions(-) delete mode 100644 include/Nazara/Shader/ShaderAstCache.hpp delete mode 100644 include/Nazara/Shader/ShaderAstCache.inl delete mode 100644 include/Nazara/Shader/ShaderAstExpressionType.hpp delete mode 100644 include/Nazara/Shader/ShaderAstExpressionType.inl create mode 100644 include/Nazara/Shader/ShaderAstScopedVisitor.hpp create mode 100644 include/Nazara/Shader/ShaderAstScopedVisitor.inl delete mode 100644 src/Nazara/Shader/ShaderAstExpressionType.cpp create mode 100644 src/Nazara/Shader/ShaderAstScopedVisitor.cpp diff --git a/include/Nazara/Shader.hpp b/include/Nazara/Shader.hpp index cef4eada9..2bd6df584 100644 --- a/include/Nazara/Shader.hpp +++ b/include/Nazara/Shader.hpp @@ -32,12 +32,9 @@ #include #include #include -#include #include -#include #include #include -#include #include #include #include diff --git a/include/Nazara/Shader/GlslWriter.hpp b/include/Nazara/Shader/GlslWriter.hpp index aab8f06c5..8b5f964e8 100644 --- a/include/Nazara/Shader/GlslWriter.hpp +++ b/include/Nazara/Shader/GlslWriter.hpp @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include #include @@ -17,7 +17,7 @@ namespace Nz { - class NAZARA_SHADER_API GlslWriter : public ShaderWriter, public ShaderAst::AstRecursiveVisitor + class NAZARA_SHADER_API GlslWriter : public ShaderWriter, public ShaderAst::AstScopedVisitor { public: struct Environment; @@ -57,8 +57,8 @@ namespace Nz template void Append(const T& param); template void Append(const T1& firstParam, const T2& secondParam, Args&&... params); void AppendCommentSection(const std::string& section); - void AppendEntryPoint(ShaderStageType shaderStage); - void AppendField(std::size_t scopeId, const std::string& structName, const std::string* memberIdentifier, std::size_t remainingMembers); + void AppendEntryPoint(ShaderStageType shaderStage, ShaderAst::StatementPtr& shader); + void AppendField(const std::string& structName, const std::string* memberIdentifier, std::size_t remainingMembers); void AppendLine(const std::string& txt = {}); template void AppendLine(Args&&... params); diff --git a/include/Nazara/Shader/ShaderAstCache.hpp b/include/Nazara/Shader/ShaderAstCache.hpp deleted file mode 100644 index 2a18b173d..000000000 --- a/include/Nazara/Shader/ShaderAstCache.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// 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_SHADERASTCACHE_HPP -#define NAZARA_SHADERASTCACHE_HPP - -#include -#include -#include -#include - -namespace Nz::ShaderAst -{ - struct AstCache - { - struct Identifier; - - struct Alias - { - std::variant value; - }; - - struct Variable - { - ExpressionType type; - }; - - struct Identifier - { - std::string name; - std::variant value; - }; - - struct Scope - { - std::optional parentScopeIndex; - std::vector identifiers; - }; - - inline void Clear(); - inline const Identifier* FindIdentifier(std::size_t startingScopeId, const std::string& identifierName) const; - inline std::size_t GetScopeId(const Node* node) const; - - std::array entryFunctions = {}; - std::unordered_map nodeExpressionType; - std::unordered_map scopeIdByNode; - std::vector scopes; - }; -} - -#include - -#endif diff --git a/include/Nazara/Shader/ShaderAstCache.inl b/include/Nazara/Shader/ShaderAstCache.inl deleted file mode 100644 index f254eac0c..000000000 --- a/include/Nazara/Shader/ShaderAstCache.inl +++ /dev/null @@ -1,45 +0,0 @@ -// 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 -#include - -namespace Nz::ShaderAst -{ - inline void AstCache::Clear() - { - entryFunctions.fill(nullptr); - nodeExpressionType.clear(); - scopeIdByNode.clear(); - scopes.clear(); - } - - inline auto AstCache::FindIdentifier(std::size_t startingScopeId, const std::string& identifierName) const -> const Identifier* - { - assert(startingScopeId < scopes.size()); - - std::optional scopeId = startingScopeId; - do - { - const auto& scope = scopes[*scopeId]; - auto it = std::find_if(scope.identifiers.rbegin(), scope.identifiers.rend(), [&](const auto& identifier) { return identifier.name == identifierName; }); - if (it != scope.identifiers.rend()) - return &*it; - - scopeId = scope.parentScopeIndex; - } while (scopeId); - - return nullptr; - } - - inline std::size_t AstCache::GetScopeId(const Node* node) const - { - auto it = scopeIdByNode.find(node); - assert(it != scopeIdByNode.end()); - - return it->second; - } -} - -#include diff --git a/include/Nazara/Shader/ShaderAstCloner.hpp b/include/Nazara/Shader/ShaderAstCloner.hpp index a2ee45f44..6b7d6b2b7 100644 --- a/include/Nazara/Shader/ShaderAstCloner.hpp +++ b/include/Nazara/Shader/ShaderAstCloner.hpp @@ -33,7 +33,7 @@ namespace Nz::ShaderAst ExpressionPtr CloneExpression(ExpressionPtr& expr); StatementPtr CloneStatement(StatementPtr& statement); - virtual std::unique_ptr Clone(DeclareFunctionStatement& node); + virtual StatementPtr Clone(DeclareFunctionStatement& node); using AstExpressionVisitor::Visit; using AstStatementVisitor::Visit; diff --git a/include/Nazara/Shader/ShaderAstExpressionType.hpp b/include/Nazara/Shader/ShaderAstExpressionType.hpp deleted file mode 100644 index 095b5e5ea..000000000 --- a/include/Nazara/Shader/ShaderAstExpressionType.hpp +++ /dev/null @@ -1,58 +0,0 @@ -// 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_SHADERASTEXPRESSIONTYPE_HPP -#define NAZARA_SHADERASTEXPRESSIONTYPE_HPP - -#include -#include -#include -#include -#include - -namespace Nz::ShaderAst -{ - struct AstCache; - - class NAZARA_SHADER_API ExpressionTypeVisitor : public AstExpressionVisitor - { - public: - ExpressionTypeVisitor() = default; - ExpressionTypeVisitor(const ExpressionTypeVisitor&) = delete; - ExpressionTypeVisitor(ExpressionTypeVisitor&&) = delete; - ~ExpressionTypeVisitor() = default; - - ExpressionType GetExpressionType(Expression& expression, AstCache* cache); - - ExpressionTypeVisitor& operator=(const ExpressionTypeVisitor&) = delete; - ExpressionTypeVisitor& operator=(ExpressionTypeVisitor&&) = delete; - - private: - ExpressionType GetExpressionTypeInternal(Expression& expression); - ExpressionType ResolveAlias(Expression& expression, ExpressionType expressionType); - - void Visit(Expression& expression); - - void Visit(AccessMemberExpression& node) override; - void Visit(AssignExpression& node) override; - void Visit(BinaryExpression& node) override; - void Visit(CastExpression& node) override; - void Visit(ConditionalExpression& node) override; - void Visit(ConstantExpression& node) override; - void Visit(IdentifierExpression& node) override; - void Visit(IntrinsicExpression& node) override; - void Visit(SwizzleExpression& node) override; - - AstCache* m_cache; - std::optional m_lastExpressionType; - }; - - inline ExpressionType GetExpressionType(Expression& expression, AstCache* cache = nullptr); -} - -#include - -#endif diff --git a/include/Nazara/Shader/ShaderAstExpressionType.inl b/include/Nazara/Shader/ShaderAstExpressionType.inl deleted file mode 100644 index 279a3909e..000000000 --- a/include/Nazara/Shader/ShaderAstExpressionType.inl +++ /dev/null @@ -1,17 +0,0 @@ -// 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 -#include - -namespace Nz::ShaderAst -{ - inline ExpressionType GetExpressionType(Expression& expression, AstCache* cache) - { - ExpressionTypeVisitor visitor; - return visitor.GetExpressionType(expression, cache); - } -} - -#include diff --git a/include/Nazara/Shader/ShaderAstScopedVisitor.hpp b/include/Nazara/Shader/ShaderAstScopedVisitor.hpp new file mode 100644 index 000000000..e212a30b5 --- /dev/null +++ b/include/Nazara/Shader/ShaderAstScopedVisitor.hpp @@ -0,0 +1,68 @@ +// 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_SCOPED_VISITOR_HPP +#define NAZARA_SHADER_SCOPED_VISITOR_HPP + +#include +#include +#include + +namespace Nz::ShaderAst +{ + class NAZARA_SHADER_API AstScopedVisitor : public AstRecursiveVisitor + { + public: + struct Identifier; + + AstScopedVisitor() = default; + ~AstScopedVisitor() = default; + + inline const Identifier* FindIdentifier(const std::string_view& identifierName) const; + + void ScopedVisit(StatementPtr& nodePtr); + + using AstRecursiveVisitor::Visit; + void Visit(BranchStatement& node) override; + void Visit(ConditionalStatement& node) override; + void Visit(DeclareExternalStatement& node) override; + void Visit(DeclareFunctionStatement& node) override; + void Visit(DeclareStructStatement& node) override; + void Visit(DeclareVariableStatement& node) override; + void Visit(MultiStatement& node) override; + + struct Alias + { + std::variant value; + }; + + struct Variable + { + ExpressionType type; + }; + + struct Identifier + { + std::string name; + std::variant value; + }; + + protected: + void PushScope(); + void PopScope(); + + inline void RegisterStruct(StructDescription structDesc); + inline void RegisterVariable(std::string name, ExpressionType type); + + private: + std::vector m_identifiersInScope; + std::vector m_scopeSizes; + }; +} + +#include + +#endif diff --git a/include/Nazara/Shader/ShaderAstScopedVisitor.inl b/include/Nazara/Shader/ShaderAstScopedVisitor.inl new file mode 100644 index 000000000..67042069a --- /dev/null +++ b/include/Nazara/Shader/ShaderAstScopedVisitor.inl @@ -0,0 +1,38 @@ +// 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 +#include + +namespace Nz::ShaderAst +{ + inline auto AstScopedVisitor::FindIdentifier(const std::string_view& identifierName) const -> const Identifier* + { + auto it = std::find_if(m_identifiersInScope.rbegin(), m_identifiersInScope.rend(), [&](const Identifier& identifier) { return identifier.name == identifierName; }); + if (it == m_identifiersInScope.rend()) + return nullptr; + + return &*it; + } + + inline void AstScopedVisitor::RegisterStruct(StructDescription structDesc) + { + std::string name = structDesc.name; + + m_identifiersInScope.push_back({ + std::move(name), + std::move(structDesc) + }); + } + + inline void AstScopedVisitor::RegisterVariable(std::string name, ExpressionType type) + { + m_identifiersInScope.push_back({ + std::move(name), + Variable { std::move(type) } + }); + } +} + +#include diff --git a/include/Nazara/Shader/ShaderAstValidator.hpp b/include/Nazara/Shader/ShaderAstValidator.hpp index e3dd4d94e..b617e27c7 100644 --- a/include/Nazara/Shader/ShaderAstValidator.hpp +++ b/include/Nazara/Shader/ShaderAstValidator.hpp @@ -9,13 +9,12 @@ #include #include -#include -#include +#include #include namespace Nz::ShaderAst { - class NAZARA_SHADER_API AstValidator : public AstRecursiveVisitor + class NAZARA_SHADER_API AstValidator final : public AstScopedVisitor { public: inline AstValidator(); @@ -23,28 +22,24 @@ namespace Nz::ShaderAst AstValidator(AstValidator&&) = delete; ~AstValidator() = default; - bool Validate(StatementPtr& node, std::string* error = nullptr, AstCache* cache = nullptr); + bool Validate(StatementPtr& node, std::string* error = nullptr); private: + const ExpressionType& GetExpressionType(Expression& expression); Expression& MandatoryExpr(ExpressionPtr& node); Statement& MandatoryStatement(StatementPtr& node); void TypeMustMatch(ExpressionPtr& left, ExpressionPtr& right); void TypeMustMatch(const ExpressionType& left, const ExpressionType& right); ExpressionType CheckField(const std::string& structName, const std::string* memberIdentifier, std::size_t remainingMembers); - - AstCache::Scope& EnterScope(); - void ExitScope(); - - void RegisterExpressionType(Expression& node, ExpressionType expressionType); - void RegisterScope(Node& node); + const ExpressionType& ResolveAlias(const ExpressionType& expressionType); void Visit(AccessMemberExpression& node) override; void Visit(AssignExpression& node) override; void Visit(BinaryExpression& node) override; void Visit(CastExpression& node) override; - void Visit(ConditionalExpression& node) override; void Visit(ConstantExpression& node) override; + void Visit(ConditionalExpression& node) override; void Visit(IdentifierExpression& node) override; void Visit(IntrinsicExpression& node) override; void Visit(SwizzleExpression& node) override; @@ -54,17 +49,15 @@ namespace Nz::ShaderAst void Visit(DeclareExternalStatement& node) override; void Visit(DeclareFunctionStatement& node) override; void Visit(DeclareStructStatement& node) override; - void Visit(DeclareVariableStatement& node) override; void Visit(ExpressionStatement& node) override; void Visit(MultiStatement& node) override; - void Visit(ReturnStatement& node) override; struct Context; Context* m_context; }; - NAZARA_SHADER_API bool ValidateAst(StatementPtr& node, std::string* error = nullptr, AstCache* cache = nullptr); + NAZARA_SHADER_API bool ValidateAst(StatementPtr& node, std::string* error = nullptr); } #include diff --git a/include/Nazara/Shader/ShaderNodes.hpp b/include/Nazara/Shader/ShaderNodes.hpp index bfd0ebb47..7b442c07c 100644 --- a/include/Nazara/Shader/ShaderNodes.hpp +++ b/include/Nazara/Shader/ShaderNodes.hpp @@ -56,6 +56,8 @@ namespace Nz::ShaderAst Expression& operator=(const Expression&) = delete; Expression& operator=(Expression&&) noexcept = default; + + std::optional cachedExpressionType; }; struct NAZARA_SHADER_API AccessMemberExpression : public Expression diff --git a/include/Nazara/Shader/SpirvAstVisitor.hpp b/include/Nazara/Shader/SpirvAstVisitor.hpp index b6536ea2e..d868dab41 100644 --- a/include/Nazara/Shader/SpirvAstVisitor.hpp +++ b/include/Nazara/Shader/SpirvAstVisitor.hpp @@ -21,7 +21,7 @@ namespace Nz class NAZARA_SHADER_API SpirvAstVisitor : public ShaderAst::ExpressionVisitorExcept, public ShaderAst::StatementVisitorExcept { public: - inline SpirvAstVisitor(SpirvWriter& writer, std::vector& blocks, ShaderAst::AstCache* cache); + inline SpirvAstVisitor(SpirvWriter& writer, std::vector& blocks); SpirvAstVisitor(const SpirvAstVisitor&) = delete; SpirvAstVisitor(SpirvAstVisitor&&) = delete; ~SpirvAstVisitor() = default; @@ -53,10 +53,10 @@ namespace Nz SpirvAstVisitor& operator=(SpirvAstVisitor&&) = delete; private: + inline const ShaderAst::ExpressionType& GetExpressionType(ShaderAst::Expression& expr) const; void PushResultId(UInt32 value); UInt32 PopResultId(); - ShaderAst::AstCache* m_cache; std::vector& m_blocks; std::vector m_resultIds; SpirvBlock* m_currentBlock; diff --git a/include/Nazara/Shader/SpirvAstVisitor.inl b/include/Nazara/Shader/SpirvAstVisitor.inl index 8694244be..bb54eb594 100644 --- a/include/Nazara/Shader/SpirvAstVisitor.inl +++ b/include/Nazara/Shader/SpirvAstVisitor.inl @@ -7,13 +7,18 @@ namespace Nz { - inline SpirvAstVisitor::SpirvAstVisitor(SpirvWriter& writer, std::vector& blocks, ShaderAst::AstCache* cache) : - m_cache(cache), + inline SpirvAstVisitor::SpirvAstVisitor(SpirvWriter& writer, std::vector& blocks) : m_blocks(blocks), m_writer(writer) { m_currentBlock = &m_blocks.back(); } + + inline const ShaderAst::ExpressionType& SpirvAstVisitor::GetExpressionType(ShaderAst::Expression& expr) const + { + assert(expr.cachedExpressionType); + return expr.cachedExpressionType.value(); + } } #include diff --git a/include/Nazara/Shader/SpirvConstantCache.hpp b/include/Nazara/Shader/SpirvConstantCache.hpp index 5453e9f46..c01ab8d68 100644 --- a/include/Nazara/Shader/SpirvConstantCache.hpp +++ b/include/Nazara/Shader/SpirvConstantCache.hpp @@ -31,11 +31,14 @@ namespace Nz ~SpirvConstantCache(); struct Constant; + struct Identifier; struct Type; using ConstantPtr = std::shared_ptr; using TypePtr = std::shared_ptr; + using IdentifierCallback = std::function; + struct Bool {}; struct Float @@ -63,6 +66,11 @@ namespace Nz UInt32 columnCount; }; + struct Identifier + { + std::string name; + }; + struct Image { std::optional qualifier; @@ -104,7 +112,7 @@ namespace Nz std::vector members; }; - using AnyType = std::variant; + using AnyType = std::variant; struct ConstantBool { @@ -166,6 +174,8 @@ namespace Nz UInt32 Register(Type t); UInt32 Register(Variable v); + void SetIdentifierCallback(IdentifierCallback callback); + void Write(SpirvSection& annotations, SpirvSection& constants, SpirvSection& debugInfos); SpirvConstantCache& operator=(const SpirvConstantCache& cache) = delete; @@ -181,6 +191,7 @@ namespace Nz static TypePtr BuildType(const ShaderAst::NoType& type); static TypePtr BuildType(const ShaderAst::PrimitiveType& type); static TypePtr BuildType(const ShaderAst::SamplerType& type); + static TypePtr BuildType(const ShaderAst::StructDescription& structDesc); static TypePtr BuildType(const ShaderAst::VectorType& type); private: @@ -193,6 +204,7 @@ namespace Nz void WriteStruct(const Structure& structData, UInt32 resultId, SpirvSection& annotations, SpirvSection& constants, SpirvSection& debugInfos); + IdentifierCallback m_identifierCallback; std::unique_ptr m_internal; }; } diff --git a/src/Nazara/Shader/GlslWriter.cpp b/src/Nazara/Shader/GlslWriter.cpp index 8580fd5b0..0f1aaac4a 100644 --- a/src/Nazara/Shader/GlslWriter.cpp +++ b/src/Nazara/Shader/GlslWriter.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -22,31 +21,87 @@ namespace Nz static const char* flipYUniformName = "_NzFlipValue"; static const char* overridenMain = "_NzMain"; - struct AstAdapter : ShaderAst::AstCloner + //FIXME: Have this only once + std::unordered_map s_entryPoints = { + { "frag", ShaderStageType::Fragment }, + { "vert", ShaderStageType::Vertex }, + }; + + struct PreVisitor : ShaderAst::AstCloner { using AstCloner::Clone; - std::unique_ptr Clone(ShaderAst::DeclareFunctionStatement& node) override + ShaderAst::StatementPtr Clone(ShaderAst::DeclareFunctionStatement& node) override { auto clone = AstCloner::Clone(node); - if (clone->name == "main") - clone->name = "_NzMain"; + assert(clone->GetType() == ShaderAst::NodeType::DeclareFunctionStatement); + + ShaderAst::DeclareFunctionStatement* func = static_cast(clone.get()); + + bool hasEntryPoint = false; + + for (auto& attribute : func->attributes) + { + if (attribute.type == ShaderAst::AttributeType::Entry) + { + auto it = s_entryPoints.find(std::get(attribute.args)); + assert(it != s_entryPoints.end()); + + if (it->second == selectedEntryPoint) + { + hasEntryPoint = true; + break; + } + } + } + + if (!hasEntryPoint) + return ShaderBuilder::NoOp(); + + entryPoint = func; + + if (func->name == "main") + func->name = "_NzMain"; return clone; } - void Visit(ShaderAst::DeclareFunctionStatement& node) - { - if (removedEntryPoints.find(&node) != removedEntryPoints.end()) - { - PushStatement(ShaderBuilder::NoOp()); - return; - } + ShaderStageType selectedEntryPoint; + ShaderAst::DeclareFunctionStatement* entryPoint = nullptr; + }; - AstCloner::Visit(node); + struct EntryFuncResolver : ShaderAst::AstScopedVisitor + { + void Visit(ShaderAst::DeclareFunctionStatement& node) override + { + + + if (&node != entryPoint) + return; + + assert(node.parameters.size() == 1); + + const ShaderAst::ExpressionType& inputType = node.parameters.front().type; + const ShaderAst::ExpressionType& outputType = node.returnType; + + const Identifier* identifier; + + assert(IsIdentifierType(node.parameters.front().type)); + identifier = FindIdentifier(std::get(inputType).name); + assert(identifier); + + inputIdentifier = *identifier; + + assert(IsIdentifierType(outputType)); + identifier = FindIdentifier(std::get(outputType).name); + assert(identifier); + + outputIdentifier = *identifier; } - std::unordered_set removedEntryPoints; + Identifier inputIdentifier; + Identifier outputIdentifier; + ShaderAst::DeclareFunctionStatement* entryPoint; }; struct Builtin @@ -64,7 +119,6 @@ namespace Nz struct GlslWriter::State { const States* states = nullptr; - ShaderAst::AstCache cache; ShaderAst::DeclareFunctionStatement* entryFunc = nullptr; std::stringstream stream; unsigned int indentLevel = 0; @@ -86,29 +140,18 @@ namespace Nz }); std::string error; - if (!ShaderAst::ValidateAst(shader, &error, &state.cache)) + if (!ShaderAst::ValidateAst(shader, &error)) throw std::runtime_error("Invalid shader AST: " + error); - state.entryFunc = state.cache.entryFunctions[UnderlyingCast(shaderStage)]; - if (!state.entryFunc) + PreVisitor previsitor; + previsitor.selectedEntryPoint = shaderStage; + + ShaderAst::StatementPtr adaptedShader = previsitor.Clone(shader); + + if (!previsitor.entryPoint) throw std::runtime_error("missing entry point"); - AstAdapter adapter; - - for (ShaderAst::DeclareFunctionStatement* entryFunc : state.cache.entryFunctions) - { - if (entryFunc != state.entryFunc) - adapter.removedEntryPoints.insert(entryFunc); - } - - ShaderAst::StatementPtr adaptedShader = adapter.Clone(shader); - - state.cache.Clear(); - if (!ShaderAst::ValidateAst(adaptedShader, &error, &state.cache)) - throw std::runtime_error("Internal error:" + error); - - state.entryFunc = state.cache.entryFunctions[UnderlyingCast(shaderStage)]; - assert(state.entryFunc); + state.entryFunc = previsitor.entryPoint; unsigned int glslVersion; if (m_environment.glES) @@ -190,10 +233,14 @@ namespace Nz AppendLine(); } - adaptedShader->Visit(*this); + PushScope(); + { + adaptedShader->Visit(*this); - // Append true GLSL entry point - AppendEntryPoint(shaderStage); + // Append true GLSL entry point + AppendEntryPoint(shaderStage, adaptedShader); + } + PopScope(); return state.stream.str(); } @@ -340,8 +387,12 @@ namespace Nz AppendLine(); } - void GlslWriter::AppendEntryPoint(ShaderStageType shaderStage) + void GlslWriter::AppendEntryPoint(ShaderStageType shaderStage, ShaderAst::StatementPtr& shader) { + EntryFuncResolver entryResolver; + entryResolver.entryPoint = m_currentState->entryFunc; + entryResolver.ScopedVisit(shader); + AppendLine(); AppendLine("// Entry point handling"); @@ -354,15 +405,10 @@ namespace Nz std::vector inputFields; const ShaderAst::StructDescription* inputStruct = nullptr; - auto HandleInOutStructs = [this, shaderStage](const ShaderAst::ExpressionType& expressionType, std::vector& fields, const char* keyword, const char* fromPrefix, const char* targetPrefix) -> const ShaderAst::StructDescription* + auto HandleInOutStructs = [this, shaderStage](const Identifier& identifier, std::vector& fields, const char* keyword, const char* fromPrefix, const char* targetPrefix) -> const ShaderAst::StructDescription* { - assert(IsIdentifierType(expressionType)); - - const ShaderAst::AstCache::Identifier* identifier = m_currentState->cache.FindIdentifier(0, std::get(expressionType).name); - assert(identifier); - - assert(std::holds_alternative(identifier->value)); - const auto& s = std::get(identifier->value); + assert(std::holds_alternative(identifier.value)); + const auto& s = std::get(identifier.value); for (const auto& member : s.members) { @@ -426,17 +472,12 @@ namespace Nz }; if (!m_currentState->entryFunc->parameters.empty()) - { - assert(m_currentState->entryFunc->parameters.size() == 1); - const auto& parameter = m_currentState->entryFunc->parameters.front(); - - inputStruct = HandleInOutStructs(parameter.type, inputFields, "in", "_nzInput.", "_NzIn_"); - } + inputStruct = HandleInOutStructs(entryResolver.inputIdentifier, inputFields, "in", "_nzInput.", "_NzIn_"); std::vector outputFields; const ShaderAst::StructDescription* outputStruct = nullptr; if (!IsNoType(m_currentState->entryFunc->returnType)) - outputStruct = HandleInOutStructs(m_currentState->entryFunc->returnType, outputFields, "out", "_nzOutput.", "_NzOut_"); + outputStruct = HandleInOutStructs(entryResolver.outputIdentifier, outputFields, "out", "_nzOutput.", "_NzOut_"); if (shaderStage == ShaderStageType::Vertex && m_environment.flipYPosition) AppendLine("uniform float ", flipYUniformName, ";"); @@ -486,12 +527,12 @@ namespace Nz LeaveScope(); } - void GlslWriter::AppendField(std::size_t scopeId, const std::string& structName, const std::string* memberIdentifier, std::size_t remainingMembers) + void GlslWriter::AppendField(const std::string& structName, const std::string* memberIdentifier, std::size_t remainingMembers) { Append("."); Append(memberIdentifier[0]); - const ShaderAst::AstCache::Identifier* identifier = m_currentState->cache.FindIdentifier(scopeId, structName); + const Identifier* identifier = FindIdentifier(structName); assert(identifier); assert(std::holds_alternative(identifier->value)); @@ -503,7 +544,7 @@ namespace Nz const auto& member = *memberIt; if (remainingMembers > 1) - AppendField(scopeId, std::get(member.type).name, memberIdentifier + 1, remainingMembers - 1); + AppendField(std::get(member.type).name, memberIdentifier + 1, remainingMembers - 1); } void GlslWriter::AppendLine(const std::string& txt) @@ -558,12 +599,10 @@ namespace Nz { Visit(node.structExpr, true); - const ShaderAst::ExpressionType& exprType = GetExpressionType(*node.structExpr, &m_currentState->cache); + const ShaderAst::ExpressionType& exprType = node.structExpr->cachedExpressionType.value(); assert(IsIdentifierType(exprType)); - std::size_t scopeId = m_currentState->cache.GetScopeId(&node); - - AppendField(scopeId, std::get(exprType).name, node.memberIdentifiers.data(), node.memberIdentifiers.size()); + AppendField(std::get(exprType).name, node.memberIdentifiers.data(), node.memberIdentifiers.size()); } void GlslWriter::Visit(ShaderAst::AssignExpression& node) @@ -593,7 +632,9 @@ namespace Nz AppendLine(")"); EnterScope(); + PushScope(); statement.statement->Visit(*this); + PopScope(); LeaveScope(); first = false; @@ -604,7 +645,9 @@ namespace Nz AppendLine("else"); EnterScope(); + PushScope(); node.elseStatement->Visit(*this); + PopScope(); LeaveScope(); } } @@ -698,6 +741,8 @@ namespace Nz void GlslWriter::Visit(ShaderAst::DeclareExternalStatement& node) { + + for (const auto& externalVar : node.externalVars) { std::optional bindingIndex; @@ -729,7 +774,7 @@ namespace Nz EnterScope(); { - const ShaderAst::AstCache::Identifier* identifier = m_currentState->cache.FindIdentifier(0, std::get(externalVar.type).containedType.name); + const Identifier* identifier = FindIdentifier(std::get(externalVar.type).containedType.name); assert(identifier); assert(std::holds_alternative(identifier->value)); @@ -780,15 +825,19 @@ namespace Nz Append(")\n"); EnterScope(); + PushScope(); { for (auto& statement : node.statements) statement->Visit(*this); } + PopScope(); LeaveScope(); } void GlslWriter::Visit(ShaderAst::DeclareStructStatement& node) { + RegisterStruct(node.description); + Append("struct "); AppendLine(node.description.name); EnterScope(); @@ -813,6 +862,8 @@ namespace Nz void GlslWriter::Visit(ShaderAst::DeclareVariableStatement& node) { + RegisterVariable(node.varName, node.varType); + Append(node.varType); Append(" "); Append(node.varName); @@ -871,6 +922,8 @@ namespace Nz void GlslWriter::Visit(ShaderAst::MultiStatement& node) { + PushScope(); + bool first = true; for (const ShaderAst::StatementPtr& statement : node.statements) { @@ -881,6 +934,8 @@ namespace Nz first = false; } + + PopScope(); } void GlslWriter::Visit(ShaderAst::NoOpStatement& /*node*/) diff --git a/src/Nazara/Shader/ShaderAstCloner.cpp b/src/Nazara/Shader/ShaderAstCloner.cpp index 92eae1621..4ebfa9548 100644 --- a/src/Nazara/Shader/ShaderAstCloner.cpp +++ b/src/Nazara/Shader/ShaderAstCloner.cpp @@ -42,7 +42,7 @@ namespace Nz::ShaderAst return PopStatement(); } - std::unique_ptr AstCloner::Clone(DeclareFunctionStatement& node) + StatementPtr AstCloner::Clone(DeclareFunctionStatement& node) { auto clone = std::make_unique(); clone->attributes = node.attributes; @@ -63,6 +63,8 @@ namespace Nz::ShaderAst clone->memberIdentifiers = node.memberIdentifiers; clone->structExpr = CloneExpression(node.structExpr); + clone->cachedExpressionType = node.cachedExpressionType; + PushExpression(std::move(clone)); } @@ -73,6 +75,8 @@ namespace Nz::ShaderAst clone->left = CloneExpression(node.left); clone->right = CloneExpression(node.right); + clone->cachedExpressionType = node.cachedExpressionType; + PushExpression(std::move(clone)); } @@ -83,6 +87,8 @@ namespace Nz::ShaderAst clone->left = CloneExpression(node.left); clone->right = CloneExpression(node.right); + clone->cachedExpressionType = node.cachedExpressionType; + PushExpression(std::move(clone)); } @@ -100,6 +106,8 @@ namespace Nz::ShaderAst clone->expressions[expressionCount++] = CloneExpression(expr); } + clone->cachedExpressionType = node.cachedExpressionType; + PushExpression(std::move(clone)); } @@ -110,6 +118,8 @@ namespace Nz::ShaderAst clone->falsePath = CloneExpression(node.falsePath); clone->truePath = CloneExpression(node.truePath); + clone->cachedExpressionType = node.cachedExpressionType; + PushExpression(std::move(clone)); } @@ -118,6 +128,8 @@ namespace Nz::ShaderAst auto clone = std::make_unique(); clone->value = node.value; + clone->cachedExpressionType = node.cachedExpressionType; + PushExpression(std::move(clone)); } @@ -126,6 +138,8 @@ namespace Nz::ShaderAst auto clone = std::make_unique(); clone->identifier = node.identifier; + clone->cachedExpressionType = node.cachedExpressionType; + PushExpression(std::move(clone)); } @@ -138,6 +152,8 @@ namespace Nz::ShaderAst for (auto& parameter : node.parameters) clone->parameters.push_back(CloneExpression(parameter)); + clone->cachedExpressionType = node.cachedExpressionType; + PushExpression(std::move(clone)); } @@ -148,6 +164,8 @@ namespace Nz::ShaderAst clone->components = node.components; clone->expression = CloneExpression(node.expression); + clone->cachedExpressionType = node.cachedExpressionType; + PushExpression(std::move(clone)); } diff --git a/src/Nazara/Shader/ShaderAstExpressionType.cpp b/src/Nazara/Shader/ShaderAstExpressionType.cpp deleted file mode 100644 index bd87822f7..000000000 --- a/src/Nazara/Shader/ShaderAstExpressionType.cpp +++ /dev/null @@ -1,258 +0,0 @@ -// 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 -#include -#include -#include - -namespace Nz::ShaderAst -{ - ExpressionType ExpressionTypeVisitor::GetExpressionType(Expression& expression, AstCache* cache) - { - m_cache = cache; - ExpressionType type = GetExpressionTypeInternal(expression); - m_cache = nullptr; - - return type; - } - - ExpressionType ExpressionTypeVisitor::GetExpressionTypeInternal(Expression& expression) - { - m_lastExpressionType.reset(); - - Visit(expression); - - assert(m_lastExpressionType.has_value()); - return std::move(*m_lastExpressionType); - } - - ExpressionType ExpressionTypeVisitor::ResolveAlias(Expression& expression, ExpressionType expressionType) - { - if (IsIdentifierType(expressionType)) - { - auto scopeIt = m_cache->scopeIdByNode.find(&expression); - if (scopeIt == m_cache->scopeIdByNode.end()) - throw std::runtime_error("internal error"); - - const AstCache::Identifier* identifier = m_cache->FindIdentifier(scopeIt->second, std::get(expressionType).name); - if (identifier && std::holds_alternative(identifier->value)) - { - const AstCache::Alias& alias = std::get(identifier->value); - return std::visit([&](auto&& arg) -> ShaderAst::ExpressionType - { - using T = std::decay_t; - - if constexpr (std::is_same_v) - return arg; - else - static_assert(AlwaysFalse::value, "non-exhaustive visitor"); - }, alias.value); - } - } - - return expressionType; - } - - void ExpressionTypeVisitor::Visit(Expression& expression) - { - if (m_cache) - { - auto it = m_cache->nodeExpressionType.find(&expression); - if (it != m_cache->nodeExpressionType.end()) - { - m_lastExpressionType = it->second; - return; - } - } - - expression.Visit(*this); - - if (m_cache) - { - assert(m_lastExpressionType.has_value()); - m_cache->nodeExpressionType.emplace(&expression, *m_lastExpressionType); - } - } - - void ExpressionTypeVisitor::Visit(AccessMemberExpression& node) - { - auto scopeIt = m_cache->scopeIdByNode.find(&node); - if (scopeIt == m_cache->scopeIdByNode.end()) - throw std::runtime_error("internal error"); - - ExpressionType expressionType = ResolveAlias(node, GetExpressionTypeInternal(*node.structExpr)); - if (!IsIdentifierType(expressionType)) - throw std::runtime_error("internal error"); - - const AstCache::Identifier* identifier = m_cache->FindIdentifier(scopeIt->second, std::get(expressionType).name); - - throw std::runtime_error("unhandled accessmember expression"); - } - - void ExpressionTypeVisitor::Visit(AssignExpression& node) - { - Visit(*node.left); - } - - void ExpressionTypeVisitor::Visit(BinaryExpression& node) - { - switch (node.op) - { - case BinaryType::Add: - case BinaryType::Subtract: - return Visit(*node.left); - - case BinaryType::Divide: - case BinaryType::Multiply: - { - ExpressionType leftExprType = ResolveAlias(node, GetExpressionTypeInternal(*node.left)); - ExpressionType rightExprType = ResolveAlias(node, GetExpressionTypeInternal(*node.right)); - - if (IsPrimitiveType(leftExprType)) - { - switch (std::get(leftExprType)) - { - case PrimitiveType::Boolean: - m_lastExpressionType = std::move(leftExprType); - break; - - case PrimitiveType::Float32: - case PrimitiveType::Int32: - case PrimitiveType::UInt32: - m_lastExpressionType = std::move(rightExprType); - break; - } - } - else if (IsMatrixType(leftExprType)) - { - if (IsVectorType(rightExprType)) - m_lastExpressionType = std::move(rightExprType); - else - m_lastExpressionType = std::move(leftExprType); - } - else if (IsVectorType(leftExprType)) - m_lastExpressionType = std::move(leftExprType); - else - throw std::runtime_error("validation failure"); - - break; - } - - case BinaryType::CompEq: - case BinaryType::CompGe: - case BinaryType::CompGt: - case BinaryType::CompLe: - case BinaryType::CompLt: - case BinaryType::CompNe: - m_lastExpressionType = PrimitiveType::Boolean; - break; - } - } - - void ExpressionTypeVisitor::Visit(CastExpression& node) - { - m_lastExpressionType = node.targetType; - } - - void ExpressionTypeVisitor::Visit(ConditionalExpression& node) - { - ExpressionType leftExprType = ResolveAlias(node, GetExpressionTypeInternal(*node.truePath)); - assert(leftExprType == ResolveAlias(node, GetExpressionTypeInternal(*node.falsePath))); - - m_lastExpressionType = std::move(leftExprType); - } - - void ExpressionTypeVisitor::Visit(ConstantExpression& node) - { - m_lastExpressionType = std::visit([&](auto&& arg) -> ShaderAst::ExpressionType - { - using T = std::decay_t; - - if constexpr (std::is_same_v) - return PrimitiveType::Boolean; - else if constexpr (std::is_same_v) - return PrimitiveType::Float32; - else if constexpr (std::is_same_v) - return PrimitiveType::Int32; - else if constexpr (std::is_same_v) - return PrimitiveType::UInt32; - else if constexpr (std::is_same_v) - return VectorType{ 2, PrimitiveType::Float32 }; - else if constexpr (std::is_same_v) - return VectorType{ 3, PrimitiveType::Float32 }; - else if constexpr (std::is_same_v) - return VectorType{ 4, PrimitiveType::Float32 }; - else if constexpr (std::is_same_v) - return VectorType{ 2, PrimitiveType::Int32 }; - else if constexpr (std::is_same_v) - return VectorType{ 3, PrimitiveType::Int32 }; - else if constexpr (std::is_same_v) - return VectorType{ 4, PrimitiveType::Int32 }; - else - static_assert(AlwaysFalse::value, "non-exhaustive visitor"); - }, node.value); - } - - void ExpressionTypeVisitor::Visit(IdentifierExpression& node) - { - assert(m_cache); - - auto scopeIt = m_cache->scopeIdByNode.find(&node); - if (scopeIt == m_cache->scopeIdByNode.end()) - throw std::runtime_error("internal error"); - - const AstCache::Identifier* identifier = m_cache->FindIdentifier(scopeIt->second, node.identifier); - if (!identifier || !std::holds_alternative(identifier->value)) - throw std::runtime_error("internal error"); - - m_lastExpressionType = ResolveAlias(node, std::get(identifier->value).type); - } - - void ExpressionTypeVisitor::Visit(IntrinsicExpression& node) - { - switch (node.intrinsic) - { - case IntrinsicType::CrossProduct: - Visit(*node.parameters.front()); - break; - - case IntrinsicType::DotProduct: - m_lastExpressionType = PrimitiveType::Float32; - break; - - case IntrinsicType::SampleTexture: - { - if (node.parameters.empty()) - throw std::runtime_error("validation failure"); - - ExpressionType firstParamType = ResolveAlias(node, GetExpressionTypeInternal(*node.parameters.front())); - - if (!IsSamplerType(firstParamType)) - throw std::runtime_error("validation failure"); - - const auto& sampler = std::get(firstParamType); - - m_lastExpressionType = VectorType{ - 4, - sampler.sampledType - }; - - break; - } - } - } - - void ExpressionTypeVisitor::Visit(SwizzleExpression& node) - { - ExpressionType exprType = GetExpressionTypeInternal(*node.expression); - - if (IsMatrixType(exprType)) - m_lastExpressionType = std::get(exprType).type; - else if (IsVectorType(exprType)) - m_lastExpressionType = std::get(exprType).type; - else - throw std::runtime_error("validation failure"); - } -} diff --git a/src/Nazara/Shader/ShaderAstOptimizer.cpp b/src/Nazara/Shader/ShaderAstOptimizer.cpp index c83ae1412..3c67240a7 100644 --- a/src/Nazara/Shader/ShaderAstOptimizer.cpp +++ b/src/Nazara/Shader/ShaderAstOptimizer.cpp @@ -4,7 +4,6 @@ #include #include -#include #include #include #include @@ -453,8 +452,11 @@ namespace Nz::ShaderAst { auto& constant = static_cast(*cond); - assert(IsPrimitiveType(GetExpressionType(constant))); - assert(std::get(GetExpressionType(constant)) == PrimitiveType::Boolean); + assert(constant.cachedExpressionType); + const ExpressionType& constantType = constant.cachedExpressionType.value(); + + assert(IsPrimitiveType(constantType)); + assert(std::get(constantType) == PrimitiveType::Boolean); bool cValue = std::get(constant.value); if (!cValue) diff --git a/src/Nazara/Shader/ShaderAstScopedVisitor.cpp b/src/Nazara/Shader/ShaderAstScopedVisitor.cpp new file mode 100644 index 000000000..cc1aec980 --- /dev/null +++ b/src/Nazara/Shader/ShaderAstScopedVisitor.cpp @@ -0,0 +1,110 @@ +// 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 +#include + +namespace Nz::ShaderAst +{ + void AstScopedVisitor::ScopedVisit(StatementPtr& nodePtr) + { + PushScope(); //< Global scope + { + nodePtr->Visit(*this); + } + PopScope(); + } + + void AstScopedVisitor::Visit(BranchStatement& node) + { + for (auto& cond : node.condStatements) + { + PushScope(); + { + cond.condition->Visit(*this); + cond.statement->Visit(*this); + } + PopScope(); + } + + if (node.elseStatement) + { + PushScope(); + { + node.elseStatement->Visit(*this); + } + PopScope(); + } + } + + void AstScopedVisitor::Visit(ConditionalStatement& node) + { + PushScope(); + { + AstRecursiveVisitor::Visit(node); + } + PopScope(); + } + + void AstScopedVisitor::Visit(DeclareExternalStatement& node) + { + for (auto& extVar : node.externalVars) + { + ExpressionType subType = extVar.type; + if (IsUniformType(subType)) + subType = IdentifierType{ std::get(subType).containedType }; + + RegisterVariable(extVar.name, std::move(subType)); + } + + AstRecursiveVisitor::Visit(node); + } + + void AstScopedVisitor::Visit(DeclareFunctionStatement& node) + { + PushScope(); + { + for (auto& parameter : node.parameters) + RegisterVariable(parameter.name, parameter.type); + + AstRecursiveVisitor::Visit(node); + } + PopScope(); + } + + void AstScopedVisitor::Visit(DeclareStructStatement& node) + { + RegisterStruct(node.description); + + AstRecursiveVisitor::Visit(node); + } + + void AstScopedVisitor::Visit(DeclareVariableStatement& node) + { + RegisterVariable(node.varName, node.varType); + + AstRecursiveVisitor::Visit(node); + } + + void AstScopedVisitor::Visit(MultiStatement& node) + { + PushScope(); + { + AstRecursiveVisitor::Visit(node); + } + PopScope(); + } + + void AstScopedVisitor::PushScope() + { + m_scopeSizes.push_back(m_identifiersInScope.size()); + } + + void AstScopedVisitor::PopScope() + { + assert(!m_scopeSizes.empty()); + m_identifiersInScope.resize(m_scopeSizes.back()); + m_scopeSizes.pop_back(); + } +} diff --git a/src/Nazara/Shader/ShaderAstValidator.cpp b/src/Nazara/Shader/ShaderAstValidator.cpp index 8293870e9..57610a357 100644 --- a/src/Nazara/Shader/ShaderAstValidator.cpp +++ b/src/Nazara/Shader/ShaderAstValidator.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include #include @@ -27,29 +26,21 @@ namespace Nz::ShaderAst struct AstValidator::Context { - //const ShaderAst::Function* currentFunction; - std::optional activeScopeId; + std::array entryFunctions = {}; std::unordered_set declaredExternalVar; - std::unordered_set usedBindingIndexes;; - AstCache* cache; + std::unordered_set usedBindingIndexes; }; - bool AstValidator::Validate(StatementPtr& node, std::string* error, AstCache* cache) + bool AstValidator::Validate(StatementPtr& node, std::string* error) { try { - AstCache dummy; - Context currentContext; - currentContext.cache = (cache) ? cache : &dummy; m_context = ¤tContext; CallOnExit resetContext([&] { m_context = nullptr; }); - EnterScope(); - node->Visit(*this); - ExitScope(); - + ScopedVisit(node); return true; } catch (const AstError& e) @@ -61,6 +52,12 @@ namespace Nz::ShaderAst } } + const ExpressionType& AstValidator::GetExpressionType(Expression& expression) + { + assert(expression.cachedExpressionType); + return ResolveAlias(expression.cachedExpressionType.value()); + } + Expression& AstValidator::MandatoryExpr(ExpressionPtr& node) { if (!node) @@ -79,7 +76,7 @@ namespace Nz::ShaderAst void AstValidator::TypeMustMatch(ExpressionPtr& left, ExpressionPtr& right) { - return TypeMustMatch(GetExpressionType(*left, m_context->cache), GetExpressionType(*right, m_context->cache)); + return TypeMustMatch(GetExpressionType(*left), GetExpressionType(*right)); } void AstValidator::TypeMustMatch(const ExpressionType& left, const ExpressionType& right) @@ -90,7 +87,7 @@ namespace Nz::ShaderAst ExpressionType AstValidator::CheckField(const std::string& structName, const std::string* memberIdentifier, std::size_t remainingMembers) { - const AstCache::Identifier* identifier = m_context->cache->FindIdentifier(*m_context->activeScopeId, structName); + const Identifier* identifier = FindIdentifier(structName); if (!identifier) throw AstError{ "unknown identifier " + structName }; @@ -111,81 +108,69 @@ namespace Nz::ShaderAst return member.type; } - AstCache::Scope& AstValidator::EnterScope() + const ExpressionType& AstValidator::ResolveAlias(const ExpressionType& expressionType) { - std::size_t newScopeId = m_context->cache->scopes.size(); + if (!IsIdentifierType(expressionType)) + return expressionType; - std::optional previousScope = m_context->activeScopeId; + const Identifier* identifier = FindIdentifier(std::get(expressionType).name); + if (identifier && std::holds_alternative(identifier->value)) + { + const Alias& alias = std::get(identifier->value); + return std::visit([&](auto&& arg) -> const ShaderAst::ExpressionType& + { + using T = std::decay_t; - auto& newScope = m_context->cache->scopes.emplace_back(); - newScope.parentScopeIndex = previousScope; + if constexpr (std::is_same_v) + return arg; + else + static_assert(AlwaysFalse::value, "non-exhaustive visitor"); + }, alias.value); + } - m_context->activeScopeId = newScopeId; - return m_context->cache->scopes[newScopeId]; - } - - void AstValidator::ExitScope() - { - assert(m_context->activeScopeId); - auto& previousScope = m_context->cache->scopes[*m_context->activeScopeId]; - m_context->activeScopeId = previousScope.parentScopeIndex; - } - - void AstValidator::RegisterExpressionType(Expression& node, ExpressionType expressionType) - { - m_context->cache->nodeExpressionType[&node] = std::move(expressionType); - } - - void AstValidator::RegisterScope(Node& node) - { - if (m_context->activeScopeId) - m_context->cache->scopeIdByNode[&node] = *m_context->activeScopeId; + return expressionType; } void AstValidator::Visit(AccessMemberExpression& node) { - RegisterScope(node); - // Register expressions types - AstRecursiveVisitor::Visit(node); + AstScopedVisitor::Visit(node); - ExpressionType exprType = GetExpressionType(MandatoryExpr(node.structExpr), m_context->cache); + ExpressionType exprType = GetExpressionType(MandatoryExpr(node.structExpr)); if (!IsIdentifierType(exprType)) throw AstError{ "expression is not a structure" }; const std::string& structName = std::get(exprType).name; - RegisterExpressionType(node, CheckField(structName, node.memberIdentifiers.data(), node.memberIdentifiers.size())); + node.cachedExpressionType = CheckField(structName, node.memberIdentifiers.data(), node.memberIdentifiers.size()); } void AstValidator::Visit(AssignExpression& node) { - RegisterScope(node); - MandatoryExpr(node.left); MandatoryExpr(node.right); // Register expressions types - AstRecursiveVisitor::Visit(node); + AstScopedVisitor::Visit(node); TypeMustMatch(node.left, node.right); if (GetExpressionCategory(*node.left) != ExpressionCategory::LValue) throw AstError { "Assignation is only possible with a l-value" }; + + node.cachedExpressionType = GetExpressionType(*node.right); } void AstValidator::Visit(BinaryExpression& node) { - RegisterScope(node); - // Register expression type - AstRecursiveVisitor::Visit(node); + AstScopedVisitor::Visit(node); - ExpressionType leftExprType = GetExpressionType(MandatoryExpr(node.left), m_context->cache); + ExpressionType leftExprType = GetExpressionType(MandatoryExpr(node.left)); if (!IsPrimitiveType(leftExprType) && !IsMatrixType(leftExprType) && !IsVectorType(leftExprType)) throw AstError{ "left expression type does not support binary operation" }; - ExpressionType rightExprType = GetExpressionType(MandatoryExpr(node.right), m_context->cache); + ExpressionType rightExprType = GetExpressionType(MandatoryExpr(node.right)); if (!IsPrimitiveType(rightExprType) && !IsMatrixType(rightExprType) && !IsVectorType(rightExprType)) throw AstError{ "right expression type does not support binary operation" }; @@ -201,12 +186,18 @@ namespace Nz::ShaderAst if (leftType == PrimitiveType::Boolean) throw AstError{ "this operation is not supported for booleans" }; - [[fallthrough]]; + TypeMustMatch(node.left, node.right); + + node.cachedExpressionType = PrimitiveType::Boolean; + break; + case BinaryType::Add: case BinaryType::CompEq: case BinaryType::CompNe: case BinaryType::Subtract: TypeMustMatch(node.left, node.right); + + node.cachedExpressionType = leftExprType; break; case BinaryType::Multiply: @@ -219,9 +210,20 @@ namespace Nz::ShaderAst case PrimitiveType::UInt32: { if (IsMatrixType(rightExprType)) + { TypeMustMatch(leftType, std::get(rightExprType).type); + node.cachedExpressionType = rightExprType; + } + else if (IsPrimitiveType(rightExprType)) + { + TypeMustMatch(leftType, rightExprType); + node.cachedExpressionType = leftExprType; + } else if (IsVectorType(rightExprType)) + { TypeMustMatch(leftType, std::get(rightExprType).type); + node.cachedExpressionType = rightExprType; + } else throw AstError{ "incompatible types" }; @@ -248,18 +250,29 @@ namespace Nz::ShaderAst case BinaryType::CompLt: case BinaryType::CompEq: case BinaryType::CompNe: + TypeMustMatch(node.left, node.right); + node.cachedExpressionType = PrimitiveType::Boolean; + break; + case BinaryType::Add: case BinaryType::Subtract: TypeMustMatch(node.left, node.right); + node.cachedExpressionType = leftExprType; break; case BinaryType::Multiply: case BinaryType::Divide: { if (IsMatrixType(rightExprType)) + { TypeMustMatch(leftExprType, rightExprType); + node.cachedExpressionType = leftExprType; //< FIXME + } else if (IsPrimitiveType(rightExprType)) + { TypeMustMatch(leftType.type, rightExprType); + node.cachedExpressionType = leftExprType; + } else if (IsVectorType(rightExprType)) { const VectorType& rightType = std::get(rightExprType); @@ -267,6 +280,8 @@ namespace Nz::ShaderAst if (leftType.columnCount != rightType.componentCount) throw AstError{ "incompatible types" }; + + node.cachedExpressionType = rightExprType; } else throw AstError{ "incompatible types" }; @@ -275,7 +290,7 @@ namespace Nz::ShaderAst } else if (IsVectorType(leftExprType)) { - const MatrixType& leftType = std::get(leftExprType); + const VectorType& leftType = std::get(leftExprType); switch (node.op) { case BinaryType::CompGe: @@ -284,16 +299,29 @@ namespace Nz::ShaderAst case BinaryType::CompLt: case BinaryType::CompEq: case BinaryType::CompNe: + TypeMustMatch(node.left, node.right); + node.cachedExpressionType = PrimitiveType::Boolean; + break; + case BinaryType::Add: case BinaryType::Subtract: TypeMustMatch(node.left, node.right); + node.cachedExpressionType = leftExprType; break; case BinaryType::Multiply: case BinaryType::Divide: { if (IsPrimitiveType(rightExprType)) + { TypeMustMatch(leftType.type, rightExprType); + node.cachedExpressionType = rightExprType; + } + else if (IsVectorType(rightExprType)) + { + TypeMustMatch(leftType, rightExprType); + node.cachedExpressionType = rightExprType; + } else throw AstError{ "incompatible types" }; } @@ -303,11 +331,9 @@ namespace Nz::ShaderAst void AstValidator::Visit(CastExpression& node) { - RegisterScope(node); + AstScopedVisitor::Visit(node); - AstRecursiveVisitor::Visit(node); - - auto GetComponentCount = [](const ExpressionType& exprType) -> unsigned int + auto GetComponentCount = [](const ExpressionType& exprType) -> std::size_t { if (IsPrimitiveType(exprType)) return 1; @@ -317,15 +343,15 @@ namespace Nz::ShaderAst throw AstError{ "wut" }; }; - unsigned int componentCount = 0; - unsigned int requiredComponents = GetComponentCount(node.targetType); + std::size_t componentCount = 0; + std::size_t requiredComponents = GetComponentCount(node.targetType); for (auto& exprPtr : node.expressions) { if (!exprPtr) break; - ExpressionType exprType = GetExpressionType(*exprPtr, m_context->cache); + ExpressionType exprType = GetExpressionType(*exprPtr); if (!IsPrimitiveType(exprType) && !IsVectorType(exprType)) throw AstError{ "incompatible type" }; @@ -334,6 +360,40 @@ namespace Nz::ShaderAst if (componentCount != requiredComponents) throw AstError{ "component count doesn't match required component count" }; + + node.cachedExpressionType = node.targetType; + } + + void AstValidator::Visit(ConstantExpression& node) + { + node.cachedExpressionType = std::visit([&](auto&& arg) -> ShaderAst::ExpressionType + { + using T = std::decay_t; + + if constexpr (std::is_same_v) + return PrimitiveType::Boolean; + else if constexpr (std::is_same_v) + return PrimitiveType::Float32; + else if constexpr (std::is_same_v) + return PrimitiveType::Int32; + else if constexpr (std::is_same_v) + return PrimitiveType::UInt32; + else if constexpr (std::is_same_v) + return VectorType{ 2, PrimitiveType::Float32 }; + else if constexpr (std::is_same_v) + return VectorType{ 3, PrimitiveType::Float32 }; + else if constexpr (std::is_same_v) + return VectorType{ 4, PrimitiveType::Float32 }; + else if constexpr (std::is_same_v) + return VectorType{ 2, PrimitiveType::Int32 }; + else if constexpr (std::is_same_v) + return VectorType{ 3, PrimitiveType::Int32 }; + else if constexpr (std::is_same_v) + return VectorType{ 4, PrimitiveType::Int32 }; + else + static_assert(AlwaysFalse::value, "non-exhaustive visitor"); + }, node.value); + } void AstValidator::Visit(ConditionalExpression& node) @@ -341,37 +401,31 @@ namespace Nz::ShaderAst MandatoryExpr(node.truePath); MandatoryExpr(node.falsePath); - RegisterScope(node); + AstScopedVisitor::Visit(node); - AstRecursiveVisitor::Visit(node); + ExpressionType leftExprType = GetExpressionType(*node.truePath); + if (leftExprType != GetExpressionType(*node.falsePath)) + throw AstError{ "true path type must match false path type" }; + + node.cachedExpressionType = leftExprType; //if (m_shader.FindConditionByName(node.conditionName) == ShaderAst::InvalidCondition) // throw AstError{ "condition not found" }; } - void AstValidator::Visit(ConstantExpression& node) - { - RegisterScope(node); - } - void AstValidator::Visit(IdentifierExpression& node) { assert(m_context); - if (!m_context->activeScopeId) - throw AstError{ "no scope" }; - - RegisterScope(node); - - const AstCache::Identifier* identifier = m_context->cache->FindIdentifier(*m_context->activeScopeId, node.identifier); + const Identifier* identifier = FindIdentifier(node.identifier); if (!identifier) - throw AstError{ "Unknown variable " + node.identifier }; + throw AstError{ "Unknown identifier " + node.identifier }; + + node.cachedExpressionType = ResolveAlias(std::get(identifier->value).type); } void AstValidator::Visit(IntrinsicExpression& node) { - RegisterScope(node); - - AstRecursiveVisitor::Visit(node); + AstScopedVisitor::Visit(node); switch (node.intrinsic) { @@ -384,10 +438,11 @@ namespace Nz::ShaderAst for (auto& param : node.parameters) MandatoryExpr(param); - ExpressionType type = GetExpressionType(*node.parameters.front(), m_context->cache); + ExpressionType type = GetExpressionType(*node.parameters.front()); + for (std::size_t i = 1; i < node.parameters.size(); ++i) { - if (type != GetExpressionType(MandatoryExpr(node.parameters[i]), m_context->cache)) + if (type != GetExpressionType(MandatoryExpr(node.parameters[i]))) throw AstError{ "All type must match" }; } @@ -402,11 +457,11 @@ namespace Nz::ShaderAst for (auto& param : node.parameters) MandatoryExpr(param); - if (!IsSamplerType(GetExpressionType(*node.parameters[0], m_context->cache))) + if (!IsSamplerType(GetExpressionType(*node.parameters[0]))) throw AstError{ "First parameter must be a sampler" }; - if (!IsVectorType(GetExpressionType(*node.parameters[1], m_context->cache))) - throw AstError{ "First parameter must be a vector" }; + if (!IsVectorType(GetExpressionType(*node.parameters[1]))) + throw AstError{ "Second parameter must be a vector" }; } } @@ -414,63 +469,89 @@ namespace Nz::ShaderAst { case IntrinsicType::CrossProduct: { - if (GetExpressionType(*node.parameters[0]) != ExpressionType{ VectorType{ 3, PrimitiveType::Float32 } }) + ExpressionType type = GetExpressionType(*node.parameters.front()); + if (type != ExpressionType{ VectorType{ 3, PrimitiveType::Float32 } }) throw AstError{ "CrossProduct only works with vec3 expressions" }; + node.cachedExpressionType = std::move(type); break; } case IntrinsicType::DotProduct: + { + ExpressionType type = GetExpressionType(*node.parameters.front()); + if (!IsVectorType(type)) + throw AstError{ "DotProduct expects vector types" }; + + node.cachedExpressionType = std::get(type).type; break; + } + + case IntrinsicType::SampleTexture: + { + node.cachedExpressionType = VectorType{ 4, std::get(GetExpressionType(*node.parameters.front())).sampledType }; + break; + } } } void AstValidator::Visit(SwizzleExpression& node) { - RegisterScope(node); - if (node.componentCount > 4) throw AstError{ "Cannot swizzle more than four elements" }; - ExpressionType exprType = GetExpressionType(MandatoryExpr(node.expression), m_context->cache); - if (!IsPrimitiveType(exprType) && !IsVectorType(exprType)) - throw AstError{ "Cannot swizzle this type" }; + MandatoryExpr(node.expression); - AstRecursiveVisitor::Visit(node); + AstScopedVisitor::Visit(node); + + ExpressionType exprType = GetExpressionType(*node.expression); + if (IsPrimitiveType(exprType) || IsVectorType(exprType)) + { + PrimitiveType baseType; + if (IsPrimitiveType(exprType)) + baseType = std::get(exprType); + else + baseType = std::get(exprType).type; + + if (node.componentCount > 1) + { + node.cachedExpressionType = VectorType{ + node.componentCount, + baseType + }; + } + else + node.cachedExpressionType = baseType; + } + else + throw AstError{ "Cannot swizzle this type" }; } void AstValidator::Visit(BranchStatement& node) { - RegisterScope(node); - for (auto& condStatement : node.condStatements) { - ExpressionType condType = GetExpressionType(MandatoryExpr(condStatement.condition), m_context->cache); + ExpressionType condType = GetExpressionType(MandatoryExpr(condStatement.condition)); if (!IsPrimitiveType(condType) || std::get(condType) != PrimitiveType::Boolean) throw AstError{ "if expression must resolve to boolean type" }; MandatoryStatement(condStatement.statement); } - AstRecursiveVisitor::Visit(node); + AstScopedVisitor::Visit(node); } void AstValidator::Visit(ConditionalStatement& node) { MandatoryStatement(node.statement); - RegisterScope(node); - - AstRecursiveVisitor::Visit(node); + AstScopedVisitor::Visit(node); //if (m_shader.FindConditionByName(node.conditionName) == ShaderAst::InvalidCondition) // throw AstError{ "condition not found" }; } void AstValidator::Visit(DeclareExternalStatement& node) { - RegisterScope(node); - auto& scope = m_context->cache->scopes[*m_context->activeScopeId]; - for (const auto& [attributeType, arg] : node.attributes) { switch (attributeType) @@ -513,7 +594,7 @@ namespace Nz::ShaderAst throw AstError{ "attribute layout requires a string parameter" }; if (std::get(arg) != "std140") - throw AstError{ "unknow layout type" }; + throw AstError{ "unknown layout type" }; hasLayout = true; break; @@ -528,14 +609,9 @@ namespace Nz::ShaderAst throw AstError{ "External variable " + extVar.name + " is already declared" }; m_context->declaredExternalVar.insert(extVar.name); - - ExpressionType subType = extVar.type; - if (IsUniformType(subType)) - subType = IdentifierType{ std::get(subType).containedType }; - - auto& identifier = scope.identifiers.emplace_back(); - identifier = AstCache::Identifier{ extVar.name, AstCache::Variable { std::move(subType) } }; } + + AstScopedVisitor::Visit(node); } void AstValidator::Visit(DeclareFunctionStatement& node) @@ -561,10 +637,10 @@ namespace Nz::ShaderAst ShaderStageType stageType = it->second; - if (m_context->cache->entryFunctions[UnderlyingCast(stageType)]) + if (m_context->entryFunctions[UnderlyingCast(stageType)]) throw AstError{ "the same entry type has been defined multiple times" }; - m_context->cache->entryFunctions[UnderlyingCast(it->second)] = &node; + m_context->entryFunctions[UnderlyingCast(it->second)] = &node; if (node.parameters.size() > 1) throw AstError{ "entry functions can either take one struct parameter or no parameter" }; @@ -578,103 +654,41 @@ namespace Nz::ShaderAst } } - auto& scope = EnterScope(); - RegisterScope(node); - - for (auto& parameter : node.parameters) - { - auto& identifier = scope.identifiers.emplace_back(); - identifier = AstCache::Identifier{ parameter.name, AstCache::Variable { parameter.type } }; - } - for (auto& statement : node.statements) - MandatoryStatement(statement).Visit(*this); + MandatoryStatement(statement); - ExitScope(); + AstScopedVisitor::Visit(node); } void AstValidator::Visit(DeclareStructStatement& node) { assert(m_context); - if (!m_context->activeScopeId) - throw AstError{ "cannot declare variable without scope" }; - - RegisterScope(node); - //TODO: check members attributes - auto& scope = m_context->cache->scopes[*m_context->activeScopeId]; - - auto& identifier = scope.identifiers.emplace_back(); - identifier = AstCache::Identifier{ node.description.name, node.description }; - - AstRecursiveVisitor::Visit(node); - } - - void AstValidator::Visit(DeclareVariableStatement& node) - { - assert(m_context); - - if (!m_context->activeScopeId) - throw AstError{ "cannot declare variable without scope" }; - - RegisterScope(node); - - auto& scope = m_context->cache->scopes[*m_context->activeScopeId]; - - auto& identifier = scope.identifiers.emplace_back(); - identifier = AstCache::Identifier{ node.varName, AstCache::Variable { node.varType } }; - - AstRecursiveVisitor::Visit(node); + AstScopedVisitor::Visit(node); } void AstValidator::Visit(ExpressionStatement& node) { - RegisterScope(node); - MandatoryExpr(node.expression); - AstRecursiveVisitor::Visit(node); + AstScopedVisitor::Visit(node); } void AstValidator::Visit(MultiStatement& node) { assert(m_context); - EnterScope(); - - RegisterScope(node); - for (auto& statement : node.statements) MandatoryStatement(statement); - ExitScope(); - - AstRecursiveVisitor::Visit(node); + AstScopedVisitor::Visit(node); } - void AstValidator::Visit(ReturnStatement& node) - { - RegisterScope(node); - - /*if (m_context->currentFunction->returnType != ShaderExpressionType(BasicType::Void)) - { - if (GetExpressionType(MandatoryExpr(node.returnExpr)) != m_context->currentFunction->returnType) - throw AstError{ "Return type doesn't match function return type" }; - } - else - { - if (node.returnExpr) - throw AstError{ "Unexpected expression for return (function doesn't return)" }; - }*/ - - AstRecursiveVisitor::Visit(node); - } - - bool ValidateAst(StatementPtr& node, std::string* error, AstCache* cache) + bool ValidateAst(StatementPtr& node, std::string* error) { AstValidator validator; - return validator.Validate(node, error, cache); + return validator.Validate(node, error); } } diff --git a/src/Nazara/Shader/SpirvAstVisitor.cpp b/src/Nazara/Shader/SpirvAstVisitor.cpp index d559e7965..28aca39ca 100644 --- a/src/Nazara/Shader/SpirvAstVisitor.cpp +++ b/src/Nazara/Shader/SpirvAstVisitor.cpp @@ -4,7 +4,6 @@ #include #include -#include #include #include #include @@ -39,13 +38,13 @@ namespace Nz void SpirvAstVisitor::Visit(ShaderAst::BinaryExpression& node) { - ShaderAst::ExpressionType resultExprType = ShaderAst::GetExpressionType(node, m_cache); + ShaderAst::ExpressionType resultExprType = GetExpressionType(node); assert(IsPrimitiveType(resultExprType)); - ShaderAst::ExpressionType leftExprType = ShaderAst::GetExpressionType(*node.left, m_cache); + ShaderAst::ExpressionType leftExprType = GetExpressionType(*node.left); assert(IsPrimitiveType(leftExprType)); - ShaderAst::ExpressionType rightExprType = ShaderAst::GetExpressionType(*node.right, m_cache); + ShaderAst::ExpressionType rightExprType = GetExpressionType(*node.right); assert(IsPrimitiveType(rightExprType)); ShaderAst::PrimitiveType resultType = std::get(resultExprType); @@ -582,7 +581,7 @@ namespace Nz { case ShaderAst::IntrinsicType::DotProduct: { - ShaderAst::ExpressionType vecExprType = GetExpressionType(*node.parameters[0], m_cache); + ShaderAst::ExpressionType vecExprType = GetExpressionType(*node.parameters[0]); assert(IsVectorType(vecExprType)); const ShaderAst::VectorType& vecType = std::get(vecExprType); @@ -626,7 +625,7 @@ namespace Nz void SpirvAstVisitor::Visit(ShaderAst::SwizzleExpression& node) { - ShaderAst::ExpressionType targetExprType = ShaderAst::GetExpressionType(node, m_cache); + ShaderAst::ExpressionType targetExprType = GetExpressionType(node); assert(IsPrimitiveType(targetExprType)); ShaderAst::PrimitiveType targetType = std::get(targetExprType); diff --git a/src/Nazara/Shader/SpirvConstantCache.cpp b/src/Nazara/Shader/SpirvConstantCache.cpp index cc3421ac2..2aff0d642 100644 --- a/src/Nazara/Shader/SpirvConstantCache.cpp +++ b/src/Nazara/Shader/SpirvConstantCache.cpp @@ -50,6 +50,11 @@ namespace Nz return Compare(lhs.parameters, rhs.parameters) && Compare(lhs.returnType, rhs.returnType); } + bool Compare(const Identifier& lhs, const Identifier& rhs) const + { + return lhs.name == rhs.name; + } + bool Compare(const Image& lhs, const Image& rhs) const { return lhs.arrayed == rhs.arrayed @@ -226,6 +231,11 @@ namespace Nz void Register(const Integer&) {} void Register(const Void&) {} + void Register(const Identifier& identifier) + { + Register(identifier); + } + void Register(const Image& image) { Register(image.sampledType); @@ -456,6 +466,11 @@ namespace Nz UInt32 SpirvConstantCache::Register(Type t) { AnyType& type = t.type; + if (std::holds_alternative(type)) + { + assert(m_identifierCallback); + return Register(*m_identifierCallback(std::get(type).name)); + } DepRegisterer registerer(*this); registerer.Register(type); @@ -487,6 +502,11 @@ namespace Nz return it.value(); } + void SpirvConstantCache::SetIdentifierCallback(IdentifierCallback callback) + { + m_identifierCallback = std::move(callback); + } + void SpirvConstantCache::Write(SpirvSection& annotations, SpirvSection& constants, SpirvSection& debugInfos) { for (auto&& [object, id] : m_internal->ids) @@ -597,7 +617,7 @@ namespace Nz return std::make_shared(Pointer{ BuildType(type), storageClass - }); + }); } auto SpirvConstantCache::BuildType(const ShaderAst::ExpressionType& type) -> TypePtr @@ -605,37 +625,16 @@ namespace Nz return std::visit([&](auto&& arg) -> TypePtr { return BuildType(arg); - /*else if constexpr (std::is_same_v) - { - // Register struct members type - const auto& structs = shader.GetStructs(); - auto it = std::find_if(structs.begin(), structs.end(), [&](const auto& s) { return s.name == arg; }); - if (it == structs.end()) - throw std::runtime_error("struct " + arg + " has not been defined"); - - const ShaderAst::Struct& s = *it; - - Structure sType; - sType.name = s.name; - - for (const auto& member : s.members) - { - auto& sMembers = sType.members.emplace_back(); - sMembers.name = member.name; - sMembers.type = BuildType(shader, member.type); - } - - return std::make_shared(std::move(sType)); - return nullptr; - } - else - static_assert(AlwaysFalse::value, "non-exhaustive visitor");*/ }, type); } auto SpirvConstantCache::BuildType(const ShaderAst::IdentifierType& type) -> TypePtr { - throw std::runtime_error("unexpected type"); + return std::make_shared( + Identifier{ + type.name + } + ); } auto SpirvConstantCache::BuildType(const ShaderAst::PrimitiveType& type) -> TypePtr @@ -691,6 +690,21 @@ namespace Nz return std::make_shared(SampledImage{ std::make_shared(imageType) }); } + auto SpirvConstantCache::BuildType(const ShaderAst::StructDescription& structDesc) -> TypePtr + { + Structure sType; + sType.name = structDesc.name; + + for (const auto& member : structDesc.members) + { + auto& sMembers = sType.members.emplace_back(); + sMembers.name = member.name; + sMembers.type = BuildType(member.type); + } + + return std::make_shared(std::move(sType)); + } + auto SpirvConstantCache::BuildType(const ShaderAst::VectorType& type) -> TypePtr { return std::make_shared(Vector{ BuildType(type.type), UInt32(type.componentCount) }); @@ -767,6 +781,8 @@ namespace Nz appender(GetId(*param)); }); } + else if constexpr (std::is_same_v) + throw std::runtime_error("unexpected identifier"); else if constexpr (std::is_same_v) { UInt32 depth; @@ -915,6 +931,8 @@ namespace Nz } else if constexpr (std::is_same_v) throw std::runtime_error("unexpected function as struct member"); + else if constexpr (std::is_same_v) + throw std::runtime_error("unexpected identifier"); else if constexpr (std::is_same_v || std::is_same_v) throw std::runtime_error("unexpected opaque type as struct member"); else if constexpr (std::is_same_v) diff --git a/src/Nazara/Shader/SpirvWriter.cpp b/src/Nazara/Shader/SpirvWriter.cpp index fb1ad3725..0627c569e 100644 --- a/src/Nazara/Shader/SpirvWriter.cpp +++ b/src/Nazara/Shader/SpirvWriter.cpp @@ -25,18 +25,26 @@ namespace Nz { namespace { - class PreVisitor : public ShaderAst::AstRecursiveVisitor + class PreVisitor : public ShaderAst::AstScopedVisitor { public: using ExtInstList = std::unordered_set; using LocalContainer = std::unordered_set; using FunctionContainer = std::vector>; - PreVisitor(ShaderAst::AstCache* cache, const SpirvWriter::States& conditions, SpirvConstantCache& constantCache) : - m_cache(cache), + PreVisitor(const SpirvWriter::States& conditions, SpirvConstantCache& constantCache) : m_conditions(conditions), m_constantCache(constantCache) { + m_constantCache.SetIdentifierCallback([&](const std::string& identifierName) + { + const Identifier* identifier = FindIdentifier(identifierName); + if (!identifier) + throw std::runtime_error("invalid identifier " + identifierName); + + assert(std::holds_alternative(identifier->value)); + return SpirvConstantCache::BuildType(std::get(identifier->value)); + }); } void Visit(ShaderAst::AccessMemberExpression& node) override @@ -74,7 +82,7 @@ namespace Nz m_constantCache.Register(*SpirvConstantCache::BuildConstant(arg)); }, node.value); - AstRecursiveVisitor::Visit(node); + AstScopedVisitor::Visit(node); } void Visit(ShaderAst::DeclareFunctionStatement& node) override @@ -87,11 +95,13 @@ namespace Nz m_constantCache.Register(*SpirvConstantCache::BuildFunctionType(node.returnType, parameterTypes)); - AstRecursiveVisitor::Visit(node); + AstScopedVisitor::Visit(node); } void Visit(ShaderAst::DeclareStructStatement& node) override { + AstScopedVisitor::Visit(node); + SpirvConstantCache::Structure sType; sType.name = node.description.name; @@ -107,21 +117,21 @@ namespace Nz void Visit(ShaderAst::DeclareVariableStatement& node) override { - m_constantCache.Register(*SpirvConstantCache::BuildType(node.varType)); + AstScopedVisitor::Visit(node); - AstRecursiveVisitor::Visit(node); + m_constantCache.Register(*SpirvConstantCache::BuildType(node.varType)); } void Visit(ShaderAst::IdentifierExpression& node) override { - m_constantCache.Register(*SpirvConstantCache::BuildType(GetExpressionType(node, m_cache))); + m_constantCache.Register(*SpirvConstantCache::BuildType(node.cachedExpressionType.value())); - AstRecursiveVisitor::Visit(node); + AstScopedVisitor::Visit(node); } void Visit(ShaderAst::IntrinsicExpression& node) override { - AstRecursiveVisitor::Visit(node); + AstScopedVisitor::Visit(node); switch (node.intrinsic) { @@ -140,7 +150,6 @@ namespace Nz FunctionContainer funcs; private: - ShaderAst::AstCache* m_cache; const SpirvWriter::States& m_conditions; SpirvConstantCache& m_constantCache; }; @@ -214,7 +223,7 @@ namespace Nz std::vector SpirvWriter::Generate(ShaderAst::StatementPtr& shader, const States& conditions) { std::string error; - if (!ShaderAst::ValidateAst(shader, &error, &m_context.cache)) + if (!ShaderAst::ValidateAst(shader, &error)) throw std::runtime_error("Invalid shader AST: " + error); m_context.states = &conditions; @@ -229,7 +238,7 @@ namespace Nz ShaderAst::AstCloner cloner; // Register all extended instruction sets - PreVisitor preVisitor(&m_context.cache, conditions, state.constantTypeCache); + PreVisitor preVisitor(conditions, state.constantTypeCache); shader->Visit(preVisitor); for (const std::string& extInst : preVisitor.extInsts) @@ -397,7 +406,7 @@ namespace Nz state.parameterIds.emplace(param.name, std::move(parameterData)); } - SpirvAstVisitor visitor(*this, state.functionBlocks, &m_context.cache); + SpirvAstVisitor visitor(*this, state.functionBlocks); for (const auto& statement : func.statements) statement->Visit(visitor); @@ -419,7 +428,7 @@ namespace Nz for (std::size_t i = 0; i < ShaderStageTypeCount; ++i) { - const ShaderAst::DeclareFunctionStatement* statement = m_context.cache.entryFunctions[i]; + /*const ShaderAst::DeclareFunctionStatement* statement = m_context.cache.entryFunctions[i]; if (!statement) continue; @@ -462,7 +471,7 @@ namespace Nz }); if (stage == ShaderStageType::Fragment) - state.header.Append(SpirvOp::OpExecutionMode, entryFunc.id, SpirvExecutionMode::OriginUpperLeft); + state.header.Append(SpirvOp::OpExecutionMode, entryFunc.id, SpirvExecutionMode::OriginUpperLeft);*/ } std::vector ret; From ea99c6a19ed3ae4225378f9b30d924c5cdf4a44e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Mon, 12 Apr 2021 15:38:20 +0200 Subject: [PATCH 094/278] Shader: First working version on both Vulkan & OpenGL (ES) --- include/Nazara/Renderer/Enums.hpp | 1 + include/Nazara/Shader.hpp | 1 - .../ConstantValue.hpp} | 4 +- include/Nazara/Shader/Ast/ExpressionType.hpp | 12 +- include/Nazara/Shader/Ast/ExpressionType.inl | 12 + .../Nazara/Shader/Ast/TransformVisitor.hpp | 90 ++ .../Nazara/Shader/Ast/TransformVisitor.inl | 62 ++ include/Nazara/Shader/GlslWriter.hpp | 3 +- include/Nazara/Shader/ShaderAstCloner.hpp | 17 +- include/Nazara/Shader/ShaderAstNodes.hpp | 4 +- .../Shader/ShaderAstRecursiveVisitor.hpp | 4 +- include/Nazara/Shader/ShaderAstSerializer.hpp | 4 +- include/Nazara/Shader/ShaderAstUtils.hpp | 4 +- include/Nazara/Shader/ShaderAstValidator.hpp | 2 +- include/Nazara/Shader/ShaderBuilder.hpp | 26 +- include/Nazara/Shader/ShaderBuilder.inl | 42 +- include/Nazara/Shader/ShaderNodes.hpp | 32 +- include/Nazara/Shader/ShaderNodes.inl | 5 + include/Nazara/Shader/SpirvAstVisitor.hpp | 95 +- include/Nazara/Shader/SpirvAstVisitor.inl | 37 +- include/Nazara/Shader/SpirvConstantCache.hpp | 47 +- include/Nazara/Shader/SpirvExpressionLoad.hpp | 10 +- include/Nazara/Shader/SpirvExpressionLoad.inl | 5 +- .../Nazara/Shader/SpirvExpressionStore.hpp | 10 +- .../Nazara/Shader/SpirvExpressionStore.inl | 5 +- include/Nazara/Shader/SpirvWriter.hpp | 43 +- src/Nazara/Shader/Ast/TransformVisitor.cpp | 225 +++++ src/Nazara/Shader/GlslWriter.cpp | 12 +- src/Nazara/Shader/ShaderAstCloner.cpp | 144 ++- .../Shader/ShaderAstRecursiveVisitor.cpp | 12 +- src/Nazara/Shader/ShaderAstScopedVisitor.cpp | 2 +- src/Nazara/Shader/ShaderAstSerializer.cpp | 42 +- src/Nazara/Shader/ShaderAstUtils.cpp | 12 +- src/Nazara/Shader/ShaderAstValidator.cpp | 11 +- src/Nazara/Shader/ShaderLangParser.cpp | 6 +- src/Nazara/Shader/SpirvAstVisitor.cpp | 591 ++++++++----- src/Nazara/Shader/SpirvConstantCache.cpp | 302 ++++--- src/Nazara/Shader/SpirvDecoder.cpp | 4 +- src/Nazara/Shader/SpirvExpressionLoad.cpp | 39 +- src/Nazara/Shader/SpirvExpressionStore.cpp | 38 +- src/Nazara/Shader/SpirvPrinter.cpp | 4 +- src/Nazara/Shader/SpirvWriter.cpp | 835 ++++++++---------- 42 files changed, 1803 insertions(+), 1053 deletions(-) rename include/Nazara/Shader/{ShaderConstantValue.hpp => Ast/ConstantValue.hpp} (90%) create mode 100644 include/Nazara/Shader/Ast/TransformVisitor.hpp create mode 100644 include/Nazara/Shader/Ast/TransformVisitor.inl create mode 100644 src/Nazara/Shader/Ast/TransformVisitor.cpp diff --git a/include/Nazara/Renderer/Enums.hpp b/include/Nazara/Renderer/Enums.hpp index 3f9de6791..405e50968 100644 --- a/include/Nazara/Renderer/Enums.hpp +++ b/include/Nazara/Renderer/Enums.hpp @@ -140,6 +140,7 @@ namespace Nz HLSL, MSL, NazaraBinary, + NazaraShader, SpirV }; diff --git a/include/Nazara/Shader.hpp b/include/Nazara/Shader.hpp index 2bd6df584..65cd2025e 100644 --- a/include/Nazara/Shader.hpp +++ b/include/Nazara/Shader.hpp @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include diff --git a/include/Nazara/Shader/ShaderConstantValue.hpp b/include/Nazara/Shader/Ast/ConstantValue.hpp similarity index 90% rename from include/Nazara/Shader/ShaderConstantValue.hpp rename to include/Nazara/Shader/Ast/ConstantValue.hpp index 27c9e1d7e..0f8ed1fc4 100644 --- a/include/Nazara/Shader/ShaderConstantValue.hpp +++ b/include/Nazara/Shader/Ast/ConstantValue.hpp @@ -13,9 +13,9 @@ #include #include -namespace Nz +namespace Nz::ShaderAst { - using ShaderConstantValue = std::variant< + using ConstantValue = std::variant< bool, float, Int32, diff --git a/include/Nazara/Shader/Ast/ExpressionType.hpp b/include/Nazara/Shader/Ast/ExpressionType.hpp index f42776fc3..a54b03395 100644 --- a/include/Nazara/Shader/Ast/ExpressionType.hpp +++ b/include/Nazara/Shader/Ast/ExpressionType.hpp @@ -50,9 +50,17 @@ namespace Nz::ShaderAst inline bool operator!=(const SamplerType& rhs) const; }; + struct StructType + { + std::size_t structIndex; + + inline bool operator==(const StructType& rhs) const; + inline bool operator!=(const StructType& rhs) const; + }; + struct UniformType { - IdentifierType containedType; + std::variant containedType; inline bool operator==(const UniformType& rhs) const; inline bool operator!=(const UniformType& rhs) const; @@ -67,7 +75,7 @@ namespace Nz::ShaderAst inline bool operator!=(const VectorType& rhs) const; }; - using ExpressionType = std::variant; + using ExpressionType = std::variant; struct StructDescription { diff --git a/include/Nazara/Shader/Ast/ExpressionType.inl b/include/Nazara/Shader/Ast/ExpressionType.inl index b9b7734e7..2fdb36674 100644 --- a/include/Nazara/Shader/Ast/ExpressionType.inl +++ b/include/Nazara/Shader/Ast/ExpressionType.inl @@ -51,6 +51,17 @@ namespace Nz::ShaderAst return !operator==(rhs); } + + inline bool StructType::operator==(const StructType& rhs) const + { + return structIndex == rhs.structIndex; + } + + inline bool StructType::operator!=(const StructType& rhs) const + { + return !operator==(rhs); + } + inline bool UniformType::operator==(const UniformType& rhs) const { return containedType == rhs.containedType; @@ -61,6 +72,7 @@ namespace Nz::ShaderAst return !operator==(rhs); } + inline bool VectorType::operator==(const VectorType& rhs) const { return componentCount == rhs.componentCount && type == rhs.type; diff --git a/include/Nazara/Shader/Ast/TransformVisitor.hpp b/include/Nazara/Shader/Ast/TransformVisitor.hpp new file mode 100644 index 000000000..d2483a095 --- /dev/null +++ b/include/Nazara/Shader/Ast/TransformVisitor.hpp @@ -0,0 +1,90 @@ +// 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_SHADERAST_TRANSFORMVISITOR_HPP +#define NAZARA_SHADERAST_TRANSFORMVISITOR_HPP + +#include +#include +#include +#include + +namespace Nz::ShaderAst +{ + class NAZARA_SHADER_API TransformVisitor : AstCloner + { + public: + inline TransformVisitor(); + TransformVisitor(const TransformVisitor&) = delete; + TransformVisitor(TransformVisitor&&) = delete; + ~TransformVisitor() = default; + + StatementPtr Transform(StatementPtr& statement); + + TransformVisitor& operator=(const TransformVisitor&) = delete; + TransformVisitor& operator=(TransformVisitor&&) = delete; + + private: + struct Identifier; + + ExpressionPtr Clone(AccessMemberIdentifierExpression& node) override; + ExpressionPtr Clone(CastExpression& node) override; + ExpressionPtr Clone(IdentifierExpression& node) override; + ExpressionPtr CloneExpression(ExpressionPtr& expr) override; + + inline const Identifier* FindIdentifier(const std::string_view& identifierName) const; + + void PushScope(); + void PopScope(); + + inline std::size_t RegisterFunction(std::string name); + inline std::size_t RegisterStruct(std::string name, StructDescription description); + inline std::size_t RegisterVariable(std::string name); + + ExpressionType ResolveType(const ExpressionType& exprType); + + using AstCloner::Visit; + void Visit(BranchStatement& node) override; + void Visit(ConditionalStatement& node) override; + void Visit(DeclareExternalStatement& node) override; + void Visit(DeclareFunctionStatement& node) override; + void Visit(DeclareStructStatement& node) override; + void Visit(DeclareVariableStatement& node) override; + void Visit(MultiStatement& node) override; + + struct Alias + { + std::variant value; + }; + + struct Struct + { + std::size_t structIndex; + }; + + struct Variable + { + std::size_t varIndex; + }; + + struct Identifier + { + std::string name; + std::variant value; + }; + + private: + std::size_t m_nextFuncIndex; + std::size_t m_nextVarIndex; + std::vector m_identifiersInScope; + std::vector m_structs; + std::vector m_scopeSizes; + }; +} + +#include + +#endif diff --git a/include/Nazara/Shader/Ast/TransformVisitor.inl b/include/Nazara/Shader/Ast/TransformVisitor.inl new file mode 100644 index 000000000..07601b026 --- /dev/null +++ b/include/Nazara/Shader/Ast/TransformVisitor.inl @@ -0,0 +1,62 @@ +// 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 +#include + +namespace Nz::ShaderAst +{ + inline TransformVisitor::TransformVisitor() : + m_nextFuncIndex(0), + m_nextVarIndex(0) + { + } + + inline auto TransformVisitor::FindIdentifier(const std::string_view& identifierName) const -> const Identifier* + { + auto it = std::find_if(m_identifiersInScope.rbegin(), m_identifiersInScope.rend(), [&](const Identifier& identifier) { return identifier.name == identifierName; }); + if (it == m_identifiersInScope.rend()) + return nullptr; + + return &*it; + } + + inline std::size_t TransformVisitor::RegisterFunction(std::string name) + { + std::size_t funcIndex = m_nextFuncIndex++; + return funcIndex; + } + + + inline std::size_t TransformVisitor::RegisterStruct(std::string name, StructDescription description) + { + std::size_t structIndex = m_structs.size(); + m_structs.emplace_back(std::move(description)); + + m_identifiersInScope.push_back({ + std::move(name), + Struct { + structIndex + } + }); + + return structIndex; + } + + inline std::size_t TransformVisitor::RegisterVariable(std::string name) + { + std::size_t varIndex = m_nextVarIndex++; + + m_identifiersInScope.push_back({ + std::move(name), + Variable { + varIndex + } + }); + + return varIndex; + } +} + +#include diff --git a/include/Nazara/Shader/GlslWriter.hpp b/include/Nazara/Shader/GlslWriter.hpp index 8b5f964e8..7b4741cd4 100644 --- a/include/Nazara/Shader/GlslWriter.hpp +++ b/include/Nazara/Shader/GlslWriter.hpp @@ -52,6 +52,7 @@ namespace Nz void Append(ShaderAst::NoType); void Append(ShaderAst::PrimitiveType type); void Append(const ShaderAst::SamplerType& samplerType); + void Append(const ShaderAst::StructType& structType); void Append(const ShaderAst::UniformType& uniformType); void Append(const ShaderAst::VectorType& vecType); template void Append(const T& param); @@ -67,7 +68,7 @@ namespace Nz void Visit(ShaderAst::ExpressionPtr& expr, bool encloseIfRequired = false); - void Visit(ShaderAst::AccessMemberExpression& node) override; + void Visit(ShaderAst::AccessMemberIdentifierExpression& node) override; void Visit(ShaderAst::AssignExpression& node) override; void Visit(ShaderAst::BinaryExpression& node) override; void Visit(ShaderAst::CastExpression& node) override; diff --git a/include/Nazara/Shader/ShaderAstCloner.hpp b/include/Nazara/Shader/ShaderAstCloner.hpp index 6b7d6b2b7..33b6acf3a 100644 --- a/include/Nazara/Shader/ShaderAstCloner.hpp +++ b/include/Nazara/Shader/ShaderAstCloner.hpp @@ -30,15 +30,25 @@ namespace Nz::ShaderAst AstCloner& operator=(AstCloner&&) = delete; protected: - ExpressionPtr CloneExpression(ExpressionPtr& expr); - StatementPtr CloneStatement(StatementPtr& statement); + virtual ExpressionPtr CloneExpression(ExpressionPtr& expr); + virtual StatementPtr CloneStatement(StatementPtr& statement); + virtual StatementPtr Clone(DeclareExternalStatement& node); virtual StatementPtr Clone(DeclareFunctionStatement& node); + virtual StatementPtr Clone(DeclareStructStatement& node); + virtual StatementPtr Clone(DeclareVariableStatement& node); + + virtual ExpressionPtr Clone(AccessMemberIdentifierExpression& node); + virtual ExpressionPtr Clone(AccessMemberIndexExpression& node); + virtual ExpressionPtr Clone(CastExpression& node); + virtual ExpressionPtr Clone(IdentifierExpression& node); + virtual ExpressionPtr Clone(VariableExpression& node); using AstExpressionVisitor::Visit; using AstStatementVisitor::Visit; - void Visit(AccessMemberExpression& node) override; + void Visit(AccessMemberIdentifierExpression& node) override; + void Visit(AccessMemberIndexExpression& node) override; void Visit(AssignExpression& node) override; void Visit(BinaryExpression& node) override; void Visit(CastExpression& node) override; @@ -47,6 +57,7 @@ namespace Nz::ShaderAst void Visit(IdentifierExpression& node) override; void Visit(IntrinsicExpression& node) override; void Visit(SwizzleExpression& node) override; + void Visit(VariableExpression& node) override; void Visit(BranchStatement& node) override; void Visit(ConditionalStatement& node) override; diff --git a/include/Nazara/Shader/ShaderAstNodes.hpp b/include/Nazara/Shader/ShaderAstNodes.hpp index 86b19521b..0bd48175c 100644 --- a/include/Nazara/Shader/ShaderAstNodes.hpp +++ b/include/Nazara/Shader/ShaderAstNodes.hpp @@ -26,7 +26,8 @@ #define NAZARA_SHADERAST_STATEMENT_LAST(X) NAZARA_SHADERAST_STATEMENT(X) #endif -NAZARA_SHADERAST_EXPRESSION(AccessMemberExpression) +NAZARA_SHADERAST_EXPRESSION(AccessMemberIdentifierExpression) +NAZARA_SHADERAST_EXPRESSION(AccessMemberIndexExpression) NAZARA_SHADERAST_EXPRESSION(AssignExpression) NAZARA_SHADERAST_EXPRESSION(BinaryExpression) NAZARA_SHADERAST_EXPRESSION(CastExpression) @@ -35,6 +36,7 @@ NAZARA_SHADERAST_EXPRESSION(ConstantExpression) NAZARA_SHADERAST_EXPRESSION(IdentifierExpression) NAZARA_SHADERAST_EXPRESSION(IntrinsicExpression) NAZARA_SHADERAST_EXPRESSION(SwizzleExpression) +NAZARA_SHADERAST_EXPRESSION(VariableExpression) NAZARA_SHADERAST_STATEMENT(BranchStatement) NAZARA_SHADERAST_STATEMENT(ConditionalStatement) NAZARA_SHADERAST_STATEMENT(DeclareExternalStatement) diff --git a/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp b/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp index 1bfbb65da..f05a20d22 100644 --- a/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp +++ b/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp @@ -20,7 +20,8 @@ namespace Nz::ShaderAst AstRecursiveVisitor() = default; ~AstRecursiveVisitor() = default; - void Visit(AccessMemberExpression& node) override; + void Visit(AccessMemberIdentifierExpression& node) override; + void Visit(AccessMemberIndexExpression& node) override; void Visit(AssignExpression& node) override; void Visit(BinaryExpression& node) override; void Visit(CastExpression& node) override; @@ -29,6 +30,7 @@ namespace Nz::ShaderAst void Visit(IdentifierExpression& node) override; void Visit(IntrinsicExpression& node) override; void Visit(SwizzleExpression& node) override; + void Visit(VariableExpression& node) override; void Visit(BranchStatement& node) override; void Visit(ConditionalStatement& node) override; diff --git a/include/Nazara/Shader/ShaderAstSerializer.hpp b/include/Nazara/Shader/ShaderAstSerializer.hpp index 2cb0bd5f1..20ac281bf 100644 --- a/include/Nazara/Shader/ShaderAstSerializer.hpp +++ b/include/Nazara/Shader/ShaderAstSerializer.hpp @@ -23,7 +23,8 @@ namespace Nz::ShaderAst AstSerializerBase(AstSerializerBase&&) = delete; ~AstSerializerBase() = default; - void Serialize(AccessMemberExpression& node); + void Serialize(AccessMemberIdentifierExpression& node); + void Serialize(AccessMemberIndexExpression& node); void Serialize(AssignExpression& node); void Serialize(BinaryExpression& node); void Serialize(CastExpression& node); @@ -32,6 +33,7 @@ namespace Nz::ShaderAst void Serialize(IdentifierExpression& node); void Serialize(IntrinsicExpression& node); void Serialize(SwizzleExpression& node); + void Serialize(VariableExpression& node); void Serialize(BranchStatement& node); void Serialize(ConditionalStatement& node); diff --git a/include/Nazara/Shader/ShaderAstUtils.hpp b/include/Nazara/Shader/ShaderAstUtils.hpp index 3f577ed3e..a560bb5b6 100644 --- a/include/Nazara/Shader/ShaderAstUtils.hpp +++ b/include/Nazara/Shader/ShaderAstUtils.hpp @@ -31,7 +31,8 @@ namespace Nz::ShaderAst private: using AstExpressionVisitor::Visit; - void Visit(AccessMemberExpression& node) override; + void Visit(AccessMemberIdentifierExpression& node) override; + void Visit(AccessMemberIndexExpression& node) override; void Visit(AssignExpression& node) override; void Visit(BinaryExpression& node) override; void Visit(CastExpression& node) override; @@ -40,6 +41,7 @@ namespace Nz::ShaderAst void Visit(IdentifierExpression& node) override; void Visit(IntrinsicExpression& node) override; void Visit(SwizzleExpression& node) override; + void Visit(VariableExpression& node) override; ExpressionCategory m_expressionCategory; }; diff --git a/include/Nazara/Shader/ShaderAstValidator.hpp b/include/Nazara/Shader/ShaderAstValidator.hpp index b617e27c7..9556eee0f 100644 --- a/include/Nazara/Shader/ShaderAstValidator.hpp +++ b/include/Nazara/Shader/ShaderAstValidator.hpp @@ -34,7 +34,7 @@ namespace Nz::ShaderAst ExpressionType CheckField(const std::string& structName, const std::string* memberIdentifier, std::size_t remainingMembers); const ExpressionType& ResolveAlias(const ExpressionType& expressionType); - void Visit(AccessMemberExpression& node) override; + void Visit(AccessMemberIdentifierExpression& node) override; void Visit(AssignExpression& node) override; void Visit(BinaryExpression& node) override; void Visit(CastExpression& node) override; diff --git a/include/Nazara/Shader/ShaderBuilder.hpp b/include/Nazara/Shader/ShaderBuilder.hpp index c6edb8041..c9f0b50de 100644 --- a/include/Nazara/Shader/ShaderBuilder.hpp +++ b/include/Nazara/Shader/ShaderBuilder.hpp @@ -15,6 +15,11 @@ namespace Nz::ShaderBuilder { namespace Impl { + struct AccessMember + { + inline std::unique_ptr operator()(ShaderAst::ExpressionPtr structExpr, std::vector memberIdentifiers) const; + }; + struct Assign { inline std::unique_ptr operator()(ShaderAst::AssignType op, ShaderAst::ExpressionPtr left, ShaderAst::ExpressionPtr right) const; @@ -36,9 +41,19 @@ namespace Nz::ShaderBuilder inline std::unique_ptr operator()(ShaderAst::ExpressionType targetType, std::vector expressions) const; }; + struct ConditionalExpression + { + inline std::unique_ptr operator()(std::string conditionName, ShaderAst::ExpressionPtr truePath, ShaderAst::ExpressionPtr falsePath) const; + }; + + struct ConditionalStatement + { + inline std::unique_ptr operator()(std::string conditionName, ShaderAst::StatementPtr statement) const; + }; + struct Constant { - inline std::unique_ptr operator()(ShaderConstantValue value) const; + inline std::unique_ptr operator()(ShaderAst::ConstantValue value) const; }; struct DeclareFunction @@ -83,12 +98,20 @@ namespace Nz::ShaderBuilder { inline std::unique_ptr operator()(ShaderAst::ExpressionPtr expr = nullptr) const; }; + + struct Swizzle + { + inline std::unique_ptr operator()(ShaderAst::ExpressionPtr expression, std::vector swizzleComponents) const; + }; } + constexpr Impl::AccessMember AccessMember; constexpr Impl::Assign Assign; constexpr Impl::Binary Binary; constexpr Impl::Branch Branch; constexpr Impl::Cast Cast; + constexpr Impl::ConditionalExpression ConditionalExpression; + constexpr Impl::ConditionalStatement ConditionalStatement; constexpr Impl::Constant Constant; constexpr Impl::DeclareFunction DeclareFunction; constexpr Impl::DeclareStruct DeclareStruct; @@ -99,6 +122,7 @@ namespace Nz::ShaderBuilder constexpr Impl::Intrinsic Intrinsic; constexpr Impl::NoParam NoOp; constexpr Impl::Return Return; + constexpr Impl::Swizzle Swizzle; } #include diff --git a/include/Nazara/Shader/ShaderBuilder.inl b/include/Nazara/Shader/ShaderBuilder.inl index feff95b8a..ec83815a7 100644 --- a/include/Nazara/Shader/ShaderBuilder.inl +++ b/include/Nazara/Shader/ShaderBuilder.inl @@ -7,6 +7,15 @@ namespace Nz::ShaderBuilder { + inline std::unique_ptr Impl::AccessMember::operator()(ShaderAst::ExpressionPtr structExpr, std::vector memberIdentifiers) const + { + auto accessMemberNode = std::make_unique(); + accessMemberNode->structExpr = std::move(structExpr); + accessMemberNode->memberIdentifiers = std::move(memberIdentifiers); + + return accessMemberNode; + } + inline std::unique_ptr Impl::Assign::operator()(ShaderAst::AssignType op, ShaderAst::ExpressionPtr left, ShaderAst::ExpressionPtr right) const { auto assignNode = std::make_unique(); @@ -61,7 +70,26 @@ namespace Nz::ShaderBuilder return castNode; } - inline std::unique_ptr Impl::Constant::operator()(ShaderConstantValue value) const + inline std::unique_ptr Impl::ConditionalExpression::operator()(std::string conditionName, ShaderAst::ExpressionPtr truePath, ShaderAst::ExpressionPtr falsePath) const + { + auto condExprNode = std::make_unique(); + condExprNode->conditionName = std::move(conditionName); + condExprNode->falsePath = std::move(falsePath); + condExprNode->truePath = std::move(truePath); + + return condExprNode; + } + + inline std::unique_ptr Impl::ConditionalStatement::operator()(std::string conditionName, ShaderAst::StatementPtr statement) const + { + auto condStatementNode = std::make_unique(); + condStatementNode->conditionName = std::move(conditionName); + condStatementNode->statement = std::move(statement); + + return condStatementNode; + } + + inline std::unique_ptr Impl::Constant::operator()(ShaderAst::ConstantValue value) const { auto constantNode = std::make_unique(); constantNode->value = std::move(value); @@ -157,6 +185,18 @@ namespace Nz::ShaderBuilder { return std::make_unique(); } + + inline std::unique_ptr Impl::Swizzle::operator()(ShaderAst::ExpressionPtr expression, std::vector swizzleComponents) const + { + auto swizzleNode = std::make_unique(); + swizzleNode->expression = std::move(expression); + + assert(swizzleComponents.size() <= swizzleNode->components.size()); + for (std::size_t i = 0; i < swizzleComponents.size(); ++i) + swizzleNode->components[i] = swizzleComponents[i]; + + return swizzleNode; + } } #include diff --git a/include/Nazara/Shader/ShaderNodes.hpp b/include/Nazara/Shader/ShaderNodes.hpp index 7b442c07c..5413457f2 100644 --- a/include/Nazara/Shader/ShaderNodes.hpp +++ b/include/Nazara/Shader/ShaderNodes.hpp @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include @@ -60,7 +60,7 @@ namespace Nz::ShaderAst std::optional cachedExpressionType; }; - struct NAZARA_SHADER_API AccessMemberExpression : public Expression + struct NAZARA_SHADER_API AccessMemberIdentifierExpression : public Expression { NodeType GetType() const override; void Visit(AstExpressionVisitor& visitor) override; @@ -69,6 +69,15 @@ namespace Nz::ShaderAst std::vector memberIdentifiers; }; + struct NAZARA_SHADER_API AccessMemberIndexExpression : public Expression + { + NodeType GetType() const override; + void Visit(AstExpressionVisitor& visitor) override; + + ExpressionPtr structExpr; + std::vector memberIndices; + }; + struct NAZARA_SHADER_API AssignExpression : public Expression { NodeType GetType() const override; @@ -113,7 +122,7 @@ namespace Nz::ShaderAst NodeType GetType() const override; void Visit(AstExpressionVisitor& visitor) override; - ShaderConstantValue value; + ShaderAst::ConstantValue value; }; struct NAZARA_SHADER_API IdentifierExpression : public Expression @@ -143,6 +152,14 @@ namespace Nz::ShaderAst ExpressionPtr expression; }; + struct NAZARA_SHADER_API VariableExpression : Expression + { + NodeType GetType() const override; + void Visit(AstExpressionVisitor& visitor) override; + + std::size_t variableId; + }; + // Statements struct Statement; @@ -193,11 +210,12 @@ namespace Nz::ShaderAst struct ExternalVar { - std::vector attributes; std::string name; + std::vector attributes; ExpressionType type; }; + std::optional varIndex; std::vector attributes; std::vector externalVars; }; @@ -213,6 +231,8 @@ namespace Nz::ShaderAst ExpressionType type; }; + std::optional funcIndex; + std::optional varIndex; std::string name; std::vector attributes; std::vector parameters; @@ -225,6 +245,7 @@ namespace Nz::ShaderAst NodeType GetType() const override; void Visit(AstStatementVisitor& visitor) override; + std::optional structIndex; std::vector attributes; StructDescription description; }; @@ -234,6 +255,7 @@ namespace Nz::ShaderAst NodeType GetType() const override; void Visit(AstStatementVisitor& visitor) override; + std::optional varIndex; std::string varName; ExpressionPtr initialExpression; ExpressionType varType; @@ -274,6 +296,8 @@ namespace Nz::ShaderAst ExpressionPtr returnExpr; }; + + inline const ShaderAst::ExpressionType& GetExpressionType(ShaderAst::Expression& expr); } #include diff --git a/include/Nazara/Shader/ShaderNodes.inl b/include/Nazara/Shader/ShaderNodes.inl index 6c702a06e..d8b320b72 100644 --- a/include/Nazara/Shader/ShaderNodes.inl +++ b/include/Nazara/Shader/ShaderNodes.inl @@ -7,6 +7,11 @@ namespace Nz::ShaderAst { + const ShaderAst::ExpressionType& GetExpressionType(ShaderAst::Expression& expr) + { + assert(expr.cachedExpressionType); + return expr.cachedExpressionType.value(); + } } #include diff --git a/include/Nazara/Shader/SpirvAstVisitor.hpp b/include/Nazara/Shader/SpirvAstVisitor.hpp index d868dab41..0f2d06495 100644 --- a/include/Nazara/Shader/SpirvAstVisitor.hpp +++ b/include/Nazara/Shader/SpirvAstVisitor.hpp @@ -11,7 +11,9 @@ #include #include #include +#include #include +#include #include namespace Nz @@ -21,17 +23,25 @@ namespace Nz class NAZARA_SHADER_API SpirvAstVisitor : public ShaderAst::ExpressionVisitorExcept, public ShaderAst::StatementVisitorExcept { public: - inline SpirvAstVisitor(SpirvWriter& writer, std::vector& blocks); + struct EntryPoint; + struct FuncData; + struct Variable; + + inline SpirvAstVisitor(SpirvWriter& writer, SpirvSection& instructions, std::vector& funcData); SpirvAstVisitor(const SpirvAstVisitor&) = delete; SpirvAstVisitor(SpirvAstVisitor&&) = delete; ~SpirvAstVisitor() = default; + UInt32 AllocateResultId(); + UInt32 EvaluateExpression(ShaderAst::ExpressionPtr& expr); + const Variable& GetVariable(std::size_t varIndex) const; + using ExpressionVisitorExcept::Visit; using StatementVisitorExcept::Visit; - void Visit(ShaderAst::AccessMemberExpression& node) override; + void Visit(ShaderAst::AccessMemberIndexExpression& node) override; void Visit(ShaderAst::AssignExpression& node) override; void Visit(ShaderAst::BinaryExpression& node) override; void Visit(ShaderAst::BranchStatement& node) override; @@ -39,27 +49,102 @@ namespace Nz void Visit(ShaderAst::ConditionalExpression& node) override; void Visit(ShaderAst::ConditionalStatement& node) override; void Visit(ShaderAst::ConstantExpression& node) override; + void Visit(ShaderAst::DeclareExternalStatement& node) override; + void Visit(ShaderAst::DeclareFunctionStatement& node) override; + void Visit(ShaderAst::DeclareStructStatement& node) override; void Visit(ShaderAst::DeclareVariableStatement& node) override; void Visit(ShaderAst::DiscardStatement& node) override; void Visit(ShaderAst::ExpressionStatement& node) override; - void Visit(ShaderAst::IdentifierExpression& node) override; void Visit(ShaderAst::IntrinsicExpression& node) override; void Visit(ShaderAst::MultiStatement& node) override; void Visit(ShaderAst::NoOpStatement& node) override; void Visit(ShaderAst::ReturnStatement& node) override; void Visit(ShaderAst::SwizzleExpression& node) override; + void Visit(ShaderAst::VariableExpression& node) override; SpirvAstVisitor& operator=(const SpirvAstVisitor&) = delete; SpirvAstVisitor& operator=(SpirvAstVisitor&&) = delete; + struct EntryPoint + { + struct Input + { + UInt32 memberIndexConstantId; + UInt32 memberPointerId; + UInt32 varId; + }; + + struct Output + { + Int32 memberIndex; + UInt32 typeId; + UInt32 varId; + }; + + struct InputStruct + { + UInt32 pointerId; + UInt32 typeId; + }; + + ShaderStageType stageType; + std::optional inputStruct; + std::optional outputStructTypeId; + std::size_t funcIndex; + std::vector inputs; + std::vector outputs; + }; + + struct FuncData + { + std::optional entryPointData; + + struct Parameter + { + UInt32 pointerTypeId; + UInt32 typeId; + }; + + struct Variable + { + UInt32 typeId; + UInt32 varId; + }; + + std::string name; + std::vector parameters; + std::vector variables; + std::unordered_map varIndexToVarId; + UInt32 funcId; + UInt32 funcTypeId; + UInt32 returnTypeId; + }; + + struct Variable + { + SpirvStorageClass storage; + UInt32 pointerId; + UInt32 pointedTypeId; + }; + private: - inline const ShaderAst::ExpressionType& GetExpressionType(ShaderAst::Expression& expr) const; void PushResultId(UInt32 value); UInt32 PopResultId(); - std::vector& m_blocks; + inline void RegisterExternalVariable(std::size_t varIndex, const ShaderAst::ExpressionType& type); + inline void RegisterStruct(std::size_t structIndex, ShaderAst::StructDescription structDesc); + inline void RegisterVariable(std::size_t varIndex, UInt32 typeId, UInt32 pointerId, SpirvStorageClass storageClass); + + std::size_t m_extVarIndex; + std::size_t m_funcIndex; + std::vector m_scopeSizes; + std::vector& m_funcData; + std::vector m_structs; + std::vector> m_variables; + std::vector m_functionBlocks; std::vector m_resultIds; SpirvBlock* m_currentBlock; + SpirvSection& m_instructions; SpirvWriter& m_writer; }; } diff --git a/include/Nazara/Shader/SpirvAstVisitor.inl b/include/Nazara/Shader/SpirvAstVisitor.inl index bb54eb594..f67692f6f 100644 --- a/include/Nazara/Shader/SpirvAstVisitor.inl +++ b/include/Nazara/Shader/SpirvAstVisitor.inl @@ -7,17 +7,42 @@ namespace Nz { - inline SpirvAstVisitor::SpirvAstVisitor(SpirvWriter& writer, std::vector& blocks) : - m_blocks(blocks), + inline SpirvAstVisitor::SpirvAstVisitor(SpirvWriter& writer, SpirvSection& instructions, std::vector& funcData) : + m_extVarIndex(0), + m_funcIndex(0), + m_funcData(funcData), + m_currentBlock(nullptr), + m_instructions(instructions), m_writer(writer) { - m_currentBlock = &m_blocks.back(); } - inline const ShaderAst::ExpressionType& SpirvAstVisitor::GetExpressionType(ShaderAst::Expression& expr) const + void SpirvAstVisitor::RegisterExternalVariable(std::size_t varIndex, const ShaderAst::ExpressionType& type) { - assert(expr.cachedExpressionType); - return expr.cachedExpressionType.value(); + UInt32 pointerId = m_writer.GetExtVarPointerId(varIndex); + SpirvStorageClass storageClass = (IsSamplerType(type)) ? SpirvStorageClass::UniformConstant : SpirvStorageClass::Uniform; + + RegisterVariable(varIndex, m_writer.GetTypeId(type), pointerId, storageClass); + } + + inline void SpirvAstVisitor::RegisterStruct(std::size_t structIndex, ShaderAst::StructDescription structDesc) + { + if (structIndex >= m_structs.size()) + m_structs.resize(structIndex + 1); + + m_structs[structIndex] = std::move(structDesc); + } + + inline void SpirvAstVisitor::RegisterVariable(std::size_t varIndex, UInt32 typeId, UInt32 pointerId, SpirvStorageClass storageClass) + { + if (varIndex >= m_variables.size()) + m_variables.resize(varIndex + 1); + + m_variables[varIndex] = Variable{ + storageClass, + pointerId, + typeId + }; } } diff --git a/include/Nazara/Shader/SpirvConstantCache.hpp b/include/Nazara/Shader/SpirvConstantCache.hpp index c01ab8d68..3025c013d 100644 --- a/include/Nazara/Shader/SpirvConstantCache.hpp +++ b/include/Nazara/Shader/SpirvConstantCache.hpp @@ -8,8 +8,8 @@ #define NAZARA_SPIRVCONSTANTCACHE_HPP #include -#include #include +#include #include #include #include @@ -25,6 +25,8 @@ namespace Nz class NAZARA_SHADER_API SpirvConstantCache { public: + using StructCallback = std::function; + SpirvConstantCache(UInt32& resultId); SpirvConstantCache(const SpirvConstantCache& cache) = delete; SpirvConstantCache(SpirvConstantCache&& cache) noexcept; @@ -37,8 +39,6 @@ namespace Nz using ConstantPtr = std::shared_ptr; using TypePtr = std::shared_ptr; - using IdentifierCallback = std::function; - struct Bool {}; struct Float @@ -66,11 +66,6 @@ namespace Nz UInt32 columnCount; }; - struct Identifier - { - std::string name; - }; - struct Image { std::optional qualifier; @@ -112,7 +107,7 @@ namespace Nz std::vector members; }; - using AnyType = std::variant; + using AnyType = std::variant; struct ConstantBool { @@ -134,10 +129,11 @@ namespace Nz struct Variable { + std::optional funcId; //< For inputs/outputs + std::optional initializer; std::string debugName; TypePtr type; SpirvStorageClass storageClass; - std::optional initializer; }; using BaseType = std::variant; @@ -166,6 +162,21 @@ namespace Nz AnyType type; }; + ConstantPtr BuildConstant(const ShaderAst::ConstantValue& value) const; + TypePtr BuildFunctionType(const ShaderAst::ExpressionType& retType, const std::vector& parameters) const; + TypePtr BuildPointerType(const ShaderAst::PrimitiveType& type, SpirvStorageClass storageClass) const; + TypePtr BuildPointerType(const ShaderAst::ExpressionType& type, SpirvStorageClass storageClass) const; + TypePtr BuildType(const ShaderAst::ExpressionType& type) const; + TypePtr BuildType(const ShaderAst::IdentifierType& type) const; + TypePtr BuildType(const ShaderAst::MatrixType& type) const; + TypePtr BuildType(const ShaderAst::NoType& type) const; + TypePtr BuildType(const ShaderAst::PrimitiveType& type) const; + TypePtr BuildType(const ShaderAst::SamplerType& type) const; + TypePtr BuildType(const ShaderAst::StructType& type) const; + TypePtr BuildType(const ShaderAst::StructDescription& structDesc) const; + TypePtr BuildType(const ShaderAst::VectorType& type) const; + TypePtr BuildType(const ShaderAst::UniformType& type) const; + UInt32 GetId(const Constant& c); UInt32 GetId(const Type& t); UInt32 GetId(const Variable& v); @@ -174,26 +185,13 @@ namespace Nz UInt32 Register(Type t); UInt32 Register(Variable v); - void SetIdentifierCallback(IdentifierCallback callback); + void SetStructCallback(StructCallback callback); void Write(SpirvSection& annotations, SpirvSection& constants, SpirvSection& debugInfos); SpirvConstantCache& operator=(const SpirvConstantCache& cache) = delete; SpirvConstantCache& operator=(SpirvConstantCache&& cache) noexcept; - static ConstantPtr BuildConstant(const ShaderConstantValue& value); - static TypePtr BuildFunctionType(const ShaderAst::ExpressionType& retType, const std::vector& parameters); - static TypePtr BuildPointerType(const ShaderAst::PrimitiveType& type, SpirvStorageClass storageClass); - static TypePtr BuildPointerType(const ShaderAst::ExpressionType& type, SpirvStorageClass storageClass); - static TypePtr BuildType(const ShaderAst::ExpressionType& type); - static TypePtr BuildType(const ShaderAst::IdentifierType& type); - static TypePtr BuildType(const ShaderAst::MatrixType& type); - static TypePtr BuildType(const ShaderAst::NoType& type); - static TypePtr BuildType(const ShaderAst::PrimitiveType& type); - static TypePtr BuildType(const ShaderAst::SamplerType& type); - static TypePtr BuildType(const ShaderAst::StructDescription& structDesc); - static TypePtr BuildType(const ShaderAst::VectorType& type); - private: struct DepRegisterer; struct Eq; @@ -204,7 +202,6 @@ namespace Nz void WriteStruct(const Structure& structData, UInt32 resultId, SpirvSection& annotations, SpirvSection& constants, SpirvSection& debugInfos); - IdentifierCallback m_identifierCallback; std::unique_ptr m_internal; }; } diff --git a/include/Nazara/Shader/SpirvExpressionLoad.hpp b/include/Nazara/Shader/SpirvExpressionLoad.hpp index ddc9551fd..bff0047cf 100644 --- a/include/Nazara/Shader/SpirvExpressionLoad.hpp +++ b/include/Nazara/Shader/SpirvExpressionLoad.hpp @@ -15,13 +15,14 @@ namespace Nz { + class SpirvAstVisitor; class SpirvBlock; class SpirvWriter; class NAZARA_SHADER_API SpirvExpressionLoad : public ShaderAst::ExpressionVisitorExcept { public: - inline SpirvExpressionLoad(SpirvWriter& writer, SpirvBlock& block); + inline SpirvExpressionLoad(SpirvWriter& writer, SpirvAstVisitor& visitor, SpirvBlock& block); SpirvExpressionLoad(const SpirvExpressionLoad&) = delete; SpirvExpressionLoad(SpirvExpressionLoad&&) = delete; ~SpirvExpressionLoad() = default; @@ -29,8 +30,8 @@ namespace Nz UInt32 Evaluate(ShaderAst::Expression& node); using ExpressionVisitorExcept::Visit; - //void Visit(ShaderAst::AccessMemberExpression& node) override; - void Visit(ShaderAst::IdentifierExpression& node) override; + void Visit(ShaderAst::AccessMemberIndexExpression& node) override; + void Visit(ShaderAst::VariableExpression& node) override; SpirvExpressionLoad& operator=(const SpirvExpressionLoad&) = delete; SpirvExpressionLoad& operator=(SpirvExpressionLoad&&) = delete; @@ -39,7 +40,7 @@ namespace Nz struct Pointer { SpirvStorageClass storage; - UInt32 resultId; + UInt32 pointerId; UInt32 pointedTypeId; }; @@ -48,6 +49,7 @@ namespace Nz UInt32 resultId; }; + SpirvAstVisitor& m_visitor; SpirvBlock& m_block; SpirvWriter& m_writer; std::variant m_value; diff --git a/include/Nazara/Shader/SpirvExpressionLoad.inl b/include/Nazara/Shader/SpirvExpressionLoad.inl index 6d5aff9cb..1522515b9 100644 --- a/include/Nazara/Shader/SpirvExpressionLoad.inl +++ b/include/Nazara/Shader/SpirvExpressionLoad.inl @@ -7,9 +7,10 @@ namespace Nz { - inline SpirvExpressionLoad::SpirvExpressionLoad(SpirvWriter& writer, SpirvBlock& block) : + inline SpirvExpressionLoad::SpirvExpressionLoad(SpirvWriter& writer, SpirvAstVisitor& visitor, SpirvBlock& block) : m_block(block), - m_writer(writer) + m_writer(writer), + m_visitor(visitor) { } } diff --git a/include/Nazara/Shader/SpirvExpressionStore.hpp b/include/Nazara/Shader/SpirvExpressionStore.hpp index ee0d96f6a..e66d545d3 100644 --- a/include/Nazara/Shader/SpirvExpressionStore.hpp +++ b/include/Nazara/Shader/SpirvExpressionStore.hpp @@ -14,13 +14,14 @@ namespace Nz { + class SpirvAstVisitor; class SpirvBlock; class SpirvWriter; class NAZARA_SHADER_API SpirvExpressionStore : public ShaderAst::ExpressionVisitorExcept { public: - inline SpirvExpressionStore(SpirvWriter& writer, SpirvBlock& block); + inline SpirvExpressionStore(SpirvWriter& writer, SpirvAstVisitor& visitor, SpirvBlock& block); SpirvExpressionStore(const SpirvExpressionStore&) = delete; SpirvExpressionStore(SpirvExpressionStore&&) = delete; ~SpirvExpressionStore() = default; @@ -28,9 +29,9 @@ namespace Nz void Store(ShaderAst::ExpressionPtr& node, UInt32 resultId); using ExpressionVisitorExcept::Visit; - //void Visit(ShaderAst::AccessMemberExpression& node) override; - void Visit(ShaderAst::IdentifierExpression& node) override; + void Visit(ShaderAst::AccessMemberIndexExpression& node) override; void Visit(ShaderAst::SwizzleExpression& node) override; + void Visit(ShaderAst::VariableExpression& node) override; SpirvExpressionStore& operator=(const SpirvExpressionStore&) = delete; SpirvExpressionStore& operator=(SpirvExpressionStore&&) = delete; @@ -44,9 +45,10 @@ namespace Nz struct Pointer { SpirvStorageClass storage; - UInt32 resultId; + UInt32 pointerId; }; + SpirvAstVisitor& m_visitor; SpirvBlock& m_block; SpirvWriter& m_writer; std::variant m_value; diff --git a/include/Nazara/Shader/SpirvExpressionStore.inl b/include/Nazara/Shader/SpirvExpressionStore.inl index 771624788..16326a438 100644 --- a/include/Nazara/Shader/SpirvExpressionStore.inl +++ b/include/Nazara/Shader/SpirvExpressionStore.inl @@ -7,9 +7,10 @@ namespace Nz { - inline SpirvExpressionStore::SpirvExpressionStore(SpirvWriter& writer, SpirvBlock& block) : + inline SpirvExpressionStore::SpirvExpressionStore(SpirvWriter& writer, SpirvAstVisitor& visitor, SpirvBlock& block) : m_block(block), - m_writer(writer) + m_writer(writer), + m_visitor(visitor) { } } diff --git a/include/Nazara/Shader/SpirvWriter.hpp b/include/Nazara/Shader/SpirvWriter.hpp index 3b770ae87..2bab892ca 100644 --- a/include/Nazara/Shader/SpirvWriter.hpp +++ b/include/Nazara/Shader/SpirvWriter.hpp @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include #include @@ -27,7 +27,6 @@ namespace Nz friend class SpirvBlock; friend class SpirvExpressionLoad; friend class SpirvExpressionStore; - friend class SpirvVisitor; public: struct Environment; @@ -48,7 +47,6 @@ namespace Nz }; private: - struct ExtVar; struct FunctionParameter; struct OnlyCache {}; @@ -56,36 +54,21 @@ namespace Nz void AppendHeader(); - UInt32 GetConstantId(const ShaderConstantValue& value) const; + SpirvConstantCache::TypePtr BuildFunctionType(const ShaderAst::DeclareFunctionStatement& functionNode); + + UInt32 GetConstantId(const ShaderAst::ConstantValue& value) const; + UInt32 GetExtVarPointerId(std::size_t varIndex) const; UInt32 GetFunctionTypeId(const ShaderAst::DeclareFunctionStatement& functionNode); - const ExtVar& GetBuiltinVariable(ShaderAst::BuiltinEntry builtin) const; - const ExtVar& GetInputVariable(const std::string& name) const; - const ExtVar& GetOutputVariable(const std::string& name) const; - const ExtVar& GetUniformVariable(const std::string& name) const; UInt32 GetPointerTypeId(const ShaderAst::ExpressionType& type, SpirvStorageClass storageClass) const; UInt32 GetTypeId(const ShaderAst::ExpressionType& type) const; inline bool IsConditionEnabled(const std::string& condition) const; - UInt32 ReadInputVariable(const std::string& name); - std::optional ReadInputVariable(const std::string& name, OnlyCache); - UInt32 ReadLocalVariable(const std::string& name); - std::optional ReadLocalVariable(const std::string& name, OnlyCache); - UInt32 ReadParameterVariable(const std::string& name); - std::optional ReadParameterVariable(const std::string& name, OnlyCache); - UInt32 ReadUniformVariable(const std::string& name); - std::optional ReadUniformVariable(const std::string& name, OnlyCache); - UInt32 ReadVariable(ExtVar& var); - std::optional ReadVariable(const ExtVar& var, OnlyCache); - - UInt32 RegisterConstant(const ShaderConstantValue& value); + UInt32 RegisterConstant(const ShaderAst::ConstantValue& value); UInt32 RegisterFunctionType(const ShaderAst::DeclareFunctionStatement& functionNode); UInt32 RegisterPointerType(ShaderAst::ExpressionType type, SpirvStorageClass storageClass); UInt32 RegisterType(ShaderAst::ExpressionType type); - void WriteLocalVariable(std::string name, UInt32 resultId); - - static SpirvConstantCache::TypePtr BuildFunctionType(const ShaderAst::DeclareFunctionStatement& functionNode); static void MergeSections(std::vector& output, const SpirvSection& from); struct Context @@ -93,20 +76,6 @@ namespace Nz const States* states = nullptr; }; - struct ExtVar - { - UInt32 pointerTypeId; - UInt32 typeId; - UInt32 varId; - std::optional valueId; - }; - - struct FunctionParameter - { - std::string name; - ShaderAst::ExpressionType type; - }; - struct State; Context m_context; diff --git a/src/Nazara/Shader/Ast/TransformVisitor.cpp b/src/Nazara/Shader/Ast/TransformVisitor.cpp new file mode 100644 index 000000000..14f127697 --- /dev/null +++ b/src/Nazara/Shader/Ast/TransformVisitor.cpp @@ -0,0 +1,225 @@ +// 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 +#include +#include + +namespace Nz::ShaderAst +{ + StatementPtr TransformVisitor::Transform(StatementPtr& nodePtr) + { + StatementPtr clone; + + PushScope(); //< Global scope + { + clone = AstCloner::Clone(nodePtr); + } + PopScope(); + + return clone; + } + + void TransformVisitor::Visit(BranchStatement& node) + { + for (auto& cond : node.condStatements) + { + PushScope(); + { + cond.condition->Visit(*this); + cond.statement->Visit(*this); + } + PopScope(); + } + + if (node.elseStatement) + { + PushScope(); + { + node.elseStatement->Visit(*this); + } + PopScope(); + } + } + + void TransformVisitor::Visit(ConditionalStatement& node) + { + PushScope(); + { + AstCloner::Visit(node); + } + PopScope(); + } + + ExpressionType TransformVisitor::ResolveType(const ExpressionType& exprType) + { + return std::visit([&](auto&& arg) -> ExpressionType + { + using T = std::decay_t; + + if constexpr (std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v) + { + return exprType; + } + else if constexpr (std::is_same_v) + { + const Identifier* identifier = FindIdentifier(arg.name); + assert(identifier); + assert(std::holds_alternative(identifier->value)); + + return StructType{ std::get(identifier->value).structIndex }; + } + else if constexpr (std::is_same_v) + { + return std::visit([&](auto&& containedArg) + { + ExpressionType resolvedType = ResolveType(containedArg); + assert(std::holds_alternative(resolvedType)); + + return UniformType{ std::get(resolvedType) }; + }, arg.containedType); + } + else + static_assert(AlwaysFalse::value, "non-exhaustive visitor"); + }, exprType); + } + + void TransformVisitor::Visit(DeclareExternalStatement& node) + { + for (auto& extVar : node.externalVars) + { + extVar.type = ResolveType(extVar.type); + + std::size_t varIndex = RegisterVariable(extVar.name); + if (!node.varIndex) + node.varIndex = varIndex; + } + + AstCloner::Visit(node); + } + + void TransformVisitor::Visit(DeclareFunctionStatement& node) + { + node.funcIndex = m_nextFuncIndex++; + node.returnType = ResolveType(node.returnType); + for (auto& parameter : node.parameters) + parameter.type = ResolveType(parameter.type); + + PushScope(); + { + for (auto& parameter : node.parameters) + { + std::size_t varIndex = RegisterVariable(parameter.name); + if (!node.varIndex) + node.varIndex = varIndex; + } + + AstCloner::Visit(node); + } + PopScope(); + } + + void TransformVisitor::Visit(DeclareStructStatement& node) + { + node.structIndex = RegisterStruct(node.description.name, node.description); + + AstCloner::Visit(node); + } + + void TransformVisitor::Visit(DeclareVariableStatement& node) + { + node.varType = ResolveType(node.varType); + node.varIndex = RegisterVariable(node.varName); + + AstCloner::Visit(node); + } + + void TransformVisitor::Visit(MultiStatement& node) + { + PushScope(); + { + AstCloner::Visit(node); + } + PopScope(); + } + + ExpressionPtr TransformVisitor::Clone(AccessMemberIdentifierExpression& node) + { + auto accessMemberIndex = std::make_unique(); + accessMemberIndex->structExpr = CloneExpression(node.structExpr); + accessMemberIndex->cachedExpressionType = node.cachedExpressionType; + accessMemberIndex->memberIndices.resize(node.memberIdentifiers.size()); + + ExpressionType exprType = GetExpressionType(*node.structExpr); + for (std::size_t i = 0; i < node.memberIdentifiers.size(); ++i) + { + exprType = ResolveType(exprType); + assert(std::holds_alternative(exprType)); + + std::size_t structIndex = std::get(exprType).structIndex; + assert(structIndex < m_structs.size()); + const StructDescription& structDesc = m_structs[structIndex]; + + auto it = std::find_if(structDesc.members.begin(), structDesc.members.end(), [&](const auto& member) { return member.name == node.memberIdentifiers[i]; }); + assert(it != structDesc.members.end()); + + accessMemberIndex->memberIndices[i] = std::distance(structDesc.members.begin(), it); + exprType = it->type; + } + + return accessMemberIndex; + } + + ExpressionPtr TransformVisitor::Clone(CastExpression& node) + { + ExpressionPtr expr = AstCloner::Clone(node); + + CastExpression* castExpr = static_cast(expr.get()); + castExpr->targetType = ResolveType(castExpr->targetType); + + return expr; + } + + ExpressionPtr TransformVisitor::Clone(IdentifierExpression& node) + { + const Identifier* identifier = FindIdentifier(node.identifier); + assert(identifier); + assert(std::holds_alternative(identifier->value)); + + auto varExpr = std::make_unique(); + varExpr->cachedExpressionType = node.cachedExpressionType; + varExpr->variableId = std::get(identifier->value).varIndex; + + return varExpr; + } + + ExpressionPtr TransformVisitor::CloneExpression(ExpressionPtr& expr) + { + ExpressionPtr exprPtr = AstCloner::CloneExpression(expr); + if (exprPtr) + { + assert(exprPtr->cachedExpressionType); + *exprPtr->cachedExpressionType = ResolveType(*exprPtr->cachedExpressionType); + } + + return exprPtr; + } + + void TransformVisitor::PushScope() + { + m_scopeSizes.push_back(m_identifiersInScope.size()); + } + + void TransformVisitor::PopScope() + { + assert(!m_scopeSizes.empty()); + m_identifiersInScope.resize(m_scopeSizes.back()); + m_scopeSizes.pop_back(); + } +} diff --git a/src/Nazara/Shader/GlslWriter.cpp b/src/Nazara/Shader/GlslWriter.cpp index 0f1aaac4a..46c63e5f7 100644 --- a/src/Nazara/Shader/GlslWriter.cpp +++ b/src/Nazara/Shader/GlslWriter.cpp @@ -330,6 +330,11 @@ namespace Nz } } + void GlslWriter::Append(const ShaderAst::StructType& structType) + { + throw std::runtime_error("unexpected struct type"); + } + void GlslWriter::Append(const ShaderAst::UniformType& uniformType) { /* TODO */ @@ -371,6 +376,7 @@ namespace Nz m_currentState->stream << param; } + template void GlslWriter::Append(const T1& firstParam, const T2& secondParam, Args&&... params) { @@ -595,7 +601,7 @@ namespace Nz Append(")"); } - void GlslWriter::Visit(ShaderAst::AccessMemberExpression& node) + void GlslWriter::Visit(ShaderAst::AccessMemberIdentifierExpression& node) { Visit(node.structExpr, true); @@ -741,8 +747,6 @@ namespace Nz void GlslWriter::Visit(ShaderAst::DeclareExternalStatement& node) { - - for (const auto& externalVar : node.externalVars) { std::optional bindingIndex; @@ -774,7 +778,7 @@ namespace Nz EnterScope(); { - const Identifier* identifier = FindIdentifier(std::get(externalVar.type).containedType.name); + const Identifier* identifier = FindIdentifier(std::get(std::get(externalVar.type).containedType).name); assert(identifier); assert(std::holds_alternative(identifier->value)); diff --git a/src/Nazara/Shader/ShaderAstCloner.cpp b/src/Nazara/Shader/ShaderAstCloner.cpp index 4ebfa9548..7e1b3256c 100644 --- a/src/Nazara/Shader/ShaderAstCloner.cpp +++ b/src/Nazara/Shader/ShaderAstCloner.cpp @@ -42,13 +42,25 @@ namespace Nz::ShaderAst return PopStatement(); } + StatementPtr AstCloner::Clone(DeclareExternalStatement& node) + { + auto clone = std::make_unique(); + clone->attributes = node.attributes; + clone->externalVars = node.externalVars; + clone->varIndex = node.varIndex; + + return clone; + } + StatementPtr AstCloner::Clone(DeclareFunctionStatement& node) { auto clone = std::make_unique(); clone->attributes = node.attributes; + clone->funcIndex = node.funcIndex; clone->name = node.name; clone->parameters = node.parameters; clone->returnType = node.returnType; + clone->varIndex = node.varIndex; clone->statements.reserve(node.statements.size()); for (auto& statement : node.statements) @@ -57,15 +69,95 @@ namespace Nz::ShaderAst return clone; } - void AstCloner::Visit(AccessMemberExpression& node) + StatementPtr AstCloner::Clone(DeclareStructStatement& node) { - auto clone = std::make_unique(); + auto clone = std::make_unique(); + clone->structIndex = node.structIndex; + clone->description = node.description; + + return clone; + } + + StatementPtr AstCloner::Clone(DeclareVariableStatement& node) + { + auto clone = std::make_unique(); + clone->varIndex = node.varIndex; + clone->varName = node.varName; + clone->varType = node.varType; + clone->initialExpression = CloneExpression(node.initialExpression); + + return clone; + } + + ExpressionPtr AstCloner::Clone(AccessMemberIdentifierExpression& node) + { + auto clone = std::make_unique(); clone->memberIdentifiers = node.memberIdentifiers; clone->structExpr = CloneExpression(node.structExpr); clone->cachedExpressionType = node.cachedExpressionType; - PushExpression(std::move(clone)); + return clone; + } + + ExpressionPtr AstCloner::Clone(AccessMemberIndexExpression& node) + { + auto clone = std::make_unique(); + clone->memberIndices = node.memberIndices; + clone->structExpr = CloneExpression(node.structExpr); + + clone->cachedExpressionType = node.cachedExpressionType; + + return clone; + } + + ExpressionPtr AstCloner::Clone(CastExpression& node) + { + auto clone = std::make_unique(); + clone->targetType = node.targetType; + + std::size_t expressionCount = 0; + for (auto& expr : node.expressions) + { + if (!expr) + break; + + clone->expressions[expressionCount++] = CloneExpression(expr); + } + + clone->cachedExpressionType = node.cachedExpressionType; + + return clone; + } + + ExpressionPtr AstCloner::Clone(IdentifierExpression& node) + { + auto clone = std::make_unique(); + clone->identifier = node.identifier; + + clone->cachedExpressionType = node.cachedExpressionType; + + return clone; + } + + ExpressionPtr AstCloner::Clone(VariableExpression& node) + { + auto clone = std::make_unique(); + clone->variableId = node.variableId; + + clone->cachedExpressionType = node.cachedExpressionType; + + return clone; + } + + void AstCloner::Visit(AccessMemberIdentifierExpression& node) + { + return PushExpression(Clone(node)); + } + + void AstCloner::Visit(AccessMemberIndexExpression& node) + { + return PushExpression(Clone(node)); } void AstCloner::Visit(AssignExpression& node) @@ -94,21 +186,7 @@ namespace Nz::ShaderAst void AstCloner::Visit(CastExpression& node) { - auto clone = std::make_unique(); - clone->targetType = node.targetType; - - std::size_t expressionCount = 0; - for (auto& expr : node.expressions) - { - if (!expr) - break; - - clone->expressions[expressionCount++] = CloneExpression(expr); - } - - clone->cachedExpressionType = node.cachedExpressionType; - - PushExpression(std::move(clone)); + PushExpression(Clone(node)); } void AstCloner::Visit(ConditionalExpression& node) @@ -135,12 +213,7 @@ namespace Nz::ShaderAst void AstCloner::Visit(IdentifierExpression& node) { - auto clone = std::make_unique(); - clone->identifier = node.identifier; - - clone->cachedExpressionType = node.cachedExpressionType; - - PushExpression(std::move(clone)); + PushExpression(Clone(node)); } void AstCloner::Visit(IntrinsicExpression& node) @@ -169,6 +242,11 @@ namespace Nz::ShaderAst PushExpression(std::move(clone)); } + void AstCloner::Visit(VariableExpression& node) + { + PushExpression(Clone(node)); + } + void AstCloner::Visit(BranchStatement& node) { auto clone = std::make_unique(); @@ -197,11 +275,7 @@ namespace Nz::ShaderAst void AstCloner::Visit(DeclareExternalStatement& node) { - auto clone = std::make_unique(); - clone->attributes = node.attributes; - clone->externalVars = node.externalVars; - - PushStatement(std::move(clone)); + PushStatement(Clone(node)); } void AstCloner::Visit(DeclareFunctionStatement& node) @@ -211,20 +285,12 @@ namespace Nz::ShaderAst void AstCloner::Visit(DeclareStructStatement& node) { - auto clone = std::make_unique(); - clone->description = node.description; - - PushStatement(std::move(clone)); + PushStatement(Clone(node)); } void AstCloner::Visit(DeclareVariableStatement& node) { - auto clone = std::make_unique(); - clone->varName = node.varName; - clone->varType = node.varType; - clone->initialExpression = CloneExpression(node.initialExpression); - - PushStatement(std::move(clone)); + PushStatement(Clone(node)); } void AstCloner::Visit(DiscardStatement& /*node*/) diff --git a/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp b/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp index e0a87ad51..52e6dc3eb 100644 --- a/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp +++ b/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp @@ -7,7 +7,12 @@ namespace Nz::ShaderAst { - void AstRecursiveVisitor::Visit(AccessMemberExpression& node) + void AstRecursiveVisitor::Visit(AccessMemberIdentifierExpression& node) + { + node.structExpr->Visit(*this); + } + + void AstRecursiveVisitor::Visit(AccessMemberIndexExpression& node) { node.structExpr->Visit(*this); } @@ -62,6 +67,11 @@ namespace Nz::ShaderAst node.expression->Visit(*this); } + void AstRecursiveVisitor::Visit(VariableExpression& node) + { + /* Nothing to do */ + } + void AstRecursiveVisitor::Visit(BranchStatement& node) { for (auto& cond : node.condStatements) diff --git a/src/Nazara/Shader/ShaderAstScopedVisitor.cpp b/src/Nazara/Shader/ShaderAstScopedVisitor.cpp index cc1aec980..39e80470e 100644 --- a/src/Nazara/Shader/ShaderAstScopedVisitor.cpp +++ b/src/Nazara/Shader/ShaderAstScopedVisitor.cpp @@ -53,7 +53,7 @@ namespace Nz::ShaderAst { ExpressionType subType = extVar.type; if (IsUniformType(subType)) - subType = IdentifierType{ std::get(subType).containedType }; + subType = std::get(std::get(subType).containedType); RegisterVariable(extVar.name, std::move(subType)); } diff --git a/src/Nazara/Shader/ShaderAstSerializer.cpp b/src/Nazara/Shader/ShaderAstSerializer.cpp index 20b0b4b63..7102e45fa 100644 --- a/src/Nazara/Shader/ShaderAstSerializer.cpp +++ b/src/Nazara/Shader/ShaderAstSerializer.cpp @@ -33,7 +33,7 @@ namespace Nz::ShaderAst }; } - void AstSerializerBase::Serialize(AccessMemberExpression& node) + void AstSerializerBase::Serialize(AccessMemberIdentifierExpression& node) { Node(node.structExpr); @@ -42,6 +42,15 @@ namespace Nz::ShaderAst Value(identifier); } + void AstSerializerBase::Serialize(AccessMemberIndexExpression& node) + { + Node(node.structExpr); + + Container(node.memberIndices); + for (std::size_t& identifier : node.memberIndices) + SizeT(identifier); + } + void AstSerializerBase::Serialize(AssignExpression& node) { Enum(node.op); @@ -133,6 +142,11 @@ namespace Nz::ShaderAst Enum(node.components[i]); } + void AstSerializerBase::Serialize(VariableExpression& node) + { + SizeT(node.variableId); + } + void AstSerializerBase::Serialize(BranchStatement& node) { @@ -364,14 +378,19 @@ namespace Nz::ShaderAst m_stream << UInt32(arg.dim); m_stream << UInt32(arg.sampledType); } - else if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) { m_stream << UInt8(5); - m_stream << arg.containedType.name; + m_stream << UInt32(arg.structIndex); + } + else if constexpr (std::is_same_v) + { + m_stream << UInt8(6); + m_stream << std::get(arg.containedType).name; } else if constexpr (std::is_same_v) { - m_stream << UInt8(6); + m_stream << UInt8(7); m_stream << UInt32(arg.componentCount); m_stream << UInt32(arg.type); } @@ -621,7 +640,18 @@ namespace Nz::ShaderAst break; } - case 5: //< UniformType + case 5: //< StructType + { + UInt32 structIndex; + Value(structIndex); + + type = StructType{ + structIndex + }; + break; + } + + case 6: //< UniformType { std::string containedType; Value(containedType); @@ -634,7 +664,7 @@ namespace Nz::ShaderAst break; } - case 6: //< VectorType + case 7: //< VectorType { UInt32 componentCount; PrimitiveType componentType; diff --git a/src/Nazara/Shader/ShaderAstUtils.cpp b/src/Nazara/Shader/ShaderAstUtils.cpp index c26d38ae5..47f73cdeb 100644 --- a/src/Nazara/Shader/ShaderAstUtils.cpp +++ b/src/Nazara/Shader/ShaderAstUtils.cpp @@ -13,7 +13,12 @@ namespace Nz::ShaderAst return m_expressionCategory; } - void ShaderAstValueCategory::Visit(AccessMemberExpression& node) + void ShaderAstValueCategory::Visit(AccessMemberIdentifierExpression& node) + { + node.structExpr->Visit(*this); + } + + void ShaderAstValueCategory::Visit(AccessMemberIndexExpression& node) { node.structExpr->Visit(*this); } @@ -66,4 +71,9 @@ namespace Nz::ShaderAst { node.expression->Visit(*this); } + + void ShaderAstValueCategory::Visit(VariableExpression& node) + { + m_expressionCategory = ExpressionCategory::LValue; + } } diff --git a/src/Nazara/Shader/ShaderAstValidator.cpp b/src/Nazara/Shader/ShaderAstValidator.cpp index 57610a357..8f998341e 100644 --- a/src/Nazara/Shader/ShaderAstValidator.cpp +++ b/src/Nazara/Shader/ShaderAstValidator.cpp @@ -131,7 +131,7 @@ namespace Nz::ShaderAst return expressionType; } - void AstValidator::Visit(AccessMemberExpression& node) + void AstValidator::Visit(AccessMemberIdentifierExpression& node) { // Register expressions types AstScopedVisitor::Visit(node); @@ -351,7 +351,7 @@ namespace Nz::ShaderAst if (!exprPtr) break; - ExpressionType exprType = GetExpressionType(*exprPtr); + const ExpressionType& exprType = GetExpressionType(*exprPtr); if (!IsPrimitiveType(exprType) && !IsVectorType(exprType)) throw AstError{ "incompatible type" }; @@ -552,14 +552,17 @@ namespace Nz::ShaderAst void AstValidator::Visit(DeclareExternalStatement& node) { - for (const auto& [attributeType, arg] : node.attributes) + if (!node.attributes.empty()) + throw AstError{ "unhandled attribute for external block" }; + + /*for (const auto& [attributeType, arg] : node.attributes) { switch (attributeType) { default: throw AstError{ "unhandled attribute for external block" }; } - } + }*/ for (const auto& extVar : node.externalVars) { diff --git a/src/Nazara/Shader/ShaderLangParser.cpp b/src/Nazara/Shader/ShaderLangParser.cpp index 3a493ab30..b896055a0 100644 --- a/src/Nazara/Shader/ShaderLangParser.cpp +++ b/src/Nazara/Shader/ShaderLangParser.cpp @@ -602,7 +602,7 @@ namespace Nz::ShaderLang if (Peek().type == TokenType::Dot) { - std::unique_ptr accessMemberNode = std::make_unique(); + std::unique_ptr accessMemberNode = std::make_unique(); accessMemberNode->structExpr = std::move(identifierExpr); do @@ -685,9 +685,9 @@ namespace Nz::ShaderLang if (IsVariableInScope(identifier)) { auto node = ParseIdentifier(); - if (node->GetType() == ShaderAst::NodeType::AccessMemberExpression) + if (node->GetType() == ShaderAst::NodeType::AccessMemberIdentifierExpression) { - ShaderAst::AccessMemberExpression* memberExpr = static_cast(node.get()); + ShaderAst::AccessMemberIdentifierExpression* memberExpr = static_cast(node.get()); if (!memberExpr->memberIdentifiers.empty() && memberExpr->memberIdentifiers.front() == "Sample") { if (Peek().type == TokenType::OpenParenthesis) diff --git a/src/Nazara/Shader/SpirvAstVisitor.cpp b/src/Nazara/Shader/SpirvAstVisitor.cpp index 28aca39ca..9e0795751 100644 --- a/src/Nazara/Shader/SpirvAstVisitor.cpp +++ b/src/Nazara/Shader/SpirvAstVisitor.cpp @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include #include #include @@ -12,6 +13,11 @@ namespace Nz { + UInt32 SpirvAstVisitor::AllocateResultId() + { + return m_writer.AllocateResultId(); + } + UInt32 SpirvAstVisitor::EvaluateExpression(ShaderAst::ExpressionPtr& expr) { expr->Visit(*this); @@ -20,9 +26,16 @@ namespace Nz return PopResultId(); } - void SpirvAstVisitor::Visit(ShaderAst::AccessMemberExpression& node) + auto SpirvAstVisitor::GetVariable(std::size_t varIndex) const -> const Variable& { - SpirvExpressionLoad accessMemberVisitor(m_writer, *m_currentBlock); + assert(varIndex < m_variables.size()); + assert(m_variables[varIndex]); + return *m_variables[varIndex]; + } + + void SpirvAstVisitor::Visit(ShaderAst::AccessMemberIndexExpression& node) + { + SpirvExpressionLoad accessMemberVisitor(m_writer, *this, *m_currentBlock); PushResultId(accessMemberVisitor.Evaluate(node)); } @@ -30,7 +43,7 @@ namespace Nz { UInt32 resultId = EvaluateExpression(node.right); - SpirvExpressionStore storeVisitor(m_writer, *m_currentBlock); + SpirvExpressionStore storeVisitor(m_writer, *this, *m_currentBlock); storeVisitor.Store(node.left, resultId); PushResultId(resultId); @@ -38,18 +51,24 @@ namespace Nz void SpirvAstVisitor::Visit(ShaderAst::BinaryExpression& node) { - ShaderAst::ExpressionType resultExprType = GetExpressionType(node); - assert(IsPrimitiveType(resultExprType)); + auto RetrieveBaseType = [](const ShaderAst::ExpressionType& exprType) + { + if (IsPrimitiveType(exprType)) + return std::get(exprType); + else if (IsVectorType(exprType)) + return std::get(exprType).type; + else if (IsMatrixType(exprType)) + return std::get(exprType).type; + else + throw std::runtime_error("unexpected type"); + }; - ShaderAst::ExpressionType leftExprType = GetExpressionType(*node.left); - assert(IsPrimitiveType(leftExprType)); + const ShaderAst::ExpressionType& resultType = GetExpressionType(node); + const ShaderAst::ExpressionType& leftType = GetExpressionType(*node.left); + const ShaderAst::ExpressionType& rightType = GetExpressionType(*node.right); - ShaderAst::ExpressionType rightExprType = GetExpressionType(*node.right); - assert(IsPrimitiveType(rightExprType)); - - ShaderAst::PrimitiveType resultType = std::get(resultExprType); - ShaderAst::PrimitiveType leftType = std::get(leftExprType); - ShaderAst::PrimitiveType rightType = std::get(rightExprType); + ShaderAst::PrimitiveType leftTypeBase = RetrieveBaseType(leftType); + ShaderAst::PrimitiveType rightTypeBase = RetrieveBaseType(rightType); UInt32 leftOperand = EvaluateExpression(node.left); @@ -64,28 +83,16 @@ namespace Nz { case ShaderAst::BinaryType::Add: { - switch (leftType) + switch (leftTypeBase) { case ShaderAst::PrimitiveType::Float32: -// case ShaderAst::PrimitiveType::Float2: -// case ShaderAst::PrimitiveType::Float3: -// case ShaderAst::PrimitiveType::Float4: -// case ShaderAst::PrimitiveType::Mat4x4: return SpirvOp::OpFAdd; case ShaderAst::PrimitiveType::Int32: -// case ShaderAst::PrimitiveType::Int2: -// case ShaderAst::PrimitiveType::Int3: -// case ShaderAst::PrimitiveType::Int4: case ShaderAst::PrimitiveType::UInt32: -// case ShaderAst::PrimitiveType::UInt2: -// case ShaderAst::PrimitiveType::UInt3: -// case ShaderAst::PrimitiveType::UInt4: return SpirvOp::OpIAdd; case ShaderAst::PrimitiveType::Boolean: -// case ShaderAst::PrimitiveType::Sampler2D: -// case ShaderAst::PrimitiveType::Void: break; } @@ -94,28 +101,16 @@ namespace Nz case ShaderAst::BinaryType::Subtract: { - switch (leftType) + switch (leftTypeBase) { case ShaderAst::PrimitiveType::Float32: -// case ShaderAst::PrimitiveType::Float2: -// case ShaderAst::PrimitiveType::Float3: -// case ShaderAst::PrimitiveType::Float4: -// case ShaderAst::PrimitiveType::Mat4x4: return SpirvOp::OpFSub; case ShaderAst::PrimitiveType::Int32: -// case ShaderAst::PrimitiveType::Int2: -// case ShaderAst::PrimitiveType::Int3: -// case ShaderAst::PrimitiveType::Int4: case ShaderAst::PrimitiveType::UInt32: -// case ShaderAst::PrimitiveType::UInt2: -// case ShaderAst::PrimitiveType::UInt3: -// case ShaderAst::PrimitiveType::UInt4: return SpirvOp::OpISub; case ShaderAst::PrimitiveType::Boolean: -// case ShaderAst::PrimitiveType::Sampler2D: -// case ShaderAst::PrimitiveType::Void: break; } @@ -124,30 +119,18 @@ namespace Nz case ShaderAst::BinaryType::Divide: { - switch (leftType) + switch (leftTypeBase) { case ShaderAst::PrimitiveType::Float32: -// case ShaderAst::PrimitiveType::Float2: -// case ShaderAst::PrimitiveType::Float3: -// case ShaderAst::PrimitiveType::Float4: -// case ShaderAst::PrimitiveType::Mat4x4: return SpirvOp::OpFDiv; case ShaderAst::PrimitiveType::Int32: -// case ShaderAst::PrimitiveType::Int2: -// case ShaderAst::PrimitiveType::Int3: -// case ShaderAst::PrimitiveType::Int4: return SpirvOp::OpSDiv; case ShaderAst::PrimitiveType::UInt32: -// case ShaderAst::PrimitiveType::UInt2: -// case ShaderAst::PrimitiveType::UInt3: -// case ShaderAst::PrimitiveType::UInt4: return SpirvOp::OpUDiv; case ShaderAst::PrimitiveType::Boolean: -// case ShaderAst::PrimitiveType::Sampler2D: -// case ShaderAst::PrimitiveType::Void: break; } @@ -156,31 +139,17 @@ namespace Nz case ShaderAst::BinaryType::CompEq: { - switch (leftType) + switch (leftTypeBase) { case ShaderAst::PrimitiveType::Boolean: return SpirvOp::OpLogicalEqual; case ShaderAst::PrimitiveType::Float32: -// case ShaderAst::PrimitiveType::Float2: -// case ShaderAst::PrimitiveType::Float3: -// case ShaderAst::PrimitiveType::Float4: -// case ShaderAst::PrimitiveType::Mat4x4: return SpirvOp::OpFOrdEqual; case ShaderAst::PrimitiveType::Int32: -// case ShaderAst::PrimitiveType::Int2: -// case ShaderAst::PrimitiveType::Int3: -// case ShaderAst::PrimitiveType::Int4: case ShaderAst::PrimitiveType::UInt32: -// case ShaderAst::PrimitiveType::UInt2: -// case ShaderAst::PrimitiveType::UInt3: -// case ShaderAst::PrimitiveType::UInt4: return SpirvOp::OpIEqual; - -// case ShaderAst::PrimitiveType::Sampler2D: -// case ShaderAst::PrimitiveType::Void: -// break; } break; @@ -188,30 +157,18 @@ namespace Nz case ShaderAst::BinaryType::CompGe: { - switch (leftType) + switch (leftTypeBase) { case ShaderAst::PrimitiveType::Float32: -// case ShaderAst::PrimitiveType::Float2: -// case ShaderAst::PrimitiveType::Float3: -// case ShaderAst::PrimitiveType::Float4: -// case ShaderAst::PrimitiveType::Mat4x4: return SpirvOp::OpFOrdGreaterThan; case ShaderAst::PrimitiveType::Int32: -// case ShaderAst::PrimitiveType::Int2: -// case ShaderAst::PrimitiveType::Int3: -// case ShaderAst::PrimitiveType::Int4: return SpirvOp::OpSGreaterThan; case ShaderAst::PrimitiveType::UInt32: -// case ShaderAst::PrimitiveType::UInt2: -// case ShaderAst::PrimitiveType::UInt3: -// case ShaderAst::PrimitiveType::UInt4: return SpirvOp::OpUGreaterThan; case ShaderAst::PrimitiveType::Boolean: -// case ShaderAst::PrimitiveType::Sampler2D: -// case ShaderAst::PrimitiveType::Void: break; } @@ -220,30 +177,18 @@ namespace Nz case ShaderAst::BinaryType::CompGt: { - switch (leftType) + switch (leftTypeBase) { case ShaderAst::PrimitiveType::Float32: -// case ShaderAst::PrimitiveType::Float2: -// case ShaderAst::PrimitiveType::Float3: -// case ShaderAst::PrimitiveType::Float4: -// case ShaderAst::PrimitiveType::Mat4x4: return SpirvOp::OpFOrdGreaterThanEqual; case ShaderAst::PrimitiveType::Int32: -// case ShaderAst::PrimitiveType::Int2: -// case ShaderAst::PrimitiveType::Int3: -// case ShaderAst::PrimitiveType::Int4: return SpirvOp::OpSGreaterThanEqual; case ShaderAst::PrimitiveType::UInt32: -// case ShaderAst::PrimitiveType::UInt2: -// case ShaderAst::PrimitiveType::UInt3: -// case ShaderAst::PrimitiveType::UInt4: return SpirvOp::OpUGreaterThanEqual; case ShaderAst::PrimitiveType::Boolean: -// case ShaderAst::PrimitiveType::Sampler2D: -// case ShaderAst::PrimitiveType::Void: break; } @@ -252,30 +197,18 @@ namespace Nz case ShaderAst::BinaryType::CompLe: { - switch (leftType) + switch (leftTypeBase) { case ShaderAst::PrimitiveType::Float32: -// case ShaderAst::PrimitiveType::Float2: -// case ShaderAst::PrimitiveType::Float3: -// case ShaderAst::PrimitiveType::Float4: -// case ShaderAst::PrimitiveType::Mat4x4: return SpirvOp::OpFOrdLessThanEqual; case ShaderAst::PrimitiveType::Int32: -// case ShaderAst::PrimitiveType::Int2: -// case ShaderAst::PrimitiveType::Int3: -// case ShaderAst::PrimitiveType::Int4: return SpirvOp::OpSLessThanEqual; case ShaderAst::PrimitiveType::UInt32: -// case ShaderAst::PrimitiveType::UInt2: -// case ShaderAst::PrimitiveType::UInt3: -// case ShaderAst::PrimitiveType::UInt4: return SpirvOp::OpULessThanEqual; case ShaderAst::PrimitiveType::Boolean: -// case ShaderAst::PrimitiveType::Sampler2D: -// case ShaderAst::PrimitiveType::Void: break; } @@ -284,30 +217,18 @@ namespace Nz case ShaderAst::BinaryType::CompLt: { - switch (leftType) + switch (leftTypeBase) { case ShaderAst::PrimitiveType::Float32: -// case ShaderAst::PrimitiveType::Float2: -// case ShaderAst::PrimitiveType::Float3: -// case ShaderAst::PrimitiveType::Float4: -// case ShaderAst::PrimitiveType::Mat4x4: return SpirvOp::OpFOrdLessThan; case ShaderAst::PrimitiveType::Int32: -// case ShaderAst::PrimitiveType::Int2: -// case ShaderAst::PrimitiveType::Int3: -// case ShaderAst::PrimitiveType::Int4: return SpirvOp::OpSLessThan; case ShaderAst::PrimitiveType::UInt32: -// case ShaderAst::PrimitiveType::UInt2: -// case ShaderAst::PrimitiveType::UInt3: -// case ShaderAst::PrimitiveType::UInt4: return SpirvOp::OpULessThan; case ShaderAst::PrimitiveType::Boolean: -// case ShaderAst::PrimitiveType::Sampler2D: -// case ShaderAst::PrimitiveType::Void: break; } @@ -316,31 +237,17 @@ namespace Nz case ShaderAst::BinaryType::CompNe: { - switch (leftType) + switch (leftTypeBase) { case ShaderAst::PrimitiveType::Boolean: return SpirvOp::OpLogicalNotEqual; case ShaderAst::PrimitiveType::Float32: -// case ShaderAst::PrimitiveType::Float2: -// case ShaderAst::PrimitiveType::Float3: -// case ShaderAst::PrimitiveType::Float4: -// case ShaderAst::PrimitiveType::Mat4x4: return SpirvOp::OpFOrdNotEqual; case ShaderAst::PrimitiveType::Int32: -// case ShaderAst::PrimitiveType::Int2: -// case ShaderAst::PrimitiveType::Int3: -// case ShaderAst::PrimitiveType::Int4: case ShaderAst::PrimitiveType::UInt32: -// case ShaderAst::PrimitiveType::UInt2: -// case ShaderAst::PrimitiveType::UInt3: -// case ShaderAst::PrimitiveType::UInt4: return SpirvOp::OpINotEqual; - -// case ShaderAst::PrimitiveType::Sampler2D: -// case ShaderAst::PrimitiveType::Void: -// break; } break; @@ -348,81 +255,51 @@ namespace Nz case ShaderAst::BinaryType::Multiply: { - switch (leftType) + switch (leftTypeBase) { case ShaderAst::PrimitiveType::Float32: { - switch (rightType) + if (IsPrimitiveType(leftType)) { - case ShaderAst::PrimitiveType::Float32: - return SpirvOp::OpFMul; - -// case ShaderAst::PrimitiveType::Float2: -// case ShaderAst::PrimitiveType::Float3: -// case ShaderAst::PrimitiveType::Float4: -// swapOperands = true; -// return SpirvOp::OpVectorTimesScalar; -// -// case ShaderAst::PrimitiveType::Mat4x4: -// swapOperands = true; -// return SpirvOp::OpMatrixTimesScalar; - - default: - break; + // Handle float * matrix|vector as matrix|vector * float + if (IsMatrixType(rightType)) + { + swapOperands = true; + return SpirvOp::OpMatrixTimesScalar; + } + else if (IsVectorType(rightType)) + { + swapOperands = true; + return SpirvOp::OpVectorTimesScalar; + } + } + else if (IsPrimitiveType(rightType)) + { + if (IsMatrixType(leftType)) + return SpirvOp::OpMatrixTimesScalar; + else if (IsVectorType(leftType)) + return SpirvOp::OpVectorTimesScalar; + } + else if (IsMatrixType(leftType)) + { + if (IsMatrixType(rightType)) + return SpirvOp::OpMatrixTimesMatrix; + else if (IsVectorType(rightType)) + return SpirvOp::OpMatrixTimesVector; + } + else if (IsMatrixType(rightType)) + { + assert(IsVectorType(leftType)); + return SpirvOp::OpVectorTimesMatrix; } - break; + return SpirvOp::OpFMul; } -// case ShaderAst::PrimitiveType::Float2: -// case ShaderAst::PrimitiveType::Float3: -// case ShaderAst::PrimitiveType::Float4: -// { -// switch (rightType) -// { -// case ShaderAst::PrimitiveType::Float32: -// return SpirvOp::OpVectorTimesScalar; -// -// case ShaderAst::PrimitiveType::Float2: -// case ShaderAst::PrimitiveType::Float3: -// case ShaderAst::PrimitiveType::Float4: -// return SpirvOp::OpFMul; -// -// case ShaderAst::PrimitiveType::Mat4x4: -// return SpirvOp::OpVectorTimesMatrix; -// -// default: -// break; -// } -// -// break; -// } - case ShaderAst::PrimitiveType::Int32: -// case ShaderAst::PrimitiveType::Int2: -// case ShaderAst::PrimitiveType::Int3: -// case ShaderAst::PrimitiveType::Int4: case ShaderAst::PrimitiveType::UInt32: -// case ShaderAst::PrimitiveType::UInt2: -// case ShaderAst::PrimitiveType::UInt3: -// case ShaderAst::PrimitiveType::UInt4: return SpirvOp::OpIMul; -// case ShaderAst::PrimitiveType::Mat4x4: -// { -// switch (rightType) -// { -// case ShaderAst::PrimitiveType::Float32: return SpirvOp::OpMatrixTimesScalar; -// case ShaderAst::PrimitiveType::Float4: return SpirvOp::OpMatrixTimesVector; -// case ShaderAst::PrimitiveType::Mat4x4: return SpirvOp::OpMatrixTimesMatrix; -// -// default: -// break; -// } -// -// break; -// } - default: break; } @@ -454,7 +331,7 @@ namespace Nz firstCond.statement->Visit(*this); SpirvBlock mergeBlock(m_writer); - m_blocks.back().Append(SpirvOp::OpSelectionMerge, mergeBlock.GetLabelId(), SpirvSelectionControl::None); + m_functionBlocks.back().Append(SpirvOp::OpSelectionMerge, mergeBlock.GetLabelId(), SpirvSelectionControl::None); std::optional nextBlock; for (std::size_t statementIndex = 1; statementIndex < node.condStatements.size(); ++statementIndex) @@ -463,10 +340,10 @@ namespace Nz SpirvBlock contentBlock(m_writer); - m_blocks.back().Append(SpirvOp::OpBranchConditional, previousConditionId, previousContentBlock.GetLabelId(), contentBlock.GetLabelId()); + m_functionBlocks.back().Append(SpirvOp::OpBranchConditional, previousConditionId, previousContentBlock.GetLabelId(), contentBlock.GetLabelId()); previousConditionId = EvaluateExpression(statement.condition); - m_blocks.emplace_back(std::move(previousContentBlock)); + m_functionBlocks.emplace_back(std::move(previousContentBlock)); previousContentBlock = std::move(contentBlock); m_currentBlock = &previousContentBlock; @@ -479,54 +356,148 @@ namespace Nz SpirvBlock elseBlock(m_writer); m_currentBlock = &elseBlock; + node.elseStatement->Visit(*this); elseBlock.Append(SpirvOp::OpBranch, mergeBlock.GetLabelId()); //< FIXME: Shouldn't terminate twice - m_blocks.back().Append(SpirvOp::OpBranchConditional, previousConditionId, previousContentBlock.GetLabelId(), elseBlock.GetLabelId()); - m_blocks.emplace_back(std::move(previousContentBlock)); - m_blocks.emplace_back(std::move(elseBlock)); + m_functionBlocks.back().Append(SpirvOp::OpBranchConditional, previousConditionId, previousContentBlock.GetLabelId(), elseBlock.GetLabelId()); + m_functionBlocks.emplace_back(std::move(previousContentBlock)); + m_functionBlocks.emplace_back(std::move(elseBlock)); } else { - m_blocks.back().Append(SpirvOp::OpBranchConditional, previousConditionId, previousContentBlock.GetLabelId(), mergeBlock.GetLabelId()); - m_blocks.emplace_back(std::move(previousContentBlock)); + m_functionBlocks.back().Append(SpirvOp::OpBranchConditional, previousConditionId, previousContentBlock.GetLabelId(), mergeBlock.GetLabelId()); + m_functionBlocks.emplace_back(std::move(previousContentBlock)); } - m_blocks.emplace_back(std::move(mergeBlock)); + m_functionBlocks.emplace_back(std::move(mergeBlock)); - m_currentBlock = &m_blocks.back(); + m_currentBlock = &m_functionBlocks.back(); } void SpirvAstVisitor::Visit(ShaderAst::CastExpression& node) { const ShaderAst::ExpressionType& targetExprType = node.targetType; - assert(IsPrimitiveType(targetExprType)); - - ShaderAst::PrimitiveType targetType = std::get(targetExprType); - - StackVector exprResults = NazaraStackVector(UInt32, node.expressions.size()); - - for (auto& exprPtr : node.expressions) + if (IsPrimitiveType(targetExprType)) { - if (!exprPtr) - break; + ShaderAst::PrimitiveType targetType = std::get(targetExprType); - exprResults.push_back(EvaluateExpression(exprPtr)); + assert(node.expressions[0] && !node.expressions[1]); + ShaderAst::ExpressionPtr& expression = node.expressions[0]; + + assert(expression->cachedExpressionType.has_value()); + const ShaderAst::ExpressionType& exprType = expression->cachedExpressionType.value(); + assert(IsPrimitiveType(exprType)); + ShaderAst::PrimitiveType fromType = std::get(exprType); + + UInt32 fromId = EvaluateExpression(expression); + if (targetType == fromType) + return PushResultId(fromId); + + std::optional castOp; + switch (targetType) + { + case ShaderAst::PrimitiveType::Boolean: + throw std::runtime_error("unsupported cast to boolean"); + + case ShaderAst::PrimitiveType::Float32: + { + switch (fromType) + { + case ShaderAst::PrimitiveType::Boolean: + throw std::runtime_error("unsupported cast from boolean"); + + case ShaderAst::PrimitiveType::Float32: + break; //< Already handled + + case ShaderAst::PrimitiveType::Int32: + castOp = SpirvOp::OpConvertSToF; + break; + + case ShaderAst::PrimitiveType::UInt32: + castOp = SpirvOp::OpConvertUToF; + break; + } + break; + } + + case ShaderAst::PrimitiveType::Int32: + { + switch (fromType) + { + case ShaderAst::PrimitiveType::Boolean: + throw std::runtime_error("unsupported cast from boolean"); + + case ShaderAst::PrimitiveType::Float32: + castOp = SpirvOp::OpConvertFToS; + break; + + case ShaderAst::PrimitiveType::Int32: + break; //< Already handled + + case ShaderAst::PrimitiveType::UInt32: + castOp = SpirvOp::OpSConvert; + break; + } + break; + } + + case ShaderAst::PrimitiveType::UInt32: + { + switch (fromType) + { + case ShaderAst::PrimitiveType::Boolean: + throw std::runtime_error("unsupported cast from boolean"); + + case ShaderAst::PrimitiveType::Float32: + castOp = SpirvOp::OpConvertFToU; + break; + + case ShaderAst::PrimitiveType::Int32: + castOp = SpirvOp::OpUConvert; + break; + + case ShaderAst::PrimitiveType::UInt32: + break; //< Already handled + } + break; + } + } + + assert(castOp); + + UInt32 resultId = m_writer.AllocateResultId(); + m_currentBlock->Append(*castOp, m_writer.GetTypeId(targetType), resultId, fromId); + + throw std::runtime_error("toudou"); } - - UInt32 resultId = m_writer.AllocateResultId(); - - m_currentBlock->AppendVariadic(SpirvOp::OpCompositeConstruct, [&](const auto& appender) + else { - appender(m_writer.GetTypeId(targetType)); - appender(resultId); + assert(IsVectorType(targetExprType)); + StackVector exprResults = NazaraStackVector(UInt32, node.expressions.size()); - for (UInt32 exprResultId : exprResults) - appender(exprResultId); - }); + for (auto& exprPtr : node.expressions) + { + if (!exprPtr) + break; - PushResultId(resultId); + exprResults.push_back(EvaluateExpression(exprPtr)); + } + + UInt32 resultId = m_writer.AllocateResultId(); + + m_currentBlock->AppendVariadic(SpirvOp::OpCompositeConstruct, [&](const auto& appender) + { + appender(m_writer.GetTypeId(targetExprType)); + appender(resultId); + + for (UInt32 exprResultId : exprResults) + appender(exprResultId); + }); + + PushResultId(resultId); + } } void SpirvAstVisitor::Visit(ShaderAst::ConditionalExpression& node) @@ -551,10 +522,108 @@ namespace Nz }, node.value); } + void SpirvAstVisitor::Visit(ShaderAst::DeclareExternalStatement& node) + { + assert(node.varIndex); + + std::size_t varIndex = *node.varIndex; + for (auto&& extVar : node.externalVars) + RegisterExternalVariable(varIndex++, extVar.type); + } + + void SpirvAstVisitor::Visit(ShaderAst::DeclareFunctionStatement& node) + { + assert(node.funcIndex); + m_funcIndex = *node.funcIndex; + + auto& func = m_funcData[m_funcIndex]; + func.funcId = m_writer.AllocateResultId(); + + m_instructions.Append(SpirvOp::OpFunction, func.returnTypeId, func.funcId, 0, func.funcTypeId); + + if (!func.parameters.empty()) + { + std::size_t varIndex = *node.varIndex; + for (const auto& param : func.parameters) + { + UInt32 paramResultId = m_writer.AllocateResultId(); + m_instructions.Append(SpirvOp::OpFunctionParameter, param.typeId, paramResultId); + + RegisterVariable(varIndex++, param.typeId, paramResultId, SpirvStorageClass::Function); + } + } + + m_functionBlocks.clear(); + + m_currentBlock = &m_functionBlocks.emplace_back(m_writer); + CallOnExit resetCurrentBlock([&] { m_currentBlock = nullptr; }); + + for (auto& var : func.variables) + { + var.varId = m_writer.AllocateResultId(); + m_currentBlock->Append(SpirvOp::OpVariable, var.typeId, var.varId, SpirvStorageClass::Function); + } + + if (func.entryPointData) + { + auto& entryPointData = *func.entryPointData; + if (entryPointData.inputStruct) + { + auto& inputStruct = *entryPointData.inputStruct; + + std::size_t varIndex = *node.varIndex; + + UInt32 paramId = m_writer.AllocateResultId(); + m_currentBlock->Append(SpirvOp::OpVariable, inputStruct.pointerId, paramId, SpirvStorageClass::Function); + + for (const auto& input : entryPointData.inputs) + { + UInt32 resultId = m_writer.AllocateResultId(); + m_currentBlock->Append(SpirvOp::OpAccessChain, input.memberPointerId, resultId, paramId, input.memberIndexConstantId); + m_currentBlock->Append(SpirvOp::OpCopyMemory, resultId, input.varId); + } + + RegisterVariable(varIndex, inputStruct.typeId, paramId, SpirvStorageClass::Function); + } + } + + for (auto& statementPtr : node.statements) + statementPtr->Visit(*this); + + // Add implicit return + if (!m_functionBlocks.back().IsTerminated()) + m_functionBlocks.back().Append(SpirvOp::OpReturn); + + for (SpirvBlock& block : m_functionBlocks) + m_instructions.AppendSection(block); + + m_instructions.Append(SpirvOp::OpFunctionEnd); + } + + void SpirvAstVisitor::Visit(ShaderAst::DeclareStructStatement& node) + { + assert(node.structIndex); + RegisterStruct(*node.structIndex, node.description); + } + void SpirvAstVisitor::Visit(ShaderAst::DeclareVariableStatement& node) { + const auto& func = m_funcData[m_funcIndex]; + + UInt32 pointerTypeId = m_writer.GetPointerTypeId(node.varType, SpirvStorageClass::Function); + UInt32 typeId = m_writer.GetTypeId(node.varType); + + assert(node.varIndex); + auto varIt = func.varIndexToVarId.find(*node.varIndex); + UInt32 varId = func.variables[varIt->second].varId; + + RegisterVariable(*node.varIndex, typeId, varId, SpirvStorageClass::Function); + if (node.initialExpression) - m_writer.WriteLocalVariable(node.varName, EvaluateExpression(node.initialExpression)); + { + UInt32 value = EvaluateExpression(node.initialExpression); + m_currentBlock->Append(SpirvOp::OpStore, varId, value); + } } void SpirvAstVisitor::Visit(ShaderAst::DiscardStatement& /*node*/) @@ -569,19 +638,13 @@ namespace Nz PopResultId(); } - void SpirvAstVisitor::Visit(ShaderAst::IdentifierExpression& node) - { - SpirvExpressionLoad loadVisitor(m_writer, *m_currentBlock); - PushResultId(loadVisitor.Evaluate(node)); - } - void SpirvAstVisitor::Visit(ShaderAst::IntrinsicExpression& node) { switch (node.intrinsic) { case ShaderAst::IntrinsicType::DotProduct: { - ShaderAst::ExpressionType vecExprType = GetExpressionType(*node.parameters[0]); + const ShaderAst::ExpressionType& vecExprType = GetExpressionType(*node.parameters[0]); assert(IsVectorType(vecExprType)); const ShaderAst::VectorType& vecType = std::get(vecExprType); @@ -598,6 +661,19 @@ namespace Nz break; } + case ShaderAst::IntrinsicType::SampleTexture: + { + UInt32 typeId = m_writer.GetTypeId(ShaderAst::VectorType{4, ShaderAst::PrimitiveType::Float32}); + + UInt32 samplerId = EvaluateExpression(node.parameters[0]); + UInt32 coordinatesId = EvaluateExpression(node.parameters[1]); + UInt32 resultId = m_writer.AllocateResultId(); + + m_currentBlock->Append(SpirvOp::OpImageSampleImplicitLod, typeId, resultId, samplerId, coordinatesId); + PushResultId(resultId); + break; + } + case ShaderAst::IntrinsicType::CrossProduct: default: throw std::runtime_error("not yet implemented"); @@ -609,23 +685,44 @@ namespace Nz // nothing to do } - void SpirvAstVisitor::Visit(ShaderAst::ReturnStatement& node) - { - if (node.returnExpr) - m_currentBlock->Append(SpirvOp::OpReturnValue, EvaluateExpression(node.returnExpr)); - else - m_currentBlock->Append(SpirvOp::OpReturn); - } - void SpirvAstVisitor::Visit(ShaderAst::MultiStatement& node) { for (auto& statement : node.statements) statement->Visit(*this); } + void SpirvAstVisitor::Visit(ShaderAst::ReturnStatement& node) + { + if (node.returnExpr) + { + // Handle entry point return + const auto& func = m_funcData[m_funcIndex]; + if (func.entryPointData) + { + auto& entryPointData = *func.entryPointData; + if (entryPointData.outputStructTypeId) + { + UInt32 paramId = EvaluateExpression(node.returnExpr); + for (const auto& output : entryPointData.outputs) + { + UInt32 resultId = m_writer.AllocateResultId(); + m_currentBlock->Append(SpirvOp::OpCompositeExtract, output.typeId, resultId, paramId, output.memberIndex); + m_currentBlock->Append(SpirvOp::OpStore, output.varId, resultId); + } + } + + m_currentBlock->Append(SpirvOp::OpReturn); + } + else + m_currentBlock->Append(SpirvOp::OpReturnValue, EvaluateExpression(node.returnExpr)); + } + else + m_currentBlock->Append(SpirvOp::OpReturn); + } + void SpirvAstVisitor::Visit(ShaderAst::SwizzleExpression& node) { - ShaderAst::ExpressionType targetExprType = GetExpressionType(node); + const ShaderAst::ExpressionType& targetExprType = GetExpressionType(node); assert(IsPrimitiveType(targetExprType)); ShaderAst::PrimitiveType targetType = std::get(targetExprType); @@ -658,6 +755,12 @@ namespace Nz PushResultId(resultId); } + void SpirvAstVisitor::Visit(ShaderAst::VariableExpression& node) + { + SpirvExpressionLoad loadVisitor(m_writer, *this, *m_currentBlock); + PushResultId(loadVisitor.Evaluate(node)); + } + void SpirvAstVisitor::PushResultId(UInt32 value) { m_resultIds.push_back(value); diff --git a/src/Nazara/Shader/SpirvConstantCache.cpp b/src/Nazara/Shader/SpirvConstantCache.cpp index 2aff0d642..ad2fa52d8 100644 --- a/src/Nazara/Shader/SpirvConstantCache.cpp +++ b/src/Nazara/Shader/SpirvConstantCache.cpp @@ -50,11 +50,6 @@ namespace Nz return Compare(lhs.parameters, rhs.parameters) && Compare(lhs.returnType, rhs.returnType); } - bool Compare(const Identifier& lhs, const Identifier& rhs) const - { - return lhs.name == rhs.name; - } - bool Compare(const Image& lhs, const Image& rhs) const { return lhs.arrayed == rhs.arrayed @@ -114,6 +109,9 @@ namespace Nz if (lhs.debugName != rhs.debugName) return false; + if (lhs.funcId != rhs.funcId) + return false; + if (!Compare(lhs.initializer, rhs.initializer)) return false; @@ -231,11 +229,6 @@ namespace Nz void Register(const Integer&) {} void Register(const Void&) {} - void Register(const Identifier& identifier) - { - Register(identifier); - } - void Register(const Image& image) { Register(image.sampledType); @@ -406,6 +399,7 @@ namespace Nz tsl::ordered_map, UInt32 /*id*/, AnyHasher, Eq> ids; tsl::ordered_map variableIds; tsl::ordered_map structureSizes; + StructCallback structCallback; UInt32& nextResultId; }; @@ -417,132 +411,8 @@ namespace Nz SpirvConstantCache::SpirvConstantCache(SpirvConstantCache&& cache) noexcept = default; SpirvConstantCache::~SpirvConstantCache() = default; - - UInt32 SpirvConstantCache::GetId(const Constant& c) - { - auto it = m_internal->ids.find(c.constant); - if (it == m_internal->ids.end()) - throw std::runtime_error("constant is not registered"); - - return it->second; - } - - UInt32 SpirvConstantCache::GetId(const Type& t) - { - auto it = m_internal->ids.find(t.type); - if (it == m_internal->ids.end()) - throw std::runtime_error("constant is not registered"); - - return it->second; - } - - UInt32 SpirvConstantCache::GetId(const Variable& v) - { - auto it = m_internal->variableIds.find(v); - if (it == m_internal->variableIds.end()) - throw std::runtime_error("variable is not registered"); - - return it->second; - } - - UInt32 SpirvConstantCache::Register(Constant c) - { - AnyConstant& constant = c.constant; - - DepRegisterer registerer(*this); - registerer.Register(constant); - - std::size_t h = m_internal->ids.hash_function()(constant); - auto it = m_internal->ids.find(constant, h); - if (it == m_internal->ids.end()) - { - UInt32 resultId = m_internal->nextResultId++; - it = m_internal->ids.emplace(std::move(constant), resultId).first; - } - - return it.value(); - } - - UInt32 SpirvConstantCache::Register(Type t) - { - AnyType& type = t.type; - if (std::holds_alternative(type)) - { - assert(m_identifierCallback); - return Register(*m_identifierCallback(std::get(type).name)); - } - - DepRegisterer registerer(*this); - registerer.Register(type); - - std::size_t h = m_internal->ids.hash_function()(type); - auto it = m_internal->ids.find(type, h); - if (it == m_internal->ids.end()) - { - UInt32 resultId = m_internal->nextResultId++; - it = m_internal->ids.emplace(std::move(type), resultId).first; - } - - return it.value(); - } - - UInt32 SpirvConstantCache::Register(Variable v) - { - DepRegisterer registerer(*this); - registerer.Register(v); - - std::size_t h = m_internal->variableIds.hash_function()(v); - auto it = m_internal->variableIds.find(v, h); - if (it == m_internal->variableIds.end()) - { - UInt32 resultId = m_internal->nextResultId++; - it = m_internal->variableIds.emplace(std::move(v), resultId).first; - } - - return it.value(); - } - - void SpirvConstantCache::SetIdentifierCallback(IdentifierCallback callback) - { - m_identifierCallback = std::move(callback); - } - - void SpirvConstantCache::Write(SpirvSection& annotations, SpirvSection& constants, SpirvSection& debugInfos) - { - for (auto&& [object, id] : m_internal->ids) - { - UInt32 resultId = id; - - std::visit(overloaded - { - [&](const AnyConstant& constant) { Write(constant, resultId, constants); }, - [&](const AnyType& type) { Write(type, resultId, annotations, constants, debugInfos); }, - }, object); - } - - for (auto&& [variable, id] : m_internal->variableIds) - { - const auto& var = variable; - UInt32 resultId = id; - - if (!variable.debugName.empty()) - debugInfos.Append(SpirvOp::OpName, resultId, variable.debugName); - - constants.AppendVariadic(SpirvOp::OpVariable, [&](const auto& appender) - { - appender(GetId(*var.type)); - appender(resultId); - appender(var.storageClass); - - if (var.initializer) - appender(GetId((*var.initializer)->constant)); - }); - } - } - - SpirvConstantCache& SpirvConstantCache::operator=(SpirvConstantCache&& cache) noexcept = default; - - auto SpirvConstantCache::BuildConstant(const ShaderConstantValue& value) -> ConstantPtr + + auto SpirvConstantCache::BuildConstant(const ShaderAst::ConstantValue& value) const -> ConstantPtr { return std::make_shared(std::visit([&](auto&& arg) -> SpirvConstantCache::AnyConstant { @@ -590,7 +460,7 @@ namespace Nz }, value)); } - auto SpirvConstantCache::BuildFunctionType(const ShaderAst::ExpressionType& retType, const std::vector& parameters) -> TypePtr + auto SpirvConstantCache::BuildFunctionType(const ShaderAst::ExpressionType& retType, const std::vector& parameters) const -> TypePtr { std::vector parameterTypes; parameterTypes.reserve(parameters.size()); @@ -604,7 +474,7 @@ namespace Nz }); } - auto SpirvConstantCache::BuildPointerType(const ShaderAst::ExpressionType& type, SpirvStorageClass storageClass) -> TypePtr + auto SpirvConstantCache::BuildPointerType(const ShaderAst::ExpressionType& type, SpirvStorageClass storageClass) const -> TypePtr { return std::make_shared(Pointer{ BuildType(type), @@ -612,7 +482,7 @@ namespace Nz }); } - auto SpirvConstantCache::BuildPointerType(const ShaderAst::PrimitiveType& type, SpirvStorageClass storageClass) -> TypePtr + auto SpirvConstantCache::BuildPointerType(const ShaderAst::PrimitiveType& type, SpirvStorageClass storageClass) const -> TypePtr { return std::make_shared(Pointer{ BuildType(type), @@ -620,7 +490,7 @@ namespace Nz }); } - auto SpirvConstantCache::BuildType(const ShaderAst::ExpressionType& type) -> TypePtr + auto SpirvConstantCache::BuildType(const ShaderAst::ExpressionType& type) const -> TypePtr { return std::visit([&](auto&& arg) -> TypePtr { @@ -628,16 +498,13 @@ namespace Nz }, type); } - auto SpirvConstantCache::BuildType(const ShaderAst::IdentifierType& type) -> TypePtr + auto SpirvConstantCache::BuildType(const ShaderAst::IdentifierType& type) const -> TypePtr { - return std::make_shared( - Identifier{ - type.name - } - ); + // No IdentifierType is expected (as they should have been resolved by now) + throw std::runtime_error("unexpected identifier"); } - auto SpirvConstantCache::BuildType(const ShaderAst::PrimitiveType& type) -> TypePtr + auto SpirvConstantCache::BuildType(const ShaderAst::PrimitiveType& type) const -> TypePtr { return std::make_shared([&]() -> AnyType { @@ -657,7 +524,7 @@ namespace Nz }()); } - auto SpirvConstantCache::BuildType(const ShaderAst::MatrixType& type) -> TypePtr + auto SpirvConstantCache::BuildType(const ShaderAst::MatrixType& type) const -> TypePtr { return std::make_shared( Matrix{ @@ -668,12 +535,12 @@ namespace Nz }); } - auto SpirvConstantCache::BuildType(const ShaderAst::NoType& type) -> TypePtr + auto SpirvConstantCache::BuildType(const ShaderAst::NoType& type) const -> TypePtr { return std::make_shared(Void{}); } - auto SpirvConstantCache::BuildType(const ShaderAst::SamplerType& type) -> TypePtr + auto SpirvConstantCache::BuildType(const ShaderAst::SamplerType& type) const -> TypePtr { //TODO auto imageType = Image{ @@ -690,7 +557,13 @@ namespace Nz return std::make_shared(SampledImage{ std::make_shared(imageType) }); } - auto SpirvConstantCache::BuildType(const ShaderAst::StructDescription& structDesc) -> TypePtr + auto SpirvConstantCache::BuildType(const ShaderAst::StructType& type) const -> TypePtr + { + assert(m_internal->structCallback); + return BuildType(m_internal->structCallback(type.structIndex)); + } + + auto SpirvConstantCache::BuildType(const ShaderAst::StructDescription& structDesc) const -> TypePtr { Structure sType; sType.name = structDesc.name; @@ -705,11 +578,136 @@ namespace Nz return std::make_shared(std::move(sType)); } - auto SpirvConstantCache::BuildType(const ShaderAst::VectorType& type) -> TypePtr + auto SpirvConstantCache::BuildType(const ShaderAst::VectorType& type) const -> TypePtr { return std::make_shared(Vector{ BuildType(type.type), UInt32(type.componentCount) }); } + auto SpirvConstantCache::BuildType(const ShaderAst::UniformType& type) const -> TypePtr + { + assert(std::holds_alternative(type.containedType)); + return BuildType(std::get(type.containedType)); + } + + UInt32 SpirvConstantCache::GetId(const Constant& c) + { + auto it = m_internal->ids.find(c.constant); + if (it == m_internal->ids.end()) + throw std::runtime_error("constant is not registered"); + + return it->second; + } + + UInt32 SpirvConstantCache::GetId(const Type& t) + { + auto it = m_internal->ids.find(t.type); + if (it == m_internal->ids.end()) + throw std::runtime_error("type is not registered"); + + return it->second; + } + + UInt32 SpirvConstantCache::GetId(const Variable& v) + { + auto it = m_internal->variableIds.find(v); + if (it == m_internal->variableIds.end()) + throw std::runtime_error("variable is not registered"); + + return it->second; + } + + UInt32 SpirvConstantCache::Register(Constant c) + { + AnyConstant& constant = c.constant; + + DepRegisterer registerer(*this); + registerer.Register(constant); + + std::size_t h = m_internal->ids.hash_function()(constant); + auto it = m_internal->ids.find(constant, h); + if (it == m_internal->ids.end()) + { + UInt32 resultId = m_internal->nextResultId++; + it = m_internal->ids.emplace(std::move(constant), resultId).first; + } + + return it.value(); + } + + UInt32 SpirvConstantCache::Register(Type t) + { + AnyType& type = t.type; + + DepRegisterer registerer(*this); + registerer.Register(type); + + std::size_t h = m_internal->ids.hash_function()(type); + auto it = m_internal->ids.find(type, h); + if (it == m_internal->ids.end()) + { + UInt32 resultId = m_internal->nextResultId++; + it = m_internal->ids.emplace(std::move(type), resultId).first; + } + + return it.value(); + } + + UInt32 SpirvConstantCache::Register(Variable v) + { + DepRegisterer registerer(*this); + registerer.Register(v); + + std::size_t h = m_internal->variableIds.hash_function()(v); + auto it = m_internal->variableIds.find(v, h); + if (it == m_internal->variableIds.end()) + { + UInt32 resultId = m_internal->nextResultId++; + it = m_internal->variableIds.emplace(std::move(v), resultId).first; + } + + return it.value(); + } + + void SpirvConstantCache::SetStructCallback(StructCallback callback) + { + m_internal->structCallback = std::move(callback); + } + + void SpirvConstantCache::Write(SpirvSection& annotations, SpirvSection& constants, SpirvSection& debugInfos) + { + for (auto&& [object, id] : m_internal->ids) + { + UInt32 resultId = id; + + std::visit(overloaded + { + [&](const AnyConstant& constant) { Write(constant, resultId, constants); }, + [&](const AnyType& type) { Write(type, resultId, annotations, constants, debugInfos); }, + }, object); + } + + for (auto&& [variable, id] : m_internal->variableIds) + { + const auto& var = variable; + UInt32 resultId = id; + + if (!variable.debugName.empty()) + debugInfos.Append(SpirvOp::OpName, resultId, variable.debugName); + + constants.AppendVariadic(SpirvOp::OpVariable, [&](const auto& appender) + { + appender(GetId(*var.type)); + appender(resultId); + appender(var.storageClass); + + if (var.initializer) + appender(GetId((*var.initializer)->constant)); + }); + } + } + + SpirvConstantCache& SpirvConstantCache::operator=(SpirvConstantCache&& cache) noexcept = default; + void SpirvConstantCache::Write(const AnyConstant& constant, UInt32 resultId, SpirvSection& constants) { std::visit([&](auto&& arg) diff --git a/src/Nazara/Shader/SpirvDecoder.cpp b/src/Nazara/Shader/SpirvDecoder.cpp index 141b009f1..cef949889 100644 --- a/src/Nazara/Shader/SpirvDecoder.cpp +++ b/src/Nazara/Shader/SpirvDecoder.cpp @@ -38,6 +38,8 @@ namespace Nz while (m_currentCodepoint < m_codepointEnd) { + const UInt32* instructionBegin = m_currentCodepoint; + UInt32 firstWord = ReadWord(); UInt16 wordCount = static_cast((firstWord >> 16) & 0xFFFF); @@ -50,7 +52,7 @@ namespace Nz if (!HandleOpcode(*inst, wordCount)) break; - m_currentCodepoint += wordCount - 1; + m_currentCodepoint = instructionBegin + wordCount; } } diff --git a/src/Nazara/Shader/SpirvExpressionLoad.cpp b/src/Nazara/Shader/SpirvExpressionLoad.cpp index 068280bd1..12c0d2838 100644 --- a/src/Nazara/Shader/SpirvExpressionLoad.cpp +++ b/src/Nazara/Shader/SpirvExpressionLoad.cpp @@ -3,7 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include +#include #include #include #include @@ -24,9 +24,8 @@ namespace Nz { [this](const Pointer& pointer) -> UInt32 { - UInt32 resultId = m_writer.AllocateResultId(); - - m_block.Append(SpirvOp::OpLoad, pointer.pointedTypeId, resultId, pointer.resultId); + UInt32 resultId = m_visitor.AllocateResultId(); + m_block.Append(SpirvOp::OpLoad, pointer.pointedTypeId, resultId, pointer.pointerId); return resultId; }, @@ -41,25 +40,26 @@ namespace Nz }, m_value); } - /*void SpirvExpressionLoad::Visit(ShaderAst::AccessMemberExpression& node) + void SpirvExpressionLoad::Visit(ShaderAst::AccessMemberIndexExpression& node) { - Visit(node.structExpr); + node.structExpr->Visit(*this); + + const ShaderAst::ExpressionType& exprType = GetExpressionType(node); + + UInt32 resultId = m_visitor.AllocateResultId(); + UInt32 typeId = m_writer.GetTypeId(exprType); std::visit(overloaded { [&](const Pointer& pointer) { - ShaderAst::ShaderExpressionType exprType = GetExpressionType(node.structExpr); - - UInt32 resultId = m_writer.AllocateResultId(); - UInt32 pointerType = m_writer.RegisterPointerType(node.exprType, pointer.storage); //< FIXME - UInt32 typeId = m_writer.GetTypeId(node.exprType); + UInt32 pointerType = m_writer.RegisterPointerType(exprType, pointer.storage); //< FIXME m_block.AppendVariadic(SpirvOp::OpAccessChain, [&](const auto& appender) { appender(pointerType); appender(resultId); - appender(pointer.resultId); + appender(pointer.pointerId); for (std::size_t index : node.memberIndices) appender(m_writer.GetConstantId(Int32(index))); @@ -69,9 +69,6 @@ namespace Nz }, [&](const Value& value) { - UInt32 resultId = m_writer.AllocateResultId(); - UInt32 typeId = m_writer.GetTypeId(node.exprType); - m_block.AppendVariadic(SpirvOp::OpCompositeExtract, [&](const auto& appender) { appender(typeId); @@ -89,15 +86,11 @@ namespace Nz throw std::runtime_error("an internal error occurred"); } }, m_value); - }*/ + } - void SpirvExpressionLoad::Visit(ShaderAst::IdentifierExpression& node) + void SpirvExpressionLoad::Visit(ShaderAst::VariableExpression& node) { - if (node.identifier == "d") - m_value = Value{ m_writer.ReadLocalVariable(node.identifier) }; - else - m_value = Value{ m_writer.ReadParameterVariable(node.identifier) }; - - //Visit(node.var); + const auto& var = m_visitor.GetVariable(node.variableId); + m_value = Pointer{ var.storage, var.pointerId, var.pointedTypeId }; } } diff --git a/src/Nazara/Shader/SpirvExpressionStore.cpp b/src/Nazara/Shader/SpirvExpressionStore.cpp index 8655b3a94..6015319c0 100644 --- a/src/Nazara/Shader/SpirvExpressionStore.cpp +++ b/src/Nazara/Shader/SpirvExpressionStore.cpp @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include #include #include @@ -23,11 +24,11 @@ namespace Nz { [&](const Pointer& pointer) { - m_block.Append(SpirvOp::OpStore, pointer.resultId, resultId); + m_block.Append(SpirvOp::OpStore, pointer.pointerId, resultId); }, [&](const LocalVar& value) { - m_writer.WriteLocalVariable(value.varName, resultId); + throw std::runtime_error("not yet implemented"); }, [](std::monostate) { @@ -36,49 +37,50 @@ namespace Nz }, m_value); } - /*void SpirvExpressionStore::Visit(ShaderAst::AccessMemberExpression& node) + void SpirvExpressionStore::Visit(ShaderAst::AccessMemberIndexExpression& node) { - Visit(node.structExpr); + node.structExpr->Visit(*this); + + const ShaderAst::ExpressionType& exprType = GetExpressionType(node); std::visit(overloaded { - [&](const Pointer& pointer) -> UInt32 + [&](const Pointer& pointer) { - UInt32 resultId = m_writer.AllocateResultId(); - UInt32 pointerType = m_writer.RegisterPointerType(node.exprType, pointer.storage); //< FIXME + UInt32 resultId = m_visitor.AllocateResultId(); + UInt32 pointerType = m_writer.RegisterPointerType(exprType, pointer.storage); //< FIXME m_block.AppendVariadic(SpirvOp::OpAccessChain, [&](const auto& appender) { appender(pointerType); appender(resultId); - appender(pointer.resultId); + appender(pointer.pointerId); for (std::size_t index : node.memberIndices) appender(m_writer.GetConstantId(Int32(index))); }); - m_value = Pointer{ pointer.storage, resultId }; - - return resultId; + m_value = Pointer { pointer.storage, resultId }; }, - [](const LocalVar& value) -> UInt32 + [&](const LocalVar& value) { throw std::runtime_error("not yet implemented"); }, - [](std::monostate) -> UInt32 + [](std::monostate) { throw std::runtime_error("an internal error occurred"); } }, m_value); - }*/ - - void SpirvExpressionStore::Visit(ShaderAst::IdentifierExpression& node) - { - m_value = LocalVar{ node.identifier }; } void SpirvExpressionStore::Visit(ShaderAst::SwizzleExpression& node) { throw std::runtime_error("not yet implemented"); } + + void SpirvExpressionStore::Visit(ShaderAst::VariableExpression& node) + { + const auto& var = m_visitor.GetVariable(node.variableId); + m_value = Pointer{ var.storage, var.pointerId }; + } } diff --git a/src/Nazara/Shader/SpirvPrinter.cpp b/src/Nazara/Shader/SpirvPrinter.cpp index cd618c8bb..373d7e2c9 100644 --- a/src/Nazara/Shader/SpirvPrinter.cpp +++ b/src/Nazara/Shader/SpirvPrinter.cpp @@ -68,7 +68,7 @@ namespace Nz UInt32 resultId = 0; std::size_t currentOperand = 0; - const UInt32* endPtr = startPtr + wordCount; + const UInt32* endPtr = startPtr + wordCount - 1; while (GetCurrentPtr() < endPtr) { const SpirvInstruction::Operand* operand = &instruction.operands[currentOperand]; @@ -209,7 +209,7 @@ namespace Nz m_currentState->stream << "\n"; - assert(GetCurrentPtr() == startPtr + wordCount); + assert(GetCurrentPtr() == startPtr + wordCount - 1); return true; } diff --git a/src/Nazara/Shader/SpirvWriter.cpp b/src/Nazara/Shader/SpirvWriter.cpp index 0627c569e..8ef74aef7 100644 --- a/src/Nazara/Shader/SpirvWriter.cpp +++ b/src/Nazara/Shader/SpirvWriter.cpp @@ -12,10 +12,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -25,34 +27,61 @@ namespace Nz { namespace { + //FIXME: Have this only once + std::unordered_map s_entryPoints = { + { "frag", ShaderStageType::Fragment }, + { "vert", ShaderStageType::Vertex }, + }; + + struct Builtin + { + const char* debugName; + ShaderStageTypeFlags compatibleStages; + SpirvBuiltIn decoration; + }; + + std::unordered_map s_builtinMapping = { + { "position", { "VertexPosition", ShaderStageType::Vertex, SpirvBuiltIn::Position } } + }; + class PreVisitor : public ShaderAst::AstScopedVisitor { public: + struct UniformVar + { + std::optional bindingIndex; + UInt32 pointerId; + }; + + using BuiltinDecoration = std::map; + using LocationDecoration = std::map; using ExtInstList = std::unordered_set; + using ExtVarContainer = std::unordered_map; using LocalContainer = std::unordered_set; using FunctionContainer = std::vector>; + using StructContainer = std::vector; - PreVisitor(const SpirvWriter::States& conditions, SpirvConstantCache& constantCache) : + PreVisitor(const SpirvWriter::States& conditions, SpirvConstantCache& constantCache, std::vector& funcs) : m_conditions(conditions), - m_constantCache(constantCache) + m_constantCache(constantCache), + m_externalBlockIndex(0), + m_funcs(funcs) { - m_constantCache.SetIdentifierCallback([&](const std::string& identifierName) + m_constantCache.SetStructCallback([this](std::size_t structIndex) -> const ShaderAst::StructDescription& { - const Identifier* identifier = FindIdentifier(identifierName); - if (!identifier) - throw std::runtime_error("invalid identifier " + identifierName); - - assert(std::holds_alternative(identifier->value)); - return SpirvConstantCache::BuildType(std::get(identifier->value)); + assert(structIndex < declaredStructs.size()); + return declaredStructs[structIndex]; }); } - void Visit(ShaderAst::AccessMemberExpression& node) override + void Visit(ShaderAst::AccessMemberIndexExpression& node) override { - /*for (std::size_t index : node.memberIdentifiers) - m_constantCache.Register(*SpirvConstantCache::BuildConstant(Int32(index)));*/ - AstRecursiveVisitor::Visit(node); + + for (std::size_t index : node.memberIndices) + m_constantCache.Register(*m_constantCache.BuildConstant(Int32(index))); + + m_constantCache.Register(*m_constantCache.BuildType(node.cachedExpressionType.value())); } void Visit(ShaderAst::ConditionalExpression& node) override @@ -64,6 +93,8 @@ namespace Nz Visit(node.truePath); else Visit(node.falsePath);*/ + + m_constantCache.Register(*m_constantCache.BuildType(node.cachedExpressionType.value())); } void Visit(ShaderAst::ConditionalStatement& node) override @@ -79,52 +110,189 @@ namespace Nz { std::visit([&](auto&& arg) { - m_constantCache.Register(*SpirvConstantCache::BuildConstant(arg)); + m_constantCache.Register(*m_constantCache.BuildConstant(arg)); }, node.value); AstScopedVisitor::Visit(node); } + void Visit(ShaderAst::DeclareExternalStatement& node) override + { + assert(node.varIndex); + std::size_t varIndex = *node.varIndex; + for (auto& extVar : node.externalVars) + { + SpirvConstantCache::Variable variable; + variable.debugName = extVar.name; + variable.storageClass = (ShaderAst::IsSamplerType(extVar.type)) ? SpirvStorageClass::UniformConstant : SpirvStorageClass::Uniform; + variable.type = m_constantCache.BuildPointerType(extVar.type, variable.storageClass); + + UniformVar& uniformVar = extVars[varIndex++]; + uniformVar.pointerId = m_constantCache.Register(variable); + + for (const auto& [attributeType, attributeParam] : extVar.attributes) + { + if (attributeType == ShaderAst::AttributeType::Binding) + { + uniformVar.bindingIndex = std::get(attributeParam); + break; + } + } + } + } + void Visit(ShaderAst::DeclareFunctionStatement& node) override { - funcs.emplace_back(node); + std::optional entryPointType; + for (auto& attribute : node.attributes) + { + if (attribute.type == ShaderAst::AttributeType::Entry) + { + auto it = s_entryPoints.find(std::get(attribute.args)); + assert(it != s_entryPoints.end()); - std::vector parameterTypes; - for (auto& parameter : node.parameters) - parameterTypes.push_back(parameter.type); + entryPointType = it->second; + break; + } + } - m_constantCache.Register(*SpirvConstantCache::BuildFunctionType(node.returnType, parameterTypes)); + assert(node.funcIndex); + std::size_t funcIndex = *node.funcIndex; + if (funcIndex >= m_funcs.size()) + m_funcs.resize(funcIndex + 1); + + auto& funcData = m_funcs[funcIndex]; + funcData.name = node.name; + + if (!entryPointType) + { + std::vector parameterTypes; + for (auto& parameter : node.parameters) + parameterTypes.push_back(parameter.type); + + funcData.returnTypeId = m_constantCache.Register(*m_constantCache.BuildType(node.returnType)); + funcData.funcTypeId = m_constantCache.Register(*m_constantCache.BuildFunctionType(node.returnType, parameterTypes)); + + for (auto& parameter : node.parameters) + { + auto& funcParam = funcData.parameters.emplace_back(); + funcParam.pointerTypeId = m_constantCache.Register(*m_constantCache.BuildPointerType(parameter.type, SpirvStorageClass::Function)); + funcParam.typeId = m_constantCache.Register(*m_constantCache.BuildType(parameter.type)); + } + } + else + { + using EntryPoint = SpirvAstVisitor::EntryPoint; + + funcData.returnTypeId = m_constantCache.Register(*m_constantCache.BuildType(ShaderAst::NoType{})); + funcData.funcTypeId = m_constantCache.Register(*m_constantCache.BuildFunctionType(ShaderAst::NoType{}, {})); + + std::optional inputStruct; + std::vector inputs; + if (!node.parameters.empty()) + { + assert(node.parameters.size() == 1); + auto& parameter = node.parameters.front(); + assert(std::holds_alternative(parameter.type)); + + std::size_t structIndex = std::get(parameter.type).structIndex; + const ShaderAst::StructDescription& structDesc = declaredStructs[structIndex]; + + std::size_t memberIndex = 0; + for (const auto& member : structDesc.members) + { + if (UInt32 varId = HandleEntryInOutType(*entryPointType, funcIndex, member, SpirvStorageClass::Input); varId != 0) + { + inputs.push_back({ + m_constantCache.Register(*m_constantCache.BuildConstant(Int32(memberIndex))), + m_constantCache.Register(*m_constantCache.BuildPointerType(member.type, SpirvStorageClass::Function)), + varId + }); + } + + memberIndex++; + } + + inputStruct = EntryPoint::InputStruct{ + m_constantCache.Register(*m_constantCache.BuildPointerType(parameter.type, SpirvStorageClass::Function)), + m_constantCache.Register(*m_constantCache.BuildType(parameter.type)) + }; + } + + std::optional outputStructId; + std::vector outputs; + if (!IsNoType(node.returnType)) + { + assert(std::holds_alternative(node.returnType)); + + std::size_t structIndex = std::get(node.returnType).structIndex; + const ShaderAst::StructDescription& structDesc = declaredStructs[structIndex]; + + std::size_t memberIndex = 0; + for (const auto& member : structDesc.members) + { + if (UInt32 varId = HandleEntryInOutType(*entryPointType, funcIndex, member, SpirvStorageClass::Output); varId != 0) + { + outputs.push_back({ + Int32(memberIndex), + m_constantCache.Register(*m_constantCache.BuildType(member.type)), + varId + }); + } + + memberIndex++; + } + + outputStructId = m_constantCache.Register(*m_constantCache.BuildType(node.returnType)); + } + + funcData.entryPointData = EntryPoint{ + *entryPointType, + inputStruct, + outputStructId, + funcIndex, + std::move(inputs), + std::move(outputs) + }; + } + + m_funcIndex = funcIndex; AstScopedVisitor::Visit(node); + m_funcIndex.reset(); } void Visit(ShaderAst::DeclareStructStatement& node) override { AstScopedVisitor::Visit(node); - SpirvConstantCache::Structure sType; - sType.name = node.description.name; + assert(node.structIndex); + std::size_t structIndex = *node.structIndex; + if (structIndex >= declaredStructs.size()) + declaredStructs.resize(structIndex + 1); - for (const auto& [name, attribute, type] : node.description.members) - { - auto& sMembers = sType.members.emplace_back(); - sMembers.name = name; - sMembers.type = SpirvConstantCache::BuildType(type); - } + declaredStructs[structIndex] = node.description; - m_constantCache.Register(SpirvConstantCache::Type{ std::move(sType) }); + m_constantCache.Register(*m_constantCache.BuildType(node.description)); } void Visit(ShaderAst::DeclareVariableStatement& node) override { AstScopedVisitor::Visit(node); - m_constantCache.Register(*SpirvConstantCache::BuildType(node.varType)); + assert(m_funcIndex); + auto& func = m_funcs[*m_funcIndex]; + + assert(node.varIndex); + func.varIndexToVarId[*node.varIndex] = func.variables.size(); + + auto& var = func.variables.emplace_back(); + var.typeId = m_constantCache.Register(*m_constantCache.BuildPointerType(node.varType, SpirvStorageClass::Function)); } void Visit(ShaderAst::IdentifierExpression& node) override { - m_constantCache.Register(*SpirvConstantCache::BuildType(node.cachedExpressionType.value())); + m_constantCache.Register(*m_constantCache.BuildType(node.cachedExpressionType.value())); AstScopedVisitor::Visit(node); } @@ -144,40 +312,88 @@ namespace Nz case ShaderAst::IntrinsicType::DotProduct: break; } + + m_constantCache.Register(*m_constantCache.BuildType(node.cachedExpressionType.value())); } + void Visit(ShaderAst::SwizzleExpression& node) override + { + AstScopedVisitor::Visit(node); + + m_constantCache.Register(*m_constantCache.BuildType(node.cachedExpressionType.value())); + } + + UInt32 HandleEntryInOutType(ShaderStageType entryPointType, std::size_t funcIndex, const ShaderAst::StructDescription::StructMember& member, SpirvStorageClass storageClass) + { + std::optional> builtinOpt; + std::optional attributeLocation; + for (const auto& [attributeType, attributeParam] : member.attributes) + { + if (attributeType == ShaderAst::AttributeType::Builtin) + { + auto it = s_builtinMapping.find(std::get(attributeParam)); + if (it != s_builtinMapping.end()) + { + builtinOpt = it->second; + break; + } + } + else if (attributeType == ShaderAst::AttributeType::Location) + { + attributeLocation = std::get(attributeParam); + break; + } + } + + if (builtinOpt) + { + Builtin& builtin = *builtinOpt; + if ((builtin.compatibleStages & entryPointType) == 0) + return 0; + + SpirvBuiltIn builtinDecoration = builtin.decoration; + + SpirvConstantCache::Variable variable; + variable.debugName = builtin.debugName; + variable.funcId = funcIndex; + variable.storageClass = storageClass; + variable.type = m_constantCache.BuildPointerType(member.type, storageClass); + + UInt32 varId = m_constantCache.Register(variable); + builtinDecorations[varId] = builtinDecoration; + + return varId; + } + else if (attributeLocation) + { + SpirvConstantCache::Variable variable; + variable.debugName = member.name; + variable.funcId = funcIndex; + variable.storageClass = storageClass; + variable.type = m_constantCache.BuildPointerType(member.type, storageClass); + + UInt32 varId = m_constantCache.Register(variable); + locationDecorations[varId] = *attributeLocation; + + return varId; + } + + return 0; + } + + BuiltinDecoration builtinDecorations; ExtInstList extInsts; - FunctionContainer funcs; + ExtVarContainer extVars; + LocationDecoration locationDecorations; + StructContainer declaredStructs; private: const SpirvWriter::States& m_conditions; SpirvConstantCache& m_constantCache; + std::optional m_funcIndex; + std::size_t m_externalBlockIndex; + std::vector& m_funcs; }; - - template - constexpr ShaderAst::PrimitiveType GetBasicType() - { - if constexpr (std::is_same_v) - return ShaderAst::PrimitiveType::Boolean; - else if constexpr (std::is_same_v) - return(ShaderAst::PrimitiveType::Float32); - else if constexpr (std::is_same_v) - return(ShaderAst::PrimitiveType::Int32); - else if constexpr (std::is_same_v) - return(ShaderAst::PrimitiveType::Float2); - else if constexpr (std::is_same_v) - return(ShaderAst::PrimitiveType::Float3); - else if constexpr (std::is_same_v) - return(ShaderAst::PrimitiveType::Float4); - else if constexpr (std::is_same_v) - return(ShaderAst::PrimitiveType::Int2); - else if constexpr (std::is_same_v) - return(ShaderAst::PrimitiveType::Int3); - else if constexpr (std::is_same_v) - return(ShaderAst::PrimitiveType::Int4); - else - static_assert(AlwaysFalse::value, "unhandled type"); - } } struct SpirvWriter::State @@ -194,18 +410,13 @@ namespace Nz UInt32 id; }; - tsl::ordered_map inputIds; - tsl::ordered_map outputIds; - tsl::ordered_map parameterIds; - tsl::ordered_map uniformIds; std::unordered_map extensionInstructions; - std::unordered_map builtinIds; std::unordered_map varToResult; - std::vector funcs; - std::vector functionBlocks; + std::vector funcs; std::vector resultIds; UInt32 nextVarIndex = 1; SpirvConstantCache constantTypeCache; //< init after nextVarIndex + PreVisitor* preVisitor; // Output SpirvSection header; @@ -226,6 +437,9 @@ namespace Nz if (!ShaderAst::ValidateAst(shader, &error)) throw std::runtime_error("Invalid shader AST: " + error); + ShaderAst::TransformVisitor transformVisitor; + ShaderAst::StatementPtr transformedShader = transformVisitor.Transform(shader); + m_context.states = &conditions; State state; @@ -235,245 +449,37 @@ namespace Nz m_currentState = nullptr; }); - ShaderAst::AstCloner cloner; - // Register all extended instruction sets - PreVisitor preVisitor(conditions, state.constantTypeCache); - shader->Visit(preVisitor); + PreVisitor preVisitor(conditions, state.constantTypeCache, state.funcs); + transformedShader->Visit(preVisitor); + + m_currentState->preVisitor = &preVisitor; for (const std::string& extInst : preVisitor.extInsts) state.extensionInstructions[extInst] = AllocateResultId(); - // Register all types - /*for (const auto& func : shader.GetFunctions()) - { - RegisterType(func.returnType); - for (const auto& param : func.parameters) - RegisterType(param.type); - } - - for (const auto& input : shader.GetInputs()) - RegisterPointerType(input.type, SpirvStorageClass::Input); - - for (const auto& output : shader.GetOutputs()) - RegisterPointerType(output.type, SpirvStorageClass::Output); - - for (const auto& uniform : shader.GetUniforms()) - RegisterPointerType(uniform.type, (IsSamplerType(uniform.type)) ? SpirvStorageClass::UniformConstant : SpirvStorageClass::Uniform); - - for (const auto& func : shader.GetFunctions()) - RegisterFunctionType(func.returnType, func.parameters); - - for (const auto& type : preVisitor.variableTypes) - RegisterType(type); - - for (const auto& builtin : preVisitor.builtinVars) - RegisterType(builtin->type); - - // Register result id and debug infos for global variables/functions - for (const auto& builtin : preVisitor.builtinVars) - { - SpirvConstantCache::Variable variable; - SpirvBuiltIn builtinDecoration; - switch (builtin->entry) - { - case ShaderAst::BuiltinEntry::VertexPosition: - variable.debugName = "builtin_VertexPosition"; - variable.storageClass = SpirvStorageClass::Output; - - builtinDecoration = SpirvBuiltIn::Position; - break; - - default: - throw std::runtime_error("unexpected builtin type"); - } - - const ShaderAst::ShaderExpressionType& builtinExprType = builtin->type; - assert(IsBasicType(builtinExprType)); - - ShaderAst::BasicType builtinType = std::get(builtinExprType); - - variable.type = SpirvConstantCache::BuildPointerType(builtinType, variable.storageClass); - - UInt32 varId = m_currentState->constantTypeCache.Register(variable); - - ExtVar builtinData; - builtinData.pointerTypeId = GetPointerTypeId(builtinType, variable.storageClass); - builtinData.typeId = GetTypeId(builtinType); - builtinData.varId = varId; - - state.annotations.Append(SpirvOp::OpDecorate, builtinData.varId, SpirvDecoration::BuiltIn, builtinDecoration); - - state.builtinIds.emplace(builtin->entry, builtinData); - } - - for (const auto& input : shader.GetInputs()) - { - SpirvConstantCache::Variable variable; - variable.debugName = input.name; - variable.storageClass = SpirvStorageClass::Input; - variable.type = SpirvConstantCache::BuildPointerType(shader, input.type, variable.storageClass); - - UInt32 varId = m_currentState->constantTypeCache.Register(variable); - - ExtVar inputData; - inputData.pointerTypeId = GetPointerTypeId(input.type, variable.storageClass); - inputData.typeId = GetTypeId(input.type); - inputData.varId = varId; - - state.inputIds.emplace(input.name, std::move(inputData)); - - if (input.locationIndex) - state.annotations.Append(SpirvOp::OpDecorate, varId, SpirvDecoration::Location, *input.locationIndex); - } - - for (const auto& output : shader.GetOutputs()) - { - SpirvConstantCache::Variable variable; - variable.debugName = output.name; - variable.storageClass = SpirvStorageClass::Output; - variable.type = SpirvConstantCache::BuildPointerType(shader, output.type, variable.storageClass); - - UInt32 varId = m_currentState->constantTypeCache.Register(variable); - - ExtVar outputData; - outputData.pointerTypeId = GetPointerTypeId(output.type, variable.storageClass); - outputData.typeId = GetTypeId(output.type); - outputData.varId = varId; - - state.outputIds.emplace(output.name, std::move(outputData)); - - if (output.locationIndex) - state.annotations.Append(SpirvOp::OpDecorate, varId, SpirvDecoration::Location, *output.locationIndex); - } - - for (const auto& uniform : shader.GetUniforms()) - { - SpirvConstantCache::Variable variable; - variable.debugName = uniform.name; - variable.storageClass = (IsSamplerType(uniform.type)) ? SpirvStorageClass::UniformConstant : SpirvStorageClass::Uniform; - variable.type = SpirvConstantCache::BuildPointerType(shader, uniform.type, variable.storageClass); - - UInt32 varId = m_currentState->constantTypeCache.Register(variable); - - ExtVar uniformData; - uniformData.pointerTypeId = GetPointerTypeId(uniform.type, variable.storageClass); - uniformData.typeId = GetTypeId(uniform.type); - uniformData.varId = varId; - - state.uniformIds.emplace(uniform.name, std::move(uniformData)); - - if (uniform.bindingIndex) - { - state.annotations.Append(SpirvOp::OpDecorate, varId, SpirvDecoration::Binding, *uniform.bindingIndex); - state.annotations.Append(SpirvOp::OpDecorate, varId, SpirvDecoration::DescriptorSet, 0); - } - }*/ - - for (const ShaderAst::DeclareFunctionStatement& func : preVisitor.funcs) - { - auto& funcData = state.funcs.emplace_back(); - funcData.statement = &func; - funcData.id = AllocateResultId(); - funcData.typeId = GetFunctionTypeId(func); - - state.debugInfo.Append(SpirvOp::OpName, funcData.id, func.name); - } - - std::size_t funcIndex = 0; - - for (const ShaderAst::DeclareFunctionStatement& func : preVisitor.funcs) - { - auto& funcData = state.funcs[funcIndex++]; - - state.instructions.Append(SpirvOp::OpFunction, GetTypeId(func.returnType), funcData.id, 0, funcData.typeId); - - state.functionBlocks.clear(); - state.functionBlocks.emplace_back(*this); - - state.parameterIds.clear(); - - for (const auto& param : func.parameters) - { - UInt32 paramResultId = AllocateResultId(); - state.instructions.Append(SpirvOp::OpFunctionParameter, GetTypeId(param.type), paramResultId); - - ExtVar parameterData; - parameterData.pointerTypeId = GetPointerTypeId(param.type, SpirvStorageClass::Function); - parameterData.typeId = GetTypeId(param.type); - parameterData.varId = paramResultId; - - state.parameterIds.emplace(param.name, std::move(parameterData)); - } - - SpirvAstVisitor visitor(*this, state.functionBlocks); - for (const auto& statement : func.statements) - statement->Visit(visitor); - - if (!state.functionBlocks.back().IsTerminated()) - { - assert(func.returnType == ShaderAst::ExpressionType{ ShaderAst::NoType{} }); - state.functionBlocks.back().Append(SpirvOp::OpReturn); - } - - for (SpirvBlock& block : state.functionBlocks) - state.instructions.AppendSection(block); - - state.instructions.Append(SpirvOp::OpFunctionEnd); - } - - m_currentState->constantTypeCache.Write(m_currentState->annotations, m_currentState->constants, m_currentState->debugInfo); + SpirvAstVisitor visitor(*this, state.instructions, state.funcs); + transformedShader->Visit(visitor); AppendHeader(); - for (std::size_t i = 0; i < ShaderStageTypeCount; ++i) + for (auto&& [varIndex, extVar] : preVisitor.extVars) { - /*const ShaderAst::DeclareFunctionStatement* statement = m_context.cache.entryFunctions[i]; - if (!statement) - continue; - - auto it = std::find_if(state.funcs.begin(), state.funcs.end(), [&](const auto& funcData) { return funcData.statement == statement; }); - assert(it != state.funcs.end()); - - const auto& entryFunc = *it; - - SpirvExecutionModel execModel; - - ShaderStageType stage = static_cast(i); - switch (stage) + if (extVar.bindingIndex) { - case ShaderStageType::Fragment: - execModel = SpirvExecutionModel::Fragment; - break; - - case ShaderStageType::Vertex: - execModel = SpirvExecutionModel::Vertex; - break; - - default: - throw std::runtime_error("not yet implemented"); + state.annotations.Append(SpirvOp::OpDecorate, extVar.pointerId, SpirvDecoration::Binding, *extVar.bindingIndex); + state.annotations.Append(SpirvOp::OpDecorate, extVar.pointerId, SpirvDecoration::DescriptorSet, 0); } - - state.header.AppendVariadic(SpirvOp::OpEntryPoint, [&](const auto& appender) - { - appender(execModel); - appender(entryFunc.id); - appender(statement->name); - - for (const auto& [name, varData] : state.builtinIds) - appender(varData.varId); - - for (const auto& [name, varData] : state.inputIds) - appender(varData.varId); - - for (const auto& [name, varData] : state.outputIds) - appender(varData.varId); - }); - - if (stage == ShaderStageType::Fragment) - state.header.Append(SpirvOp::OpExecutionMode, entryFunc.id, SpirvExecutionMode::OriginUpperLeft);*/ } + for (auto&& [varId, builtin] : preVisitor.builtinDecorations) + state.annotations.Append(SpirvOp::OpDecorate, varId, SpirvDecoration::BuiltIn, builtin); + + for (auto&& [varId, location] : preVisitor.locationDecorations) + state.annotations.Append(SpirvOp::OpDecorate, varId, SpirvDecoration::Location, location); + + m_currentState->constantTypeCache.Write(m_currentState->annotations, m_currentState->constants, m_currentState->debugInfo); + std::vector ret; MergeSections(ret, state.header); MergeSections(ret, state.debugInfo); @@ -511,171 +517,53 @@ namespace Nz m_currentState->header.Append(SpirvOp::OpExtInstImport, resultId, extInst); m_currentState->header.Append(SpirvOp::OpMemoryModel, SpirvAddressingModel::Logical, SpirvMemoryModel::GLSL450); - } - UInt32 SpirvWriter::GetConstantId(const ShaderConstantValue& value) const - { - return m_currentState->constantTypeCache.GetId(*SpirvConstantCache::BuildConstant(value)); - } - - UInt32 SpirvWriter::GetFunctionTypeId(const ShaderAst::DeclareFunctionStatement& functionNode) - { - return m_currentState->constantTypeCache.GetId({ *BuildFunctionType(functionNode) }); - } - - auto SpirvWriter::GetBuiltinVariable(ShaderAst::BuiltinEntry builtin) const -> const ExtVar& - { - auto it = m_currentState->builtinIds.find(builtin); - assert(it != m_currentState->builtinIds.end()); - - return it->second; - } - - auto SpirvWriter::GetInputVariable(const std::string& name) const -> const ExtVar& - { - auto it = m_currentState->inputIds.find(name); - assert(it != m_currentState->inputIds.end()); - - return it->second; - } - - auto SpirvWriter::GetOutputVariable(const std::string& name) const -> const ExtVar& - { - auto it = m_currentState->outputIds.find(name); - assert(it != m_currentState->outputIds.end()); - - return it->second; - } - - auto SpirvWriter::GetUniformVariable(const std::string& name) const -> const ExtVar& - { - auto it = m_currentState->uniformIds.find(name); - assert(it != m_currentState->uniformIds.end()); - - return it.value(); - } - - UInt32 SpirvWriter::GetPointerTypeId(const ShaderAst::ExpressionType& type, SpirvStorageClass storageClass) const - { - return m_currentState->constantTypeCache.GetId(*SpirvConstantCache::BuildPointerType(type, storageClass)); - } - - UInt32 SpirvWriter::GetTypeId(const ShaderAst::ExpressionType& type) const - { - return m_currentState->constantTypeCache.GetId(*SpirvConstantCache::BuildType(type)); - } - - UInt32 SpirvWriter::ReadInputVariable(const std::string& name) - { - auto it = m_currentState->inputIds.find(name); - assert(it != m_currentState->inputIds.end()); - - return ReadVariable(it.value()); - } - - std::optional SpirvWriter::ReadInputVariable(const std::string& name, OnlyCache) - { - auto it = m_currentState->inputIds.find(name); - assert(it != m_currentState->inputIds.end()); - - return ReadVariable(it.value(), OnlyCache{}); - } - - UInt32 SpirvWriter::ReadLocalVariable(const std::string& name) - { - auto it = m_currentState->varToResult.find(name); - assert(it != m_currentState->varToResult.end()); - - return it->second; - } - - std::optional SpirvWriter::ReadLocalVariable(const std::string& name, OnlyCache) - { - auto it = m_currentState->varToResult.find(name); - if (it == m_currentState->varToResult.end()) - return {}; - - return it->second; - } - - UInt32 SpirvWriter::ReadParameterVariable(const std::string& name) - { - auto it = m_currentState->parameterIds.find(name); - assert(it != m_currentState->parameterIds.end()); - - return ReadVariable(it.value()); - } - - std::optional SpirvWriter::ReadParameterVariable(const std::string& name, OnlyCache) - { - auto it = m_currentState->parameterIds.find(name); - assert(it != m_currentState->parameterIds.end()); - - return ReadVariable(it.value(), OnlyCache{}); - } - - UInt32 SpirvWriter::ReadUniformVariable(const std::string& name) - { - auto it = m_currentState->uniformIds.find(name); - assert(it != m_currentState->uniformIds.end()); - - return ReadVariable(it.value()); - } - - std::optional SpirvWriter::ReadUniformVariable(const std::string& name, OnlyCache) - { - auto it = m_currentState->uniformIds.find(name); - assert(it != m_currentState->uniformIds.end()); - - return ReadVariable(it.value(), OnlyCache{}); - } - - UInt32 SpirvWriter::ReadVariable(ExtVar& var) - { - if (!var.valueId.has_value()) + std::optional fragmentFuncId; + for (auto& func : m_currentState->funcs) { - UInt32 resultId = AllocateResultId(); - m_currentState->functionBlocks.back().Append(SpirvOp::OpLoad, var.typeId, resultId, var.varId); + m_currentState->debugInfo.Append(SpirvOp::OpName, func.funcId, func.name); - var.valueId = resultId; + if (func.entryPointData) + { + auto& entryPointData = func.entryPointData.value(); + + SpirvExecutionModel execModel; + + switch (entryPointData.stageType) + { + case ShaderStageType::Fragment: + execModel = SpirvExecutionModel::Fragment; + break; + + case ShaderStageType::Vertex: + execModel = SpirvExecutionModel::Vertex; + break; + + default: + throw std::runtime_error("not yet implemented"); + } + + m_currentState->header.AppendVariadic(SpirvOp::OpEntryPoint, [&](const auto& appender) + { + appender(execModel); + appender(func.funcId); + appender(func.name); + + for (const auto& input : entryPointData.inputs) + appender(input.varId); + + for (const auto& output : entryPointData.outputs) + appender(output.varId); + }); + + if (entryPointData.stageType == ShaderStageType::Fragment) + fragmentFuncId = func.funcId; + } } - return var.valueId.value(); - } + if (fragmentFuncId) + m_currentState->header.Append(SpirvOp::OpExecutionMode, *fragmentFuncId, SpirvExecutionMode::OriginUpperLeft); - std::optional SpirvWriter::ReadVariable(const ExtVar& var, OnlyCache) - { - if (!var.valueId.has_value()) - return {}; - - return var.valueId.value(); - } - - UInt32 SpirvWriter::RegisterConstant(const ShaderConstantValue& value) - { - return m_currentState->constantTypeCache.Register(*SpirvConstantCache::BuildConstant(value)); - } - - UInt32 SpirvWriter::RegisterFunctionType(const ShaderAst::DeclareFunctionStatement& functionNode) - { - return m_currentState->constantTypeCache.Register({ *BuildFunctionType(functionNode) }); - } - - UInt32 SpirvWriter::RegisterPointerType(ShaderAst::ExpressionType type, SpirvStorageClass storageClass) - { - return m_currentState->constantTypeCache.Register(*SpirvConstantCache::BuildPointerType(type, storageClass)); - } - - UInt32 SpirvWriter::RegisterType(ShaderAst::ExpressionType type) - { - assert(m_currentState); - return m_currentState->constantTypeCache.Register(*SpirvConstantCache::BuildType(type)); - } - - void SpirvWriter::WriteLocalVariable(std::string name, UInt32 resultId) - { - assert(m_currentState); - m_currentState->varToResult.insert_or_assign(std::move(name), resultId); } SpirvConstantCache::TypePtr SpirvWriter::BuildFunctionType(const ShaderAst::DeclareFunctionStatement& functionNode) @@ -686,7 +574,56 @@ namespace Nz for (const auto& parameter : functionNode.parameters) parameterTypes.push_back(parameter.type); - return SpirvConstantCache::BuildFunctionType(functionNode.returnType, parameterTypes); + return m_currentState->constantTypeCache.BuildFunctionType(functionNode.returnType, parameterTypes); + } + + UInt32 SpirvWriter::GetConstantId(const ShaderAst::ConstantValue& value) const + { + return m_currentState->constantTypeCache.GetId(*m_currentState->constantTypeCache.BuildConstant(value)); + } + + UInt32 SpirvWriter::GetExtVarPointerId(std::size_t extVarIndex) const + { + auto it = m_currentState->preVisitor->extVars.find(extVarIndex); + assert(it != m_currentState->preVisitor->extVars.end()); + + return it->second.pointerId; + } + + UInt32 SpirvWriter::GetFunctionTypeId(const ShaderAst::DeclareFunctionStatement& functionNode) + { + return m_currentState->constantTypeCache.GetId({ *BuildFunctionType(functionNode) }); + } + + UInt32 SpirvWriter::GetPointerTypeId(const ShaderAst::ExpressionType& type, SpirvStorageClass storageClass) const + { + return m_currentState->constantTypeCache.GetId(*m_currentState->constantTypeCache.BuildPointerType(type, storageClass)); + } + + UInt32 SpirvWriter::GetTypeId(const ShaderAst::ExpressionType& type) const + { + return m_currentState->constantTypeCache.GetId(*m_currentState->constantTypeCache.BuildType(type)); + } + + UInt32 SpirvWriter::RegisterConstant(const ShaderAst::ConstantValue& value) + { + return m_currentState->constantTypeCache.Register(*m_currentState->constantTypeCache.BuildConstant(value)); + } + + UInt32 SpirvWriter::RegisterFunctionType(const ShaderAst::DeclareFunctionStatement& functionNode) + { + return m_currentState->constantTypeCache.Register({ *BuildFunctionType(functionNode) }); + } + + UInt32 SpirvWriter::RegisterPointerType(ShaderAst::ExpressionType type, SpirvStorageClass storageClass) + { + return m_currentState->constantTypeCache.Register(*m_currentState->constantTypeCache.BuildPointerType(type, storageClass)); + } + + UInt32 SpirvWriter::RegisterType(ShaderAst::ExpressionType type) + { + assert(m_currentState); + return m_currentState->constantTypeCache.Register(*m_currentState->constantTypeCache.BuildType(type)); } void SpirvWriter::MergeSections(std::vector& output, const SpirvSection& from) From 854bb16320bdab838119ffa24004f9eb357ab90f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Mon, 12 Apr 2021 15:39:41 +0200 Subject: [PATCH 095/278] VulkanRenderer: Fix OpEntryPoint parsing --- src/Nazara/VulkanRenderer/VulkanShaderModule.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Nazara/VulkanRenderer/VulkanShaderModule.cpp b/src/Nazara/VulkanRenderer/VulkanShaderModule.cpp index dda59dee1..a6e585123 100644 --- a/src/Nazara/VulkanRenderer/VulkanShaderModule.cpp +++ b/src/Nazara/VulkanRenderer/VulkanShaderModule.cpp @@ -38,6 +38,7 @@ namespace Nz case SpirvOp::OpEntryPoint: { SpirvExecutionModel executionModel = static_cast(ReadWord()); + ReadWord(); // func id std::string name = ReadString(); entryPoints.push_back({ From 3499c1f92f149d5fc39aa767a0cbf9b204abf397 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Mon, 12 Apr 2021 18:52:48 +0200 Subject: [PATCH 096/278] Shader: Remove the need of layout(std140) in external block --- examples/RenderTest/main.cpp | 2 +- include/Nazara/Shader/Ast/ExpressionType.hpp | 1 + include/Nazara/Shader/Ast/ExpressionType.inl | 5 + include/Nazara/Shader/GlslWriter.hpp | 14 +- .../OpenGLRenderer/OpenGLShaderModule.cpp | 5 +- src/Nazara/Shader/GlslWriter.cpp | 224 ++++++++++-------- src/Nazara/Shader/ShaderAstValidator.cpp | 16 -- src/Nazara/Shader/SpirvWriter.cpp | 2 +- 8 files changed, 144 insertions(+), 125 deletions(-) diff --git a/examples/RenderTest/main.cpp b/examples/RenderTest/main.cpp index d74fb15b5..23a2c8cf9 100644 --- a/examples/RenderTest/main.cpp +++ b/examples/RenderTest/main.cpp @@ -19,7 +19,7 @@ struct Data external { - [[binding(0), layout(std140)]] viewerData: uniform, + [[binding(0)]] viewerData: uniform, [[binding(1)]] tex: sampler2D } diff --git a/include/Nazara/Shader/Ast/ExpressionType.hpp b/include/Nazara/Shader/Ast/ExpressionType.hpp index a54b03395..559602038 100644 --- a/include/Nazara/Shader/Ast/ExpressionType.hpp +++ b/include/Nazara/Shader/Ast/ExpressionType.hpp @@ -95,6 +95,7 @@ namespace Nz::ShaderAst inline bool IsNoType(const ExpressionType& type); inline bool IsPrimitiveType(const ExpressionType& type); inline bool IsSamplerType(const ExpressionType& type); + inline bool IsStructType(const ExpressionType& type); inline bool IsUniformType(const ExpressionType& type); inline bool IsVectorType(const ExpressionType& type); } diff --git a/include/Nazara/Shader/Ast/ExpressionType.inl b/include/Nazara/Shader/Ast/ExpressionType.inl index 2fdb36674..ec9580616 100644 --- a/include/Nazara/Shader/Ast/ExpressionType.inl +++ b/include/Nazara/Shader/Ast/ExpressionType.inl @@ -109,6 +109,11 @@ namespace Nz::ShaderAst return std::holds_alternative(type); } + bool IsStructType(const ExpressionType& type) + { + return std::holds_alternative(type); + } + bool IsUniformType(const ExpressionType& type) { return std::holds_alternative(type); diff --git a/include/Nazara/Shader/GlslWriter.hpp b/include/Nazara/Shader/GlslWriter.hpp index 7b4741cd4..c8f270b1d 100644 --- a/include/Nazara/Shader/GlslWriter.hpp +++ b/include/Nazara/Shader/GlslWriter.hpp @@ -9,7 +9,8 @@ #include #include -#include +#include +#include #include #include #include @@ -17,7 +18,7 @@ namespace Nz { - class NAZARA_SHADER_API GlslWriter : public ShaderWriter, public ShaderAst::AstScopedVisitor + class NAZARA_SHADER_API GlslWriter : public ShaderWriter, public ShaderAst::ExpressionVisitorExcept, public ShaderAst::StatementVisitorExcept { public: struct Environment; @@ -59,24 +60,27 @@ namespace Nz template void Append(const T1& firstParam, const T2& secondParam, Args&&... params); void AppendCommentSection(const std::string& section); void AppendEntryPoint(ShaderStageType shaderStage, ShaderAst::StatementPtr& shader); - void AppendField(const std::string& structName, const std::string* memberIdentifier, std::size_t remainingMembers); + void AppendField(std::size_t structIndex, const std::size_t* memberIndices, std::size_t remainingMembers); void AppendLine(const std::string& txt = {}); template void AppendLine(Args&&... params); void EnterScope(); void LeaveScope(bool skipLine = true); + void RegisterStruct(std::size_t structIndex, bool isStd140, ShaderAst::StructDescription desc); + void RegisterVariable(std::size_t varIndex, std::string varName); + void Visit(ShaderAst::ExpressionPtr& expr, bool encloseIfRequired = false); - void Visit(ShaderAst::AccessMemberIdentifierExpression& node) override; + void Visit(ShaderAst::AccessMemberIndexExpression& node) override; void Visit(ShaderAst::AssignExpression& node) override; void Visit(ShaderAst::BinaryExpression& node) override; void Visit(ShaderAst::CastExpression& node) override; void Visit(ShaderAst::ConditionalExpression& node) override; void Visit(ShaderAst::ConstantExpression& node) override; - void Visit(ShaderAst::IdentifierExpression& node) override; void Visit(ShaderAst::IntrinsicExpression& node) override; void Visit(ShaderAst::SwizzleExpression& node) override; + void Visit(ShaderAst::VariableExpression& node) override; void Visit(ShaderAst::BranchStatement& node) override; void Visit(ShaderAst::ConditionalStatement& node) override; diff --git a/src/Nazara/OpenGLRenderer/OpenGLShaderModule.cpp b/src/Nazara/OpenGLRenderer/OpenGLShaderModule.cpp index 8fe618231..86b043877 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLShaderModule.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLShaderModule.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -122,7 +123,9 @@ namespace Nz if (!shader.Create(device, ToOpenGL(shaderStage))) throw std::runtime_error("failed to create shader"); //< TODO: Handle error message - std::string code = writer.Generate(shaderStage, shaderAst, states); + ShaderAst::AstCloner cloner; //< FIXME: Required because writer may update AST + ShaderAst::StatementPtr clonedAst = cloner.Clone(shaderAst); + std::string code = writer.Generate(shaderStage, clonedAst, states); shader.SetSource(code.data(), code.size()); shader.Compile(); diff --git a/src/Nazara/Shader/GlslWriter.cpp b/src/Nazara/Shader/GlslWriter.cpp index 46c63e5f7..d3ddb8827 100644 --- a/src/Nazara/Shader/GlslWriter.cpp +++ b/src/Nazara/Shader/GlslWriter.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -70,40 +71,6 @@ namespace Nz ShaderAst::DeclareFunctionStatement* entryPoint = nullptr; }; - struct EntryFuncResolver : ShaderAst::AstScopedVisitor - { - void Visit(ShaderAst::DeclareFunctionStatement& node) override - { - - - if (&node != entryPoint) - return; - - assert(node.parameters.size() == 1); - - const ShaderAst::ExpressionType& inputType = node.parameters.front().type; - const ShaderAst::ExpressionType& outputType = node.returnType; - - const Identifier* identifier; - - assert(IsIdentifierType(node.parameters.front().type)); - identifier = FindIdentifier(std::get(inputType).name); - assert(identifier); - - inputIdentifier = *identifier; - - assert(IsIdentifierType(outputType)); - identifier = FindIdentifier(std::get(outputType).name); - assert(identifier); - - outputIdentifier = *identifier; - } - - Identifier inputIdentifier; - Identifier outputIdentifier; - ShaderAst::DeclareFunctionStatement* entryPoint; - }; - struct Builtin { std::string identifier; @@ -118,9 +85,17 @@ namespace Nz struct GlslWriter::State { + struct StructInfo + { + ShaderAst::StructDescription structDesc; + bool isStd140 = false; + }; + const States* states = nullptr; ShaderAst::DeclareFunctionStatement* entryFunc = nullptr; std::stringstream stream; + std::unordered_map structs; + std::unordered_map variableNames; unsigned int indentLevel = 0; }; @@ -143,10 +118,13 @@ namespace Nz if (!ShaderAst::ValidateAst(shader, &error)) throw std::runtime_error("Invalid shader AST: " + error); + ShaderAst::TransformVisitor transformVisitor; + ShaderAst::StatementPtr transformedShader = transformVisitor.Transform(shader); + PreVisitor previsitor; previsitor.selectedEntryPoint = shaderStage; - ShaderAst::StatementPtr adaptedShader = previsitor.Clone(shader); + ShaderAst::StatementPtr adaptedShader = previsitor.Clone(transformedShader); if (!previsitor.entryPoint) throw std::runtime_error("missing entry point"); @@ -233,14 +211,10 @@ namespace Nz AppendLine(); } - PushScope(); - { - adaptedShader->Visit(*this); + adaptedShader->Visit(*this); - // Append true GLSL entry point - AppendEntryPoint(shaderStage, adaptedShader); - } - PopScope(); + // Append true GLSL entry point + AppendEntryPoint(shaderStage, adaptedShader); return state.stream.str(); } @@ -275,7 +249,7 @@ namespace Nz void GlslWriter::Append(const ShaderAst::IdentifierType& identifierType) { - Append(identifierType.name); + throw std::runtime_error("unexpected identifier type"); } void GlslWriter::Append(const ShaderAst::MatrixType& matrixType) @@ -332,7 +306,8 @@ namespace Nz void GlslWriter::Append(const ShaderAst::StructType& structType) { - throw std::runtime_error("unexpected struct type"); + const auto& structDesc = m_currentState->structs[structType.structIndex].structDesc; + Append(structDesc.name); } void GlslWriter::Append(const ShaderAst::UniformType& uniformType) @@ -395,9 +370,24 @@ namespace Nz void GlslWriter::AppendEntryPoint(ShaderStageType shaderStage, ShaderAst::StatementPtr& shader) { - EntryFuncResolver entryResolver; - entryResolver.entryPoint = m_currentState->entryFunc; - entryResolver.ScopedVisit(shader); + ShaderAst::DeclareFunctionStatement& entryFunc = *m_currentState->entryFunc; + + std::optional inputStructIndex; + if (!entryFunc.parameters.empty()) + { + assert(entryFunc.parameters.size() == 1); + auto& parameter = entryFunc.parameters.front(); + assert(std::holds_alternative(parameter.type)); + + inputStructIndex = std::get(parameter.type).structIndex; + } + + std::optional outputStructIndex; + if (!IsNoType(entryFunc.returnType)) + { + assert(std::holds_alternative(entryFunc.returnType)); + outputStructIndex = std::get(entryFunc.returnType).structIndex; + } AppendLine(); AppendLine("// Entry point handling"); @@ -411,12 +401,11 @@ namespace Nz std::vector inputFields; const ShaderAst::StructDescription* inputStruct = nullptr; - auto HandleInOutStructs = [this, shaderStage](const Identifier& identifier, std::vector& fields, const char* keyword, const char* fromPrefix, const char* targetPrefix) -> const ShaderAst::StructDescription* + auto HandleInOutStructs = [this, shaderStage](std::size_t structIndex, std::vector& fields, const char* keyword, const char* fromPrefix, const char* targetPrefix) -> const ShaderAst::StructDescription* { - assert(std::holds_alternative(identifier.value)); - const auto& s = std::get(identifier.value); + const auto& structDesc = m_currentState->structs[structIndex].structDesc; - for (const auto& member : s.members) + for (const auto& member : structDesc.members) { bool skip = false; std::optional builtinName; @@ -474,16 +463,16 @@ namespace Nz } AppendLine(); - return &s; + return &structDesc; }; - if (!m_currentState->entryFunc->parameters.empty()) - inputStruct = HandleInOutStructs(entryResolver.inputIdentifier, inputFields, "in", "_nzInput.", "_NzIn_"); + if (inputStructIndex) + inputStruct = HandleInOutStructs(*inputStructIndex, inputFields, "in", "_nzInput.", "_NzIn_"); std::vector outputFields; const ShaderAst::StructDescription* outputStruct = nullptr; - if (!IsNoType(m_currentState->entryFunc->returnType)) - outputStruct = HandleInOutStructs(entryResolver.outputIdentifier, outputFields, "out", "_nzOutput.", "_NzOut_"); + if (outputStructIndex) + outputStruct = HandleInOutStructs(*outputStructIndex, outputFields, "out", "_nzOutput.", "_NzOut_"); if (shaderStage == ShaderStageType::Vertex && m_environment.flipYPosition) AppendLine("uniform float ", flipYUniformName, ";"); @@ -533,24 +522,20 @@ namespace Nz LeaveScope(); } - void GlslWriter::AppendField(const std::string& structName, const std::string* memberIdentifier, std::size_t remainingMembers) + void GlslWriter::AppendField(std::size_t structIndex, const std::size_t* memberIndices, std::size_t remainingMembers) { + const auto& structDesc = m_currentState->structs[structIndex].structDesc; + + const auto& member = structDesc.members[*memberIndices]; + Append("."); - Append(memberIdentifier[0]); - - const Identifier* identifier = FindIdentifier(structName); - assert(identifier); - - assert(std::holds_alternative(identifier->value)); - const auto& s = std::get(identifier->value); - - auto memberIt = std::find_if(s.members.begin(), s.members.begin(), [&](const auto& field) { return field.name == memberIdentifier[0]; }); - assert(memberIt != s.members.end()); - - const auto& member = *memberIt; + Append(member.name); if (remainingMembers > 1) - AppendField(std::get(member.type).name, memberIdentifier + 1, remainingMembers - 1); + { + assert(IsStructType(member.type)); + AppendField(std::get(member.type).structIndex, memberIndices + 1, remainingMembers - 1); + } } void GlslWriter::AppendLine(const std::string& txt) @@ -588,6 +573,21 @@ namespace Nz Append("}"); } + void GlslWriter::RegisterStruct(std::size_t structIndex, bool isStd140, ShaderAst::StructDescription desc) + { + assert(m_currentState->structs.find(structIndex) == m_currentState->structs.end()); + m_currentState->structs.emplace(structIndex, State::StructInfo{ + std::move(desc), + isStd140 + }); + } + + void GlslWriter::RegisterVariable(std::size_t varIndex, std::string varName) + { + assert(m_currentState->variableNames.find(varIndex) == m_currentState->variableNames.end()); + m_currentState->variableNames.emplace(varIndex, std::move(varName)); + } + void GlslWriter::Visit(ShaderAst::ExpressionPtr& expr, bool encloseIfRequired) { bool enclose = encloseIfRequired && (GetExpressionCategory(*expr) != ShaderAst::ExpressionCategory::LValue); @@ -601,14 +601,14 @@ namespace Nz Append(")"); } - void GlslWriter::Visit(ShaderAst::AccessMemberIdentifierExpression& node) + void GlslWriter::Visit(ShaderAst::AccessMemberIndexExpression& node) { Visit(node.structExpr, true); - const ShaderAst::ExpressionType& exprType = node.structExpr->cachedExpressionType.value(); - assert(IsIdentifierType(exprType)); + const ShaderAst::ExpressionType& exprType = GetExpressionType(*node.structExpr); + assert(IsStructType(exprType)); - AppendField(std::get(exprType).name, node.memberIdentifiers.data(), node.memberIdentifiers.size()); + AppendField(std::get(exprType).structIndex, node.memberIndices.data(), node.memberIndices.size()); } void GlslWriter::Visit(ShaderAst::AssignExpression& node) @@ -638,9 +638,7 @@ namespace Nz AppendLine(")"); EnterScope(); - PushScope(); statement.statement->Visit(*this); - PopScope(); LeaveScope(); first = false; @@ -651,9 +649,7 @@ namespace Nz AppendLine("else"); EnterScope(); - PushScope(); node.elseStatement->Visit(*this); - PopScope(); LeaveScope(); } } @@ -747,21 +743,32 @@ namespace Nz void GlslWriter::Visit(ShaderAst::DeclareExternalStatement& node) { + assert(node.varIndex); + std::size_t varIndex = *node.varIndex; + for (const auto& externalVar : node.externalVars) { std::optional bindingIndex; - bool isStd140 = false; for (const auto& [attributeType, attributeParam] : externalVar.attributes) { if (attributeType == ShaderAst::AttributeType::Binding) - bindingIndex = std::get(attributeParam); - else if (attributeType == ShaderAst::AttributeType::Layout) { - if (std::get(attributeParam) == "std140") - isStd140 = true; + bindingIndex = std::get(attributeParam); + break; } } + bool isStd140 = false; + if (IsUniformType(externalVar.type)) + { + auto& uniform = std::get(externalVar.type); + assert(std::holds_alternative(uniform.containedType)); + + std::size_t structIndex = std::get(uniform.containedType).structIndex; + auto& structInfo = m_currentState->structs[structIndex]; + isStd140 = structInfo.isStd140; + } + if (bindingIndex) { Append("layout(binding = "); @@ -773,19 +780,20 @@ namespace Nz if (IsUniformType(externalVar.type)) { + Append("_NzBinding_"); AppendLine(externalVar.name); EnterScope(); { - const Identifier* identifier = FindIdentifier(std::get(std::get(externalVar.type).containedType).name); - assert(identifier); + auto& uniform = std::get(externalVar.type); + assert(std::holds_alternative(uniform.containedType)); - assert(std::holds_alternative(identifier->value)); - const auto& s = std::get(identifier->value); + std::size_t structIndex = std::get(uniform.containedType).structIndex; + auto& structInfo = m_currentState->structs[structIndex]; bool first = true; - for (const auto& [name, attribute, type] : s.members) + for (const auto& [name, attribute, type] : structInfo.structDesc.members) { if (!first) AppendLine(); @@ -807,6 +815,8 @@ namespace Nz Append(externalVar.name); AppendLine(";"); } + + RegisterVariable(varIndex++, externalVar.name); } } @@ -814,6 +824,9 @@ namespace Nz { NazaraAssert(m_currentState, "This function should only be called while processing an AST"); + assert(node.varIndex); + std::size_t varIndex = *node.varIndex; + Append(node.returnType); Append(" "); Append(node.name); @@ -825,22 +838,33 @@ namespace Nz Append(node.parameters[i].type); Append(" "); Append(node.parameters[i].name); + + RegisterVariable(varIndex++, node.parameters[i].name); } Append(")\n"); EnterScope(); - PushScope(); { for (auto& statement : node.statements) statement->Visit(*this); } - PopScope(); LeaveScope(); } void GlslWriter::Visit(ShaderAst::DeclareStructStatement& node) { - RegisterStruct(node.description); + bool isStd140 = false; + for (const auto& [attributeType, attributeParam] : node.attributes) + { + if (attributeType == ShaderAst::AttributeType::Layout && std::get(attributeParam) == "std140") + { + isStd140 = true; + break; + } + } + + assert(node.structIndex); + RegisterStruct(*node.structIndex, isStd140, node.description); Append("struct "); AppendLine(node.description.name); @@ -866,7 +890,8 @@ namespace Nz void GlslWriter::Visit(ShaderAst::DeclareVariableStatement& node) { - RegisterVariable(node.varName, node.varType); + assert(node.varIndex); + RegisterVariable(*node.varIndex, node.varName); Append(node.varType); Append(" "); @@ -891,11 +916,6 @@ namespace Nz AppendLine(";"); } - void GlslWriter::Visit(ShaderAst::IdentifierExpression& node) - { - Append(node.identifier); - } - void GlslWriter::Visit(ShaderAst::IntrinsicExpression& node) { switch (node.intrinsic) @@ -926,8 +946,6 @@ namespace Nz void GlslWriter::Visit(ShaderAst::MultiStatement& node) { - PushScope(); - bool first = true; for (const ShaderAst::StatementPtr& statement : node.statements) { @@ -938,8 +956,6 @@ namespace Nz first = false; } - - PopScope(); } void GlslWriter::Visit(ShaderAst::NoOpStatement& /*node*/) @@ -987,6 +1003,12 @@ namespace Nz } } + void GlslWriter::Visit(ShaderAst::VariableExpression& node) + { + const std::string& varName = m_currentState->variableNames[node.variableId]; + Append(varName); + } + bool GlslWriter::HasExplicitBinding(ShaderAst::StatementPtr& shader) { /*for (const auto& uniform : shader.GetUniforms()) diff --git a/src/Nazara/Shader/ShaderAstValidator.cpp b/src/Nazara/Shader/ShaderAstValidator.cpp index 8f998341e..98ecb65d8 100644 --- a/src/Nazara/Shader/ShaderAstValidator.cpp +++ b/src/Nazara/Shader/ShaderAstValidator.cpp @@ -567,7 +567,6 @@ namespace Nz::ShaderAst for (const auto& extVar : node.externalVars) { bool hasBinding = false; - bool hasLayout = false; for (const auto& [attributeType, arg] : extVar.attributes) { switch (attributeType) @@ -588,21 +587,6 @@ namespace Nz::ShaderAst break; } - case AttributeType::Layout: - { - if (hasLayout) - throw AstError{ "attribute layout must be present once" }; - - if (!std::holds_alternative(arg)) - throw AstError{ "attribute layout requires a string parameter" }; - - if (std::get(arg) != "std140") - throw AstError{ "unknown layout type" }; - - hasLayout = true; - break; - } - default: throw AstError{ "unhandled attribute for external variable" }; } diff --git a/src/Nazara/Shader/SpirvWriter.cpp b/src/Nazara/Shader/SpirvWriter.cpp index 8ef74aef7..82a1d360c 100644 --- a/src/Nazara/Shader/SpirvWriter.cpp +++ b/src/Nazara/Shader/SpirvWriter.cpp @@ -238,7 +238,7 @@ namespace Nz Int32(memberIndex), m_constantCache.Register(*m_constantCache.BuildType(member.type)), varId - }); + }); } memberIndex++; From bca1561f73f4fc8b58d4319077658b23628f6e1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Tue, 13 Apr 2021 17:20:31 +0200 Subject: [PATCH 097/278] Shader/GlslWriter: Improve GLSL output --- include/Nazara/Shader/GlslWriter.hpp | 4 + src/Nazara/Shader/GlslWriter.cpp | 579 +++++++++++++++------------ 2 files changed, 318 insertions(+), 265 deletions(-) diff --git a/include/Nazara/Shader/GlslWriter.hpp b/include/Nazara/Shader/GlslWriter.hpp index c8f270b1d..83acdc4cf 100644 --- a/include/Nazara/Shader/GlslWriter.hpp +++ b/include/Nazara/Shader/GlslWriter.hpp @@ -61,12 +61,16 @@ namespace Nz void AppendCommentSection(const std::string& section); void AppendEntryPoint(ShaderStageType shaderStage, ShaderAst::StatementPtr& shader); void AppendField(std::size_t structIndex, const std::size_t* memberIndices, std::size_t remainingMembers); + void AppendHeader(); void AppendLine(const std::string& txt = {}); template void AppendLine(Args&&... params); void EnterScope(); void LeaveScope(bool skipLine = true); + void HandleEntryPoint(ShaderAst::DeclareFunctionStatement& node); + void HandleInOut(); + void RegisterStruct(std::size_t structIndex, bool isStd140, ShaderAst::StructDescription desc); void RegisterVariable(std::size_t varIndex, std::string varName); diff --git a/src/Nazara/Shader/GlslWriter.cpp b/src/Nazara/Shader/GlslWriter.cpp index d3ddb8827..6fcf520ed 100644 --- a/src/Nazara/Shader/GlslWriter.cpp +++ b/src/Nazara/Shader/GlslWriter.cpp @@ -19,8 +19,10 @@ namespace Nz { namespace { - static const char* flipYUniformName = "_NzFlipValue"; - static const char* overridenMain = "_NzMain"; + static const char* s_flipYUniformName = "_NzFlipYValue"; + static const char* s_inputPrefix = "_NzIn_"; + static const char* s_outputPrefix = "_NzOut_"; + static const char* s_outputVarName = "_nzOutput"; //FIXME: Have this only once std::unordered_map s_entryPoints = { @@ -28,6 +30,13 @@ namespace Nz { "vert", ShaderStageType::Vertex }, }; + template const T& Retrieve(const std::unordered_map& map, std::size_t id) + { + auto it = map.find(id); + assert(it != map.end()); + return it->second; + } + struct PreVisitor : ShaderAst::AstCloner { using AstCloner::Clone; @@ -39,8 +48,8 @@ namespace Nz ShaderAst::DeclareFunctionStatement* func = static_cast(clone.get()); - bool hasEntryPoint = false; - + // Remove function if it's an entry point of another type than the one selected + bool isEntryPoint = false; for (auto& attribute : func->attributes) { if (attribute.type == ShaderAst::AttributeType::Entry) @@ -48,21 +57,16 @@ namespace Nz auto it = s_entryPoints.find(std::get(attribute.args)); assert(it != s_entryPoints.end()); - if (it->second == selectedEntryPoint) - { - hasEntryPoint = true; - break; - } + if (it->second != selectedEntryPoint) + return ShaderBuilder::NoOp(); + + isEntryPoint = true; + break; } } - if (!hasEntryPoint) - return ShaderBuilder::NoOp(); - - entryPoint = func; - - if (func->name == "main") - func->name = "_NzMain"; + if (isEntryPoint) + entryPoint = func; return clone; } @@ -85,17 +89,27 @@ namespace Nz struct GlslWriter::State { + struct InOutField + { + std::string memberName; + std::string targetName; + }; + struct StructInfo { ShaderAst::StructDescription structDesc; bool isStd140 = false; }; + ShaderStageType stage; const States* states = nullptr; ShaderAst::DeclareFunctionStatement* entryFunc = nullptr; std::stringstream stream; std::unordered_map structs; std::unordered_map variableNames; + std::vector inputFields; + std::vector outputFields; + bool isInEntryPoint = false; unsigned int indentLevel = 0; }; @@ -108,6 +122,8 @@ namespace Nz std::string GlslWriter::Generate(ShaderStageType shaderStage, ShaderAst::StatementPtr& shader, const States& conditions) { State state; + state.stage = shaderStage; + m_currentState = &state; CallOnExit onExit([this]() { @@ -131,91 +147,10 @@ namespace Nz state.entryFunc = previsitor.entryPoint; - unsigned int glslVersion; - if (m_environment.glES) - { - if (m_environment.glMajorVersion >= 3 && m_environment.glMinorVersion >= 2) - glslVersion = 320; - else if (m_environment.glMajorVersion >= 3 && m_environment.glMinorVersion >= 1) - glslVersion = 310; - else if (m_environment.glMajorVersion >= 3) - glslVersion = 300; - else if (m_environment.glMajorVersion >= 2) - glslVersion = 100; - else - throw std::runtime_error("This version of OpenGL ES does not support shaders"); - } - else - { - if (m_environment.glMajorVersion >= 3 && m_environment.glMinorVersion >= 3) - glslVersion = m_environment.glMajorVersion * 100 + m_environment.glMinorVersion * 10; - else if (m_environment.glMajorVersion >= 3 && m_environment.glMinorVersion >= 2) - glslVersion = 150; - else if (m_environment.glMajorVersion >= 3 && m_environment.glMinorVersion >= 1) - glslVersion = 140; - else if (m_environment.glMajorVersion >= 3) - glslVersion = 130; - else if (m_environment.glMajorVersion >= 2 && m_environment.glMinorVersion >= 1) - glslVersion = 120; - else if (m_environment.glMajorVersion >= 2) - glslVersion = 110; - else - throw std::runtime_error("This version of OpenGL does not support shaders"); - } - - // Header - Append("#version "); - Append(glslVersion); - if (m_environment.glES) - Append(" es"); - - AppendLine(); - AppendLine(); - - // Extensions - - std::vector requiredExtensions; - - if (!m_environment.glES && m_environment.extCallback) - { - // GL_ARB_shading_language_420pack (required for layout(binding = X)) - if (glslVersion < 420 && HasExplicitBinding(adaptedShader)) - { - if (m_environment.extCallback("GL_ARB_shading_language_420pack")) - requiredExtensions.emplace_back("GL_ARB_shading_language_420pack"); - } - - // GL_ARB_separate_shader_objects (required for layout(location = X)) - if (glslVersion < 410 && HasExplicitLocation(adaptedShader)) - { - if (m_environment.extCallback("GL_ARB_separate_shader_objects")) - requiredExtensions.emplace_back("GL_ARB_separate_shader_objects"); - } - } - - if (!requiredExtensions.empty()) - { - for (const std::string& ext : requiredExtensions) - AppendLine("#extension " + ext + " : require"); - - AppendLine(); - } - - if (m_environment.glES) - { - AppendLine("#if GL_FRAGMENT_PRECISION_HIGH"); - AppendLine("precision highp float;"); - AppendLine("#else"); - AppendLine("precision mediump float;"); - AppendLine("#endif"); - AppendLine(); - } + AppendHeader(); adaptedShader->Visit(*this); - // Append true GLSL entry point - AppendEntryPoint(shaderStage, adaptedShader); - return state.stream.str(); } @@ -226,7 +161,7 @@ namespace Nz const char* GlslWriter::GetFlipYUniformName() { - return flipYUniformName; + return s_flipYUniformName; } void GlslWriter::Append(const ShaderAst::ExpressionType& type) @@ -306,7 +241,7 @@ namespace Nz void GlslWriter::Append(const ShaderAst::StructType& structType) { - const auto& structDesc = m_currentState->structs[structType.structIndex].structDesc; + const auto& structDesc = Retrieve(m_currentState->structs, structType.structIndex).structDesc; Append(structDesc.name); } @@ -368,163 +303,9 @@ namespace Nz AppendLine(); } - void GlslWriter::AppendEntryPoint(ShaderStageType shaderStage, ShaderAst::StatementPtr& shader) - { - ShaderAst::DeclareFunctionStatement& entryFunc = *m_currentState->entryFunc; - - std::optional inputStructIndex; - if (!entryFunc.parameters.empty()) - { - assert(entryFunc.parameters.size() == 1); - auto& parameter = entryFunc.parameters.front(); - assert(std::holds_alternative(parameter.type)); - - inputStructIndex = std::get(parameter.type).structIndex; - } - - std::optional outputStructIndex; - if (!IsNoType(entryFunc.returnType)) - { - assert(std::holds_alternative(entryFunc.returnType)); - outputStructIndex = std::get(entryFunc.returnType).structIndex; - } - - AppendLine(); - AppendLine("// Entry point handling"); - - struct InOutField - { - std::string name; - std::string targetName; - }; - - std::vector inputFields; - const ShaderAst::StructDescription* inputStruct = nullptr; - - auto HandleInOutStructs = [this, shaderStage](std::size_t structIndex, std::vector& fields, const char* keyword, const char* fromPrefix, const char* targetPrefix) -> const ShaderAst::StructDescription* - { - const auto& structDesc = m_currentState->structs[structIndex].structDesc; - - for (const auto& member : structDesc.members) - { - bool skip = false; - std::optional builtinName; - std::optional attributeLocation; - for (const auto& [attributeType, attributeParam] : member.attributes) - { - if (attributeType == ShaderAst::AttributeType::Builtin) - { - auto it = builtinMapping.find(std::get(attributeParam)); - if (it != builtinMapping.end()) - { - const Builtin& builtin = it->second; - if (!builtin.stageFlags.Test(shaderStage)) - { - skip = true; - break; - } - - builtinName = builtin.identifier; - break; - } - } - else if (attributeType == ShaderAst::AttributeType::Location) - { - attributeLocation = std::get(attributeParam); - break; - } - } - - if (!skip && attributeLocation) - { - Append("layout(location = "); - Append(*attributeLocation); - Append(") "); - Append(keyword); - Append(" "); - Append(member.type); - Append(" "); - Append(targetPrefix); - Append(member.name); - AppendLine(";"); - - fields.push_back({ - fromPrefix + member.name, - targetPrefix + member.name - }); - } - else if (builtinName) - { - fields.push_back({ - fromPrefix + member.name, - *builtinName - }); - } - } - AppendLine(); - - return &structDesc; - }; - - if (inputStructIndex) - inputStruct = HandleInOutStructs(*inputStructIndex, inputFields, "in", "_nzInput.", "_NzIn_"); - - std::vector outputFields; - const ShaderAst::StructDescription* outputStruct = nullptr; - if (outputStructIndex) - outputStruct = HandleInOutStructs(*outputStructIndex, outputFields, "out", "_nzOutput.", "_NzOut_"); - - if (shaderStage == ShaderStageType::Vertex && m_environment.flipYPosition) - AppendLine("uniform float ", flipYUniformName, ";"); - - AppendLine("void main()"); - EnterScope(); - { - if (inputStruct) - { - Append(inputStruct->name); - AppendLine(" _nzInput;"); - for (const auto& [name, targetName] : inputFields) - { - AppendLine(name, " = ", targetName, ";"); - } - AppendLine(); - } - - if (outputStruct) - Append(outputStruct->name, " _nzOutput = "); - - Append(m_currentState->entryFunc->name); - - Append("("); - if (m_currentState->entryFunc) - Append("_nzInput"); - Append(");"); - - if (outputStruct) - { - AppendLine(); - - for (const auto& [name, targetName] : outputFields) - { - bool isOutputPosition = (shaderStage == ShaderStageType::Vertex && m_environment.flipYPosition && targetName == "gl_Position"); - - AppendLine(); - - Append(targetName, " = ", name); - if (isOutputPosition) - Append(" * vec4(1.0, ", flipYUniformName, ", 1.0, 1.0)"); - - Append(";"); - } - } - } - LeaveScope(); - } - void GlslWriter::AppendField(std::size_t structIndex, const std::size_t* memberIndices, std::size_t remainingMembers) { - const auto& structDesc = m_currentState->structs[structIndex].structDesc; + const auto& structDesc = Retrieve(m_currentState->structs, structIndex).structDesc; const auto& member = structDesc.members[*memberIndices]; @@ -573,6 +354,144 @@ namespace Nz Append("}"); } + void GlslWriter::HandleEntryPoint(ShaderAst::DeclareFunctionStatement& node) + { + HandleInOut(); + AppendLine("void main()"); + EnterScope(); + { + if (!m_currentState->inputFields.empty()) + { + assert(node.varIndex); + assert(!node.parameters.empty()); + + auto& parameter = node.parameters.front(); + const std::string& varName = parameter.name; + RegisterVariable(*node.varIndex, varName); + + assert(IsStructType(parameter.type)); + std::size_t structIndex = std::get(parameter.type).structIndex; + const ShaderAst::StructDescription& structDesc = Retrieve(m_currentState->structs, structIndex).structDesc; + + AppendLine(structDesc.name, " ", varName, ";"); + for (const auto& [memberName, targetName] : m_currentState->inputFields) + AppendLine(varName, ".", memberName, " = ", targetName, ";"); + + AppendLine(); + } + + // Output struct is handled on return node + m_currentState->isInEntryPoint = true; + + for (auto& statement : node.statements) + statement->Visit(*this); + + m_currentState->isInEntryPoint = false; + } + LeaveScope(); + } + + void GlslWriter::HandleInOut() + { + auto AppendInOut = [this](const ShaderAst::StructDescription& structDesc, std::vector& fields, const char* keyword, const char* targetPrefix) + { + for (const auto& member : structDesc.members) + { + bool skip = false; + std::optional builtinName; + std::optional attributeLocation; + for (const auto& [attributeType, attributeParam] : member.attributes) + { + if (attributeType == ShaderAst::AttributeType::Builtin) + { + auto it = builtinMapping.find(std::get(attributeParam)); + if (it != builtinMapping.end()) + { + const Builtin& builtin = it->second; + if (!builtin.stageFlags.Test(m_currentState->stage)) + { + skip = true; + break; + } + + builtinName = builtin.identifier; + break; + } + } + else if (attributeType == ShaderAst::AttributeType::Location) + { + attributeLocation = std::get(attributeParam); + break; + } + } + + if (skip) + continue; + + if (attributeLocation) + { + Append("layout(location = "); + Append(*attributeLocation); + Append(") "); + Append(keyword); + Append(" "); + Append(member.type); + Append(" "); + Append(targetPrefix); + Append(member.name); + AppendLine(";"); + + fields.push_back({ + member.name, + targetPrefix + member.name + }); + } + else if (builtinName) + { + fields.push_back({ + member.name, + *builtinName + }); + } + } + AppendLine(); + }; + + const ShaderAst::DeclareFunctionStatement& node = *m_currentState->entryFunc; + + const ShaderAst::StructDescription* inputStruct = nullptr; + + if (!node.parameters.empty()) + { + assert(node.parameters.size() == 1); + auto& parameter = node.parameters.front(); + assert(std::holds_alternative(parameter.type)); + + std::size_t inputStructIndex = std::get(parameter.type).structIndex; + inputStruct = &Retrieve(m_currentState->structs, inputStructIndex).structDesc; + + AppendCommentSection("Inputs"); + AppendInOut(*inputStruct, m_currentState->inputFields, "in", s_inputPrefix); + } + + if (m_currentState->stage == ShaderStageType::Vertex && m_environment.flipYPosition) + { + AppendLine("uniform float ", s_flipYUniformName, ";"); + AppendLine(); + } + + if (!IsNoType(node.returnType)) + { + assert(std::holds_alternative(node.returnType)); + std::size_t outputStructIndex = std::get(node.returnType).structIndex; + + const ShaderAst::StructDescription& outputStruct = Retrieve(m_currentState->structs, outputStructIndex).structDesc; + + AppendCommentSection("Outputs"); + AppendInOut(outputStruct, m_currentState->outputFields, "out", s_outputPrefix); + } + } + void GlslWriter::RegisterStruct(std::size_t structIndex, bool isStd140, ShaderAst::StructDescription desc) { assert(m_currentState->structs.find(structIndex) == m_currentState->structs.end()); @@ -765,7 +684,7 @@ namespace Nz assert(std::holds_alternative(uniform.containedType)); std::size_t structIndex = std::get(uniform.containedType).structIndex; - auto& structInfo = m_currentState->structs[structIndex]; + auto& structInfo = Retrieve(m_currentState->structs, structIndex); isStd140 = structInfo.isStd140; } @@ -780,7 +699,6 @@ namespace Nz if (IsUniformType(externalVar.type)) { - Append("_NzBinding_"); AppendLine(externalVar.name); @@ -790,7 +708,7 @@ namespace Nz assert(std::holds_alternative(uniform.containedType)); std::size_t structIndex = std::get(uniform.containedType).structIndex; - auto& structInfo = m_currentState->structs[structIndex]; + auto& structInfo = Retrieve(m_currentState->structs, structIndex); bool first = true; for (const auto& [name, attribute, type] : structInfo.structDesc.members) @@ -814,6 +732,9 @@ namespace Nz Append(" "); Append(externalVar.name); AppendLine(";"); + + if (IsUniformType(externalVar.type)) + AppendLine(); } RegisterVariable(varIndex++, externalVar.name); @@ -824,6 +745,9 @@ namespace Nz { NazaraAssert(m_currentState, "This function should only be called while processing an AST"); + if (m_currentState->entryFunc == &node) + return HandleEntryPoint(node); + assert(node.varIndex); std::size_t varIndex = *node.varIndex; @@ -835,6 +759,7 @@ namespace Nz { if (i != 0) Append(", "); + Append(node.parameters[i].type); Append(" "); Append(node.parameters[i].name); @@ -862,7 +787,7 @@ namespace Nz break; } } - + assert(node.structIndex); RegisterStruct(*node.structIndex, isStd140, node.description); @@ -965,14 +890,55 @@ namespace Nz void GlslWriter::Visit(ShaderAst::ReturnStatement& node) { - if (node.returnExpr) + if (m_currentState->isInEntryPoint) { - Append("return "); - node.returnExpr->Visit(*this); - Append(";"); + assert(node.returnExpr); + + const ShaderAst::ExpressionType& returnType = GetExpressionType(*node.returnExpr); + assert(IsStructType(returnType)); + std::size_t structIndex = std::get(returnType).structIndex; + const ShaderAst::StructDescription& structDesc = Retrieve(m_currentState->structs, structIndex).structDesc; + + std::string outputStructVarName; + if (node.returnExpr->GetType() == ShaderAst::NodeType::VariableExpression) + outputStructVarName = Retrieve(m_currentState->variableNames, static_cast(*node.returnExpr).variableId); + else + { + AppendLine(); + Append(structDesc.name, " ", s_outputVarName, " = "); + node.returnExpr->Visit(*this); + AppendLine(";"); + + outputStructVarName = s_outputVarName; + } + + for (const auto& [name, targetName] : m_currentState->outputFields) + { + bool isOutputPosition = (m_currentState->stage == ShaderStageType::Vertex && m_environment.flipYPosition && targetName == "gl_Position"); + + AppendLine(); + + Append(targetName, " = ", outputStructVarName, ".", name); + if (isOutputPosition) + Append(" * vec4(1.0, ", s_flipYUniformName, ", 1.0, 1.0)"); + + Append(";"); + } + + AppendLine(); + Append("return;"); //< TODO: Don't return if it's the last statement of the function } else - Append("return;"); + { + if (node.returnExpr) + { + Append("return "); + node.returnExpr->Visit(*this); + Append(";"); + } + else + Append("return;"); + } } void GlslWriter::Visit(ShaderAst::SwizzleExpression& node) @@ -1005,7 +971,7 @@ namespace Nz void GlslWriter::Visit(ShaderAst::VariableExpression& node) { - const std::string& varName = m_currentState->variableNames[node.variableId]; + const std::string& varName = Retrieve(m_currentState->variableNames, node.variableId); Append(varName); } @@ -1037,4 +1003,87 @@ namespace Nz return false; } + void GlslWriter::AppendHeader() + { + unsigned int glslVersion; + if (m_environment.glES) + { + if (m_environment.glMajorVersion >= 3 && m_environment.glMinorVersion >= 2) + glslVersion = 320; + else if (m_environment.glMajorVersion >= 3 && m_environment.glMinorVersion >= 1) + glslVersion = 310; + else if (m_environment.glMajorVersion >= 3) + glslVersion = 300; + else if (m_environment.glMajorVersion >= 2) + glslVersion = 100; + else + throw std::runtime_error("This version of OpenGL ES does not support shaders"); + } + else + { + if (m_environment.glMajorVersion >= 3 && m_environment.glMinorVersion >= 3) + glslVersion = m_environment.glMajorVersion * 100 + m_environment.glMinorVersion * 10; + else if (m_environment.glMajorVersion >= 3 && m_environment.glMinorVersion >= 2) + glslVersion = 150; + else if (m_environment.glMajorVersion >= 3 && m_environment.glMinorVersion >= 1) + glslVersion = 140; + else if (m_environment.glMajorVersion >= 3) + glslVersion = 130; + else if (m_environment.glMajorVersion >= 2 && m_environment.glMinorVersion >= 1) + glslVersion = 120; + else if (m_environment.glMajorVersion >= 2) + glslVersion = 110; + else + throw std::runtime_error("This version of OpenGL does not support shaders"); + } + + // Header + Append("#version "); + Append(glslVersion); + if (m_environment.glES) + Append(" es"); + + AppendLine(); + AppendLine(); + + // Extensions + + std::vector requiredExtensions; + + if (!m_environment.glES && m_environment.extCallback) + { + // GL_ARB_shading_language_420pack (required for layout(binding = X)) + if (glslVersion < 420) + { + if (m_environment.extCallback("GL_ARB_shading_language_420pack")) + requiredExtensions.emplace_back("GL_ARB_shading_language_420pack"); + } + + // GL_ARB_separate_shader_objects (required for layout(location = X)) + if (glslVersion < 410) + { + if (m_environment.extCallback("GL_ARB_separate_shader_objects")) + requiredExtensions.emplace_back("GL_ARB_separate_shader_objects"); + } + } + + if (!requiredExtensions.empty()) + { + for (const std::string& ext : requiredExtensions) + AppendLine("#extension " + ext + " : require"); + + AppendLine(); + } + + if (m_environment.glES) + { + AppendLine("#if GL_FRAGMENT_PRECISION_HIGH"); + AppendLine("precision highp float;"); + AppendLine("#else"); + AppendLine("precision mediump float;"); + AppendLine("#endif"); + AppendLine(); + } + } + } From aababb205f79f7d9e16965ae5b7e30cf70cb1b3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 14 Apr 2021 11:34:21 +0200 Subject: [PATCH 098/278] Shader: Move attribute parsing to parser, simplifying writer code --- include/Nazara/Shader/Ast/ExpressionType.hpp | 5 +- include/Nazara/Shader/GlslWriter.hpp | 2 +- include/Nazara/Shader/ShaderAstSerializer.hpp | 1 - include/Nazara/Shader/ShaderBuilder.hpp | 4 +- include/Nazara/Shader/ShaderBuilder.inl | 13 +- include/Nazara/Shader/ShaderEnums.hpp | 16 +- include/Nazara/Shader/ShaderLangParser.hpp | 6 + include/Nazara/Shader/ShaderNodes.hpp | 6 +- src/Nazara/Shader/GlslWriter.cpp | 155 +- src/Nazara/Shader/ShaderAstCloner.cpp | 3 +- src/Nazara/Shader/ShaderAstSerializer.cpp | 87 +- src/Nazara/Shader/ShaderAstValidator.cpp | 88 +- src/Nazara/Shader/ShaderLangParser.cpp | 1508 +++++++++-------- src/Nazara/Shader/SpirvWriter.cpp | 62 +- 14 files changed, 910 insertions(+), 1046 deletions(-) diff --git a/include/Nazara/Shader/Ast/ExpressionType.hpp b/include/Nazara/Shader/Ast/ExpressionType.hpp index 559602038..2b436c7aa 100644 --- a/include/Nazara/Shader/Ast/ExpressionType.hpp +++ b/include/Nazara/Shader/Ast/ExpressionType.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -81,11 +82,13 @@ namespace Nz::ShaderAst { struct StructMember { + std::optional builtin; + std::optional locationIndex; std::string name; - std::vector attributes; ExpressionType type; }; + std::optional layout; std::string name; std::vector members; }; diff --git a/include/Nazara/Shader/GlslWriter.hpp b/include/Nazara/Shader/GlslWriter.hpp index 83acdc4cf..9f228c51e 100644 --- a/include/Nazara/Shader/GlslWriter.hpp +++ b/include/Nazara/Shader/GlslWriter.hpp @@ -71,7 +71,7 @@ namespace Nz void HandleEntryPoint(ShaderAst::DeclareFunctionStatement& node); void HandleInOut(); - void RegisterStruct(std::size_t structIndex, bool isStd140, ShaderAst::StructDescription desc); + void RegisterStruct(std::size_t structIndex, ShaderAst::StructDescription desc); void RegisterVariable(std::size_t varIndex, std::string varName); void Visit(ShaderAst::ExpressionPtr& expr, bool encloseIfRequired = false); diff --git a/include/Nazara/Shader/ShaderAstSerializer.hpp b/include/Nazara/Shader/ShaderAstSerializer.hpp index 20ac281bf..bb7e5f28b 100644 --- a/include/Nazara/Shader/ShaderAstSerializer.hpp +++ b/include/Nazara/Shader/ShaderAstSerializer.hpp @@ -48,7 +48,6 @@ namespace Nz::ShaderAst void Serialize(ReturnStatement& node); protected: - void Attributes(std::vector& attributes); template void Container(T& container); template void Enum(T& enumVal); template void OptEnum(std::optional& optVal); diff --git a/include/Nazara/Shader/ShaderBuilder.hpp b/include/Nazara/Shader/ShaderBuilder.hpp index c9f0b50de..ed6b3f624 100644 --- a/include/Nazara/Shader/ShaderBuilder.hpp +++ b/include/Nazara/Shader/ShaderBuilder.hpp @@ -10,6 +10,7 @@ #include #include #include +#include namespace Nz::ShaderBuilder { @@ -59,13 +60,12 @@ namespace Nz::ShaderBuilder struct DeclareFunction { inline std::unique_ptr operator()(std::string name, std::vector parameters, std::vector statements, ShaderAst::ExpressionType returnType = ShaderAst::NoType{}) const; - inline std::unique_ptr operator()(std::vector attributes, std::string name, std::vector parameters, std::vector statements, ShaderAst::ExpressionType returnType = ShaderAst::NoType{}) const; + inline std::unique_ptr operator()(std::optional entryStage, std::string name, std::vector parameters, std::vector statements, ShaderAst::ExpressionType returnType = ShaderAst::NoType{}) const; }; struct DeclareStruct { inline std::unique_ptr operator()(ShaderAst::StructDescription description) const; - inline std::unique_ptr operator()(std::vector attributes, ShaderAst::StructDescription description) const; }; struct DeclareVariable diff --git a/include/Nazara/Shader/ShaderBuilder.inl b/include/Nazara/Shader/ShaderBuilder.inl index ec83815a7..a034d35f9 100644 --- a/include/Nazara/Shader/ShaderBuilder.inl +++ b/include/Nazara/Shader/ShaderBuilder.inl @@ -108,10 +108,10 @@ namespace Nz::ShaderBuilder return declareFunctionNode; } - inline std::unique_ptr Impl::DeclareFunction::operator()(std::vector attributes, std::string name, std::vector parameters, std::vector statements, ShaderAst::ExpressionType returnType) const + inline std::unique_ptr Impl::DeclareFunction::operator()(std::optional entryStage, std::string name, std::vector parameters, std::vector statements, ShaderAst::ExpressionType returnType) const { auto declareFunctionNode = std::make_unique(); - declareFunctionNode->attributes = std::move(attributes); + declareFunctionNode->entryStage = entryStage; declareFunctionNode->name = std::move(name); declareFunctionNode->parameters = std::move(parameters); declareFunctionNode->returnType = std::move(returnType); @@ -128,15 +128,6 @@ namespace Nz::ShaderBuilder return declareStructNode; } - inline std::unique_ptr Impl::DeclareStruct::operator()(std::vector attributes, ShaderAst::StructDescription description) const - { - auto declareStructNode = std::make_unique(); - declareStructNode->attributes = std::move(attributes); - declareStructNode->description = std::move(description); - - return declareStructNode; - } - inline std::unique_ptr Nz::ShaderBuilder::Impl::DeclareVariable::operator()(std::string name, ShaderAst::ExpressionType type, ShaderAst::ExpressionPtr initialValue) const { auto declareVariableNode = std::make_unique(); diff --git a/include/Nazara/Shader/ShaderEnums.hpp b/include/Nazara/Shader/ShaderEnums.hpp index e56e71093..a25ef4caa 100644 --- a/include/Nazara/Shader/ShaderEnums.hpp +++ b/include/Nazara/Shader/ShaderEnums.hpp @@ -25,14 +25,6 @@ namespace Nz::ShaderAst Location //< Location (struct member only) - has argument index }; - enum class PrimitiveType - { - Boolean, //< bool - Float32, //< f32 - Int32, //< i32 - UInt32, //< ui32 - }; - enum class BinaryType { Add, //< + @@ -80,6 +72,14 @@ namespace Nz::ShaderAst #include }; + enum class PrimitiveType + { + Boolean, //< bool + Float32, //< f32 + Int32, //< i32 + UInt32, //< ui32 + }; + enum class SwizzleComponent { First, diff --git a/include/Nazara/Shader/ShaderLangParser.hpp b/include/Nazara/Shader/ShaderLangParser.hpp index 3c61ec888..1fa385c9f 100644 --- a/include/Nazara/Shader/ShaderLangParser.hpp +++ b/include/Nazara/Shader/ShaderLangParser.hpp @@ -14,6 +14,12 @@ namespace Nz::ShaderLang { + class AttributeError : public std::exception + { + public: + using exception::exception; + }; + class ExpectedToken : public std::exception { public: diff --git a/include/Nazara/Shader/ShaderNodes.hpp b/include/Nazara/Shader/ShaderNodes.hpp index 5413457f2..e5663c5d1 100644 --- a/include/Nazara/Shader/ShaderNodes.hpp +++ b/include/Nazara/Shader/ShaderNodes.hpp @@ -210,13 +210,12 @@ namespace Nz::ShaderAst struct ExternalVar { + std::optional bindingIndex; std::string name; - std::vector attributes; ExpressionType type; }; std::optional varIndex; - std::vector attributes; std::vector externalVars; }; @@ -231,10 +230,10 @@ namespace Nz::ShaderAst ExpressionType type; }; + std::optional entryStage; std::optional funcIndex; std::optional varIndex; std::string name; - std::vector attributes; std::vector parameters; std::vector statements; ExpressionType returnType; @@ -246,7 +245,6 @@ namespace Nz::ShaderAst void Visit(AstStatementVisitor& visitor) override; std::optional structIndex; - std::vector attributes; StructDescription description; }; diff --git a/src/Nazara/Shader/GlslWriter.cpp b/src/Nazara/Shader/GlslWriter.cpp index 6fcf520ed..08088d24f 100644 --- a/src/Nazara/Shader/GlslWriter.cpp +++ b/src/Nazara/Shader/GlslWriter.cpp @@ -24,12 +24,6 @@ namespace Nz static const char* s_outputPrefix = "_NzOut_"; static const char* s_outputVarName = "_nzOutput"; - //FIXME: Have this only once - std::unordered_map s_entryPoints = { - { "frag", ShaderStageType::Fragment }, - { "vert", ShaderStageType::Vertex }, - }; - template const T& Retrieve(const std::unordered_map& map, std::size_t id) { auto it = map.find(id); @@ -49,29 +43,19 @@ namespace Nz ShaderAst::DeclareFunctionStatement* func = static_cast(clone.get()); // Remove function if it's an entry point of another type than the one selected - bool isEntryPoint = false; - for (auto& attribute : func->attributes) + if (node.entryStage) { - if (attribute.type == ShaderAst::AttributeType::Entry) - { - auto it = s_entryPoints.find(std::get(attribute.args)); - assert(it != s_entryPoints.end()); + ShaderStageType stage = *node.entryStage; + if (stage != selectedStage) + return ShaderBuilder::NoOp(); - if (it->second != selectedEntryPoint) - return ShaderBuilder::NoOp(); - - isEntryPoint = true; - break; - } - } - - if (isEntryPoint) entryPoint = func; + } return clone; } - ShaderStageType selectedEntryPoint; + ShaderStageType selectedStage; ShaderAst::DeclareFunctionStatement* entryPoint = nullptr; }; @@ -81,8 +65,8 @@ namespace Nz ShaderStageTypeFlags stageFlags; }; - std::unordered_map builtinMapping = { - { "position", { "gl_Position", ShaderStageType::Vertex } } + std::unordered_map s_builtinMapping = { + { ShaderAst::BuiltinEntry::VertexPosition, { "gl_Position", ShaderStageType::Vertex } } }; } @@ -95,17 +79,11 @@ namespace Nz std::string targetName; }; - struct StructInfo - { - ShaderAst::StructDescription structDesc; - bool isStd140 = false; - }; - ShaderStageType stage; const States* states = nullptr; ShaderAst::DeclareFunctionStatement* entryFunc = nullptr; std::stringstream stream; - std::unordered_map structs; + std::unordered_map structs; std::unordered_map variableNames; std::vector inputFields; std::vector outputFields; @@ -138,7 +116,7 @@ namespace Nz ShaderAst::StatementPtr transformedShader = transformVisitor.Transform(shader); PreVisitor previsitor; - previsitor.selectedEntryPoint = shaderStage; + previsitor.selectedStage = shaderStage; ShaderAst::StatementPtr adaptedShader = previsitor.Clone(transformedShader); @@ -241,13 +219,13 @@ namespace Nz void GlslWriter::Append(const ShaderAst::StructType& structType) { - const auto& structDesc = Retrieve(m_currentState->structs, structType.structIndex).structDesc; + const auto& structDesc = Retrieve(m_currentState->structs, structType.structIndex); Append(structDesc.name); } void GlslWriter::Append(const ShaderAst::UniformType& uniformType) { - /* TODO */ + throw std::runtime_error("unexpected UniformType"); } void GlslWriter::Append(const ShaderAst::VectorType& vecType) @@ -305,7 +283,7 @@ namespace Nz void GlslWriter::AppendField(std::size_t structIndex, const std::size_t* memberIndices, std::size_t remainingMembers) { - const auto& structDesc = Retrieve(m_currentState->structs, structIndex).structDesc; + const auto& structDesc = Retrieve(m_currentState->structs, structIndex); const auto& member = structDesc.members[*memberIndices]; @@ -371,7 +349,7 @@ namespace Nz assert(IsStructType(parameter.type)); std::size_t structIndex = std::get(parameter.type).structIndex; - const ShaderAst::StructDescription& structDesc = Retrieve(m_currentState->structs, structIndex).structDesc; + const ShaderAst::StructDescription& structDesc = Retrieve(m_currentState->structs, structIndex); AppendLine(structDesc.name, " ", varName, ";"); for (const auto& [memberName, targetName] : m_currentState->inputFields) @@ -397,41 +375,24 @@ namespace Nz { for (const auto& member : structDesc.members) { - bool skip = false; - std::optional builtinName; - std::optional attributeLocation; - for (const auto& [attributeType, attributeParam] : member.attributes) + if (member.builtin) { - if (attributeType == ShaderAst::AttributeType::Builtin) - { - auto it = builtinMapping.find(std::get(attributeParam)); - if (it != builtinMapping.end()) - { - const Builtin& builtin = it->second; - if (!builtin.stageFlags.Test(m_currentState->stage)) - { - skip = true; - break; - } + auto it = s_builtinMapping.find(member.builtin.value()); + assert(it != s_builtinMapping.end()); - builtinName = builtin.identifier; - break; - } - } - else if (attributeType == ShaderAst::AttributeType::Location) - { - attributeLocation = std::get(attributeParam); - break; - } + const Builtin& builtin = it->second; + if (!builtin.stageFlags.Test(m_currentState->stage)) + continue; //< This builtin is not active in this stage, skip it + + fields.push_back({ + member.name, + builtin.identifier + }); } - - if (skip) - continue; - - if (attributeLocation) + else if (member.locationIndex) { Append("layout(location = "); - Append(*attributeLocation); + Append(*member.locationIndex); Append(") "); Append(keyword); Append(" "); @@ -446,13 +407,6 @@ namespace Nz targetPrefix + member.name }); } - else if (builtinName) - { - fields.push_back({ - member.name, - *builtinName - }); - } } AppendLine(); }; @@ -468,7 +422,7 @@ namespace Nz assert(std::holds_alternative(parameter.type)); std::size_t inputStructIndex = std::get(parameter.type).structIndex; - inputStruct = &Retrieve(m_currentState->structs, inputStructIndex).structDesc; + inputStruct = &Retrieve(m_currentState->structs, inputStructIndex); AppendCommentSection("Inputs"); AppendInOut(*inputStruct, m_currentState->inputFields, "in", s_inputPrefix); @@ -485,20 +439,17 @@ namespace Nz assert(std::holds_alternative(node.returnType)); std::size_t outputStructIndex = std::get(node.returnType).structIndex; - const ShaderAst::StructDescription& outputStruct = Retrieve(m_currentState->structs, outputStructIndex).structDesc; + const ShaderAst::StructDescription& outputStruct = Retrieve(m_currentState->structs, outputStructIndex); AppendCommentSection("Outputs"); AppendInOut(outputStruct, m_currentState->outputFields, "out", s_outputPrefix); } } - void GlslWriter::RegisterStruct(std::size_t structIndex, bool isStd140, ShaderAst::StructDescription desc) + void GlslWriter::RegisterStruct(std::size_t structIndex, ShaderAst::StructDescription desc) { assert(m_currentState->structs.find(structIndex) == m_currentState->structs.end()); - m_currentState->structs.emplace(structIndex, State::StructInfo{ - std::move(desc), - isStd140 - }); + m_currentState->structs.emplace(structIndex, std::move(desc)); } void GlslWriter::RegisterVariable(std::size_t varIndex, std::string varName) @@ -667,16 +618,6 @@ namespace Nz for (const auto& externalVar : node.externalVars) { - std::optional bindingIndex; - for (const auto& [attributeType, attributeParam] : externalVar.attributes) - { - if (attributeType == ShaderAst::AttributeType::Binding) - { - bindingIndex = std::get(attributeParam); - break; - } - } - bool isStd140 = false; if (IsUniformType(externalVar.type)) { @@ -685,13 +626,13 @@ namespace Nz std::size_t structIndex = std::get(uniform.containedType).structIndex; auto& structInfo = Retrieve(m_currentState->structs, structIndex); - isStd140 = structInfo.isStd140; + isStd140 = structInfo.layout == StructLayout_Std140; } - if (bindingIndex) + if (externalVar.bindingIndex) { Append("layout(binding = "); - Append(*bindingIndex); + Append(*externalVar.bindingIndex); if (isStd140) Append(", std140"); @@ -708,19 +649,19 @@ namespace Nz assert(std::holds_alternative(uniform.containedType)); std::size_t structIndex = std::get(uniform.containedType).structIndex; - auto& structInfo = Retrieve(m_currentState->structs, structIndex); + auto& structDesc = Retrieve(m_currentState->structs, structIndex); bool first = true; - for (const auto& [name, attribute, type] : structInfo.structDesc.members) + for (const auto& member : structDesc.members) { if (!first) AppendLine(); first = false; - Append(type); + Append(member.type); Append(" "); - Append(name); + Append(member.name); Append(";"); } } @@ -778,34 +719,24 @@ namespace Nz void GlslWriter::Visit(ShaderAst::DeclareStructStatement& node) { - bool isStd140 = false; - for (const auto& [attributeType, attributeParam] : node.attributes) - { - if (attributeType == ShaderAst::AttributeType::Layout && std::get(attributeParam) == "std140") - { - isStd140 = true; - break; - } - } - assert(node.structIndex); - RegisterStruct(*node.structIndex, isStd140, node.description); + RegisterStruct(*node.structIndex, node.description); Append("struct "); AppendLine(node.description.name); EnterScope(); { bool first = true; - for (const auto& [name, attribute, type] : node.description.members) + for (const auto& member : node.description.members) { if (!first) AppendLine(); first = false; - Append(type); + Append(member.type); Append(" "); - Append(name); + Append(member.name); Append(";"); } } @@ -897,7 +828,7 @@ namespace Nz const ShaderAst::ExpressionType& returnType = GetExpressionType(*node.returnExpr); assert(IsStructType(returnType)); std::size_t structIndex = std::get(returnType).structIndex; - const ShaderAst::StructDescription& structDesc = Retrieve(m_currentState->structs, structIndex).structDesc; + const ShaderAst::StructDescription& structDesc = Retrieve(m_currentState->structs, structIndex); std::string outputStructVarName; if (node.returnExpr->GetType() == ShaderAst::NodeType::VariableExpression) diff --git a/src/Nazara/Shader/ShaderAstCloner.cpp b/src/Nazara/Shader/ShaderAstCloner.cpp index 7e1b3256c..1a80e654f 100644 --- a/src/Nazara/Shader/ShaderAstCloner.cpp +++ b/src/Nazara/Shader/ShaderAstCloner.cpp @@ -45,7 +45,6 @@ namespace Nz::ShaderAst StatementPtr AstCloner::Clone(DeclareExternalStatement& node) { auto clone = std::make_unique(); - clone->attributes = node.attributes; clone->externalVars = node.externalVars; clone->varIndex = node.varIndex; @@ -55,7 +54,7 @@ namespace Nz::ShaderAst StatementPtr AstCloner::Clone(DeclareFunctionStatement& node) { auto clone = std::make_unique(); - clone->attributes = node.attributes; + clone->entryStage = node.entryStage; clone->funcIndex = node.funcIndex; clone->name = node.name; clone->parameters = node.parameters; diff --git a/src/Nazara/Shader/ShaderAstSerializer.cpp b/src/Nazara/Shader/ShaderAstSerializer.cpp index 7102e45fa..73ed6db60 100644 --- a/src/Nazara/Shader/ShaderAstSerializer.cpp +++ b/src/Nazara/Shader/ShaderAstSerializer.cpp @@ -115,6 +115,7 @@ namespace Nz::ShaderAst void AstSerializerBase::Serialize(DeclareVariableStatement& node) { + OptVal(node.varIndex); Value(node.varName); Type(node.varType); Node(node.initialExpression); @@ -168,14 +169,14 @@ namespace Nz::ShaderAst void AstSerializerBase::Serialize(DeclareExternalStatement& node) { - Attributes(node.attributes); + OptVal(node.varIndex); Container(node.externalVars); for (auto& extVar : node.externalVars) { - Attributes(extVar.attributes); Value(extVar.name); Type(extVar.type); + OptVal(extVar.bindingIndex); } } @@ -183,8 +184,9 @@ namespace Nz::ShaderAst { Value(node.name); Type(node.returnType); - - Attributes(node.attributes); + OptEnum(node.entryStage); + OptVal(node.funcIndex); + OptVal(node.varIndex); Container(node.parameters); for (auto& parameter : node.parameters) @@ -200,13 +202,18 @@ namespace Nz::ShaderAst void AstSerializerBase::Serialize(DeclareStructStatement& node) { + OptVal(node.structIndex); + Value(node.description.name); + OptEnum(node.description.layout); Container(node.description.members); for (auto& member : node.description.members) { Value(member.name); Type(member.type); + OptEnum(member.builtin); + OptVal(member.locationIndex); } } @@ -246,78 +253,6 @@ namespace Nz::ShaderAst m_stream.FlushBits(); } - void AstSerializerBase::Attributes(std::vector& attributes) - { - Container(attributes); - for (auto& attribute : attributes) - { - Enum(attribute.type); - - if (IsWriting()) - { - std::visit([&](auto&& arg) - { - using T = std::decay_t; - - if constexpr (std::is_same_v) - { - UInt8 typeId = 0; - Value(typeId); - } - else if constexpr (std::is_same_v) - { - UInt8 typeId = 1; - UInt64 v = UInt64(arg); - Value(typeId); - Value(v); - } - else if constexpr (std::is_same_v) - { - UInt8 typeId = 2; - Value(typeId); - Value(arg); - } - else - static_assert(AlwaysFalse::value, "non-exhaustive visitor"); - - }, attribute.args); - } - else - { - UInt8 typeId; - Value(typeId); - - switch (typeId) - { - case 0: - attribute.args.emplace(); - break; - - case 1: - { - UInt64 arg; - Value(arg); - - attribute.args = static_cast(arg); - break; - } - - case 2: - { - std::string arg; - Value(arg); - - attribute.args = std::move(arg); - break; - } - - default: - throw std::runtime_error("invalid attribute type id"); - } - } - } - } - bool ShaderAstSerializer::IsWriting() const { return true; diff --git a/src/Nazara/Shader/ShaderAstValidator.cpp b/src/Nazara/Shader/ShaderAstValidator.cpp index 98ecb65d8..ed7dcff50 100644 --- a/src/Nazara/Shader/ShaderAstValidator.cpp +++ b/src/Nazara/Shader/ShaderAstValidator.cpp @@ -11,14 +11,6 @@ namespace Nz::ShaderAst { - namespace - { - std::unordered_map entryPoints = { - { "frag", ShaderStageType::Fragment }, - { "vert", ShaderStageType::Vertex }, - }; - } - struct AstError { std::string errMsg; @@ -28,7 +20,7 @@ namespace Nz::ShaderAst { std::array entryFunctions = {}; std::unordered_set declaredExternalVar; - std::unordered_set usedBindingIndexes; + std::unordered_set usedBindingIndexes; }; bool AstValidator::Validate(StatementPtr& node, std::string* error) @@ -552,44 +544,15 @@ namespace Nz::ShaderAst void AstValidator::Visit(DeclareExternalStatement& node) { - if (!node.attributes.empty()) - throw AstError{ "unhandled attribute for external block" }; - - /*for (const auto& [attributeType, arg] : node.attributes) - { - switch (attributeType) - { - default: - throw AstError{ "unhandled attribute for external block" }; - } - }*/ - for (const auto& extVar : node.externalVars) { - bool hasBinding = false; - for (const auto& [attributeType, arg] : extVar.attributes) + if (extVar.bindingIndex) { - switch (attributeType) - { - case AttributeType::Binding: - { - if (hasBinding) - throw AstError{ "attribute binding must be present once" }; + unsigned int bindingIndex = extVar.bindingIndex.value(); + if (m_context->usedBindingIndexes.find(bindingIndex) != m_context->usedBindingIndexes.end()) + throw AstError{ "Binding #" + std::to_string(bindingIndex) + " is already in use" }; - if (!std::holds_alternative(arg)) - throw AstError{ "attribute binding requires a string parameter" }; - - long long bindingIndex = std::get(arg); - if (m_context->usedBindingIndexes.find(bindingIndex) != m_context->usedBindingIndexes.end()) - throw AstError{ "Binding #" + std::to_string(bindingIndex) + " is already in use" }; - - m_context->usedBindingIndexes.insert(bindingIndex); - break; - } - - default: - throw AstError{ "unhandled attribute for external variable" }; - } + m_context->usedBindingIndexes.insert(bindingIndex); } if (m_context->declaredExternalVar.find(extVar.name) != m_context->declaredExternalVar.end()) @@ -603,42 +566,17 @@ namespace Nz::ShaderAst void AstValidator::Visit(DeclareFunctionStatement& node) { - bool hasEntry = false; - for (const auto& [attributeType, arg] : node.attributes) + if (node.entryStage) { - switch (attributeType) - { - case AttributeType::Entry: - { - if (hasEntry) - throw AstError{ "attribute entry must be present once" }; + ShaderStageType stageType = *node.entryStage; - if (!std::holds_alternative(arg)) - throw AstError{ "attribute entry requires a string parameter" }; + if (m_context->entryFunctions[UnderlyingCast(stageType)]) + throw AstError{ "the same entry type has been defined multiple times" }; - const std::string& argStr = std::get(arg); + m_context->entryFunctions[UnderlyingCast(stageType)] = &node; - auto it = entryPoints.find(argStr); - if (it == entryPoints.end()) - throw AstError{ "invalid parameter " + argStr + " for entry attribute" }; - - ShaderStageType stageType = it->second; - - if (m_context->entryFunctions[UnderlyingCast(stageType)]) - throw AstError{ "the same entry type has been defined multiple times" }; - - m_context->entryFunctions[UnderlyingCast(it->second)] = &node; - - if (node.parameters.size() > 1) - throw AstError{ "entry functions can either take one struct parameter or no parameter" }; - - hasEntry = true; - break; - } - - default: - throw AstError{ "unhandled attribute for function" }; - } + if (node.parameters.size() > 1) + throw AstError{ "entry functions can either take one struct parameter or no parameter" }; } for (auto& statement : node.statements) diff --git a/src/Nazara/Shader/ShaderLangParser.cpp b/src/Nazara/Shader/ShaderLangParser.cpp index b896055a0..b0636f7be 100644 --- a/src/Nazara/Shader/ShaderLangParser.cpp +++ b/src/Nazara/Shader/ShaderLangParser.cpp @@ -1,631 +1,737 @@ -// 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 -#include -#include -#include - -namespace Nz::ShaderLang -{ - namespace - { - std::unordered_map identifierToBasicType = { - { "bool", ShaderAst::PrimitiveType::Boolean }, - { "i32", ShaderAst::PrimitiveType::Int32 }, - { "f32", ShaderAst::PrimitiveType::Float32 }, - { "u32", ShaderAst::PrimitiveType::UInt32 } - }; +// 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 +#include +#include +#include + +namespace Nz::ShaderLang +{ + namespace + { + std::unordered_map identifierToBasicType = { + { "bool", ShaderAst::PrimitiveType::Boolean }, + { "i32", ShaderAst::PrimitiveType::Int32 }, + { "f32", ShaderAst::PrimitiveType::Float32 }, + { "u32", ShaderAst::PrimitiveType::UInt32 } + }; std::unordered_map identifierToIntrinsic = { { "cross", ShaderAst::IntrinsicType::CrossProduct }, { "dot", ShaderAst::IntrinsicType::DotProduct }, }; - - std::unordered_map identifierToAttributeType = { - { "binding", ShaderAst::AttributeType::Binding }, - { "builtin", ShaderAst::AttributeType::Builtin }, - { "entry", ShaderAst::AttributeType::Entry }, - { "layout", ShaderAst::AttributeType::Layout }, - { "location", ShaderAst::AttributeType::Location }, + + std::unordered_map identifierToAttributeType = { + { "binding", ShaderAst::AttributeType::Binding }, + { "builtin", ShaderAst::AttributeType::Builtin }, + { "entry", ShaderAst::AttributeType::Entry }, + { "layout", ShaderAst::AttributeType::Layout }, + { "location", ShaderAst::AttributeType::Location }, + }; + + std::unordered_map s_entryPoints = { + { "frag", ShaderStageType::Fragment }, + { "vert", ShaderStageType::Vertex }, }; - } - ShaderAst::StatementPtr Parser::Parse(const std::vector& tokens) - { - Context context; - context.tokenCount = tokens.size(); - context.tokens = tokens.data(); + std::unordered_map s_builtinMapping = { + { "position", ShaderAst::BuiltinEntry::VertexPosition } + }; - context.root = std::make_unique(); + template + std::optional BoundCast(U val) + { + if (val < std::numeric_limits::min() || val > std::numeric_limits::max()) + return std::nullopt; - m_context = &context; - - std::vector attributes; + return static_cast(val); + } + } + + ShaderAst::StatementPtr Parser::Parse(const std::vector& tokens) + { + Context context; + context.tokenCount = tokens.size(); + context.tokens = tokens.data(); + + context.root = std::make_unique(); + + m_context = &context; + + std::vector attributes; EnterScope(); - - bool reachedEndOfStream = false; - while (!reachedEndOfStream) - { - const Token& nextToken = Peek(); - switch (nextToken.type) - { - case TokenType::EndOfStream: - if (!attributes.empty()) - throw UnexpectedToken{}; - - reachedEndOfStream = true; - break; - - case TokenType::External: - context.root->statements.push_back(ParseExternalBlock(std::move(attributes))); - attributes.clear(); - break; - - case TokenType::OpenAttribute: - assert(attributes.empty()); - attributes = ParseAttributes(); - break; - - case TokenType::FunctionDeclaration: - context.root->statements.push_back(ParseFunctionDeclaration(std::move(attributes))); - attributes.clear(); - break; - - case TokenType::Struct: - context.root->statements.push_back(ParseStructDeclaration(std::move(attributes))); - attributes.clear(); - break; - - default: - throw UnexpectedToken{}; - } - } + + bool reachedEndOfStream = false; + while (!reachedEndOfStream) + { + const Token& nextToken = Peek(); + switch (nextToken.type) + { + case TokenType::EndOfStream: + if (!attributes.empty()) + throw UnexpectedToken{}; + + reachedEndOfStream = true; + break; + + case TokenType::External: + context.root->statements.push_back(ParseExternalBlock(std::move(attributes))); + attributes.clear(); + break; + + case TokenType::OpenAttribute: + assert(attributes.empty()); + attributes = ParseAttributes(); + break; + + case TokenType::FunctionDeclaration: + context.root->statements.push_back(ParseFunctionDeclaration(std::move(attributes))); + attributes.clear(); + break; + + case TokenType::Struct: + context.root->statements.push_back(ParseStructDeclaration(std::move(attributes))); + attributes.clear(); + break; + + default: + throw UnexpectedToken{}; + } + } LeaveScope(); - - return std::move(context.root); - } - - const Token& Parser::Advance() + + return std::move(context.root); + } + + const Token& Parser::Advance() + { + const Token& token = Peek(); + m_context->tokenIndex++; + + return token; + } + + void Parser::Consume(std::size_t count) + { + assert(m_context->tokenIndex + count < m_context->tokenCount); + m_context->tokenIndex += count; + } + + ShaderAst::ExpressionType Parser::DecodeType(const std::string& identifier) + { + if (auto it = identifierToBasicType.find(identifier); it != identifierToBasicType.end()) + return it->second; + + //FIXME: Handle this better + if (identifier == "mat4") + { + ShaderAst::MatrixType matrixType; + matrixType.columnCount = 4; + matrixType.rowCount = 4; + + Expect(Advance(), TokenType::LessThan); //< '<' + matrixType.type = ParsePrimitiveType(); + Expect(Advance(), TokenType::GreatherThan); //< '>' + + return matrixType; + } + else if (identifier == "sampler2D") + { + ShaderAst::SamplerType samplerType; + samplerType.dim = ImageType_2D; + + Expect(Advance(), TokenType::LessThan); //< '<' + samplerType.sampledType = ParsePrimitiveType(); + Expect(Advance(), TokenType::GreatherThan); //< '>' + + return samplerType; + } + else if (identifier == "uniform") + { + ShaderAst::UniformType uniformType; + + Expect(Advance(), TokenType::LessThan); //< '<' + uniformType.containedType = ShaderAst::IdentifierType{ ParseIdentifierAsName() }; + Expect(Advance(), TokenType::GreatherThan); //< '>' + + return uniformType; + } + else if (identifier == "vec2") + { + ShaderAst::VectorType vectorType; + vectorType.componentCount = 2; + + Expect(Advance(), TokenType::LessThan); //< '<' + vectorType.type = ParsePrimitiveType(); + Expect(Advance(), TokenType::GreatherThan); //< '>' + + return vectorType; + } + else if (identifier == "vec3") + { + ShaderAst::VectorType vectorType; + vectorType.componentCount = 3; + + Expect(Advance(), TokenType::LessThan); //< '<' + vectorType.type = ParsePrimitiveType(); + Expect(Advance(), TokenType::GreatherThan); //< '>' + + return vectorType; + } + else if (identifier == "vec4") + { + ShaderAst::VectorType vectorType; + vectorType.componentCount = 4; + + Expect(Advance(), TokenType::LessThan); //< '<' + vectorType.type = ParsePrimitiveType(); + Expect(Advance(), TokenType::GreatherThan); //< '>' + + return vectorType; + } + else + { + ShaderAst::IdentifierType identifierType; + identifierType.name = identifier; + + return identifierType; + } + } + + void Parser::EnterScope() + { + m_context->scopeSizes.push_back(m_context->identifiersInScope.size()); + } + + const Token& Parser::Expect(const Token& token, TokenType type) + { + if (token.type != type) + throw ExpectedToken{}; + + return token; + } + + const Token& Parser::ExpectNot(const Token& token, TokenType type) + { + if (token.type == type) + throw ExpectedToken{}; + + return token; + } + + const Token& Parser::Expect(TokenType type) + { + const Token& token = Peek(); + Expect(token, type); + + return token; + } + + void Parser::LeaveScope() + { + assert(!m_context->scopeSizes.empty()); + m_context->identifiersInScope.resize(m_context->scopeSizes.back()); + m_context->scopeSizes.pop_back(); + } + + bool Parser::IsVariableInScope(const std::string_view& identifier) const { - const Token& token = Peek(); - m_context->tokenIndex++; - - return token; + return std::find(m_context->identifiersInScope.rbegin(), m_context->identifiersInScope.rend(), identifier) != m_context->identifiersInScope.rend(); } - - void Parser::Consume(std::size_t count) - { - assert(m_context->tokenIndex + count < m_context->tokenCount); - m_context->tokenIndex += count; - } - - ShaderAst::ExpressionType Parser::DecodeType(const std::string& identifier) - { - if (auto it = identifierToBasicType.find(identifier); it != identifierToBasicType.end()) - return it->second; - - //FIXME: Handle this better - if (identifier == "mat4") - { - ShaderAst::MatrixType matrixType; - matrixType.columnCount = 4; - matrixType.rowCount = 4; - - Expect(Advance(), TokenType::LessThan); //< '<' - matrixType.type = ParsePrimitiveType(); - Expect(Advance(), TokenType::GreatherThan); //< '>' - - return matrixType; - } - else if (identifier == "sampler2D") - { - ShaderAst::SamplerType samplerType; - samplerType.dim = ImageType_2D; - - Expect(Advance(), TokenType::LessThan); //< '<' - samplerType.sampledType = ParsePrimitiveType(); - Expect(Advance(), TokenType::GreatherThan); //< '>' - - return samplerType; - } - else if (identifier == "uniform") - { - ShaderAst::UniformType uniformType; - - Expect(Advance(), TokenType::LessThan); //< '<' - uniformType.containedType = ShaderAst::IdentifierType{ ParseIdentifierAsName() }; - Expect(Advance(), TokenType::GreatherThan); //< '>' - - return uniformType; - } - else if (identifier == "vec2") - { - ShaderAst::VectorType vectorType; - vectorType.componentCount = 2; - - Expect(Advance(), TokenType::LessThan); //< '<' - vectorType.type = ParsePrimitiveType(); - Expect(Advance(), TokenType::GreatherThan); //< '>' - - return vectorType; - } - else if (identifier == "vec3") - { - ShaderAst::VectorType vectorType; - vectorType.componentCount = 3; - - Expect(Advance(), TokenType::LessThan); //< '<' - vectorType.type = ParsePrimitiveType(); - Expect(Advance(), TokenType::GreatherThan); //< '>' - - return vectorType; - } - else if (identifier == "vec4") - { - ShaderAst::VectorType vectorType; - vectorType.componentCount = 4; - - Expect(Advance(), TokenType::LessThan); //< '<' - vectorType.type = ParsePrimitiveType(); - Expect(Advance(), TokenType::GreatherThan); //< '>' - - return vectorType; - } - else - { - ShaderAst::IdentifierType identifierType; - identifierType.name = identifier; - - return identifierType; - } - } - - void Parser::EnterScope() - { - m_context->scopeSizes.push_back(m_context->identifiersInScope.size()); - } - - const Token& Parser::Expect(const Token& token, TokenType type) - { - if (token.type != type) - throw ExpectedToken{}; - - return token; - } - - const Token& Parser::ExpectNot(const Token& token, TokenType type) - { - if (token.type == type) - throw ExpectedToken{}; - - return token; - } - - const Token& Parser::Expect(TokenType type) - { - const Token& token = Peek(); - Expect(token, type); - - return token; - } - - void Parser::LeaveScope() - { - assert(!m_context->scopeSizes.empty()); - m_context->identifiersInScope.resize(m_context->scopeSizes.back()); - m_context->scopeSizes.pop_back(); - } - - bool Parser::IsVariableInScope(const std::string_view& identifier) const - { - return std::find(m_context->identifiersInScope.rbegin(), m_context->identifiersInScope.rend(), identifier) != m_context->identifiersInScope.rend(); - } - - void Parser::RegisterVariable(std::string identifier) + + void Parser::RegisterVariable(std::string identifier) { if (IsVariableInScope(identifier)) throw DuplicateIdentifier{ ("identifier name " + identifier + " is already taken").c_str() }; assert(!m_context->scopeSizes.empty()); - m_context->identifiersInScope.push_back(std::move(identifier)); - } - - const Token& Parser::Peek(std::size_t advance) + m_context->identifiersInScope.push_back(std::move(identifier)); + } + + const Token& Parser::Peek(std::size_t advance) + { + assert(m_context->tokenIndex + advance < m_context->tokenCount); + return m_context->tokens[m_context->tokenIndex + advance]; + } + + std::vector Parser::ParseAttributes() + { + std::vector attributes; + + Expect(Advance(), TokenType::OpenAttribute); + + bool expectComma = false; + for (;;) + { + const Token& t = Peek(); + ExpectNot(t, TokenType::EndOfStream); + + if (t.type == TokenType::ClosingAttribute) + { + // Parse [[attribute1]] [[attribute2]] the same as [[attribute1, attribute2]] + if (Peek(1).type == TokenType::OpenAttribute) + { + Consume(2); + expectComma = false; + continue; + } + + break; + } + + if (expectComma) + Expect(Advance(), TokenType::Comma); + + ShaderAst::AttributeType attributeType = ParseIdentifierAsAttributeType(); + + ShaderAst::Attribute::Param arg; + if (Peek().type == TokenType::OpenParenthesis) + { + Consume(); + + const Token& n = Peek(); + if (n.type == TokenType::Identifier) + { + arg = std::get(n.data); + Consume(); + } + else if (n.type == TokenType::IntegerValue) + { + arg = std::get(n.data); + Consume(); + } + + Expect(Advance(), TokenType::ClosingParenthesis); + } + + expectComma = true; + + attributes.push_back({ + attributeType, + std::move(arg) + }); + } + + Expect(Advance(), TokenType::ClosingAttribute); + + return attributes; + } + + ShaderAst::StatementPtr Parser::ParseExternalBlock(std::vector attributes) { - assert(m_context->tokenIndex + advance < m_context->tokenCount); - return m_context->tokens[m_context->tokenIndex + advance]; - } - - std::vector Parser::ParseAttributes() - { - std::vector attributes; - - Expect(Advance(), TokenType::OpenAttribute); - - bool expectComma = false; - for (;;) - { - const Token& t = Peek(); - ExpectNot(t, TokenType::EndOfStream); - - if (t.type == TokenType::ClosingAttribute) - { - // Parse [[attribute1]] [[attribute2]] the same as [[attribute1, attribute2]] - if (Peek(1).type == TokenType::OpenAttribute) - { - Consume(2); - expectComma = false; - continue; - } - - break; - } - - if (expectComma) - Expect(Advance(), TokenType::Comma); - - ShaderAst::AttributeType attributeType = ParseIdentifierAsAttributeType(); - - ShaderAst::Attribute::Param arg; - if (Peek().type == TokenType::OpenParenthesis) - { - Consume(); - - const Token& n = Peek(); - if (n.type == TokenType::Identifier) - { - arg = std::get(n.data); - Consume(); - } - else if (n.type == TokenType::IntegerValue) - { - arg = std::get(n.data); - Consume(); - } - - Expect(Advance(), TokenType::ClosingParenthesis); - } - - expectComma = true; - - attributes.push_back({ - attributeType, - std::move(arg) - }); - } - - Expect(Advance(), TokenType::ClosingAttribute); - - return attributes; - } - - ShaderAst::StatementPtr Parser::ParseExternalBlock(std::vector attributes) - { - Expect(Advance(), TokenType::External); - Expect(Advance(), TokenType::OpenCurlyBracket); - - std::unique_ptr externalStatement = std::make_unique(); - externalStatement->attributes = std::move(attributes); - - bool first = true; - - for (;;) - { - if (!first) - { - const Token& nextToken = Peek(); - if (nextToken.type == TokenType::Comma) - Consume(); - else - { - Expect(nextToken, TokenType::ClosingCurlyBracket); - break; - } - } - - first = false; - - const Token& token = Peek(); - if (token.type == TokenType::ClosingCurlyBracket) - break; - - auto& extVar = externalStatement->externalVars.emplace_back(); - + if (!attributes.empty()) + throw AttributeError{ "unhandled attribute for external block" }; + + Expect(Advance(), TokenType::External); + Expect(Advance(), TokenType::OpenCurlyBracket); + + std::unique_ptr externalStatement = std::make_unique(); + + bool first = true; + for (;;) + { + if (!first) + { + const Token& nextToken = Peek(); + if (nextToken.type == TokenType::Comma) + Consume(); + else + { + Expect(nextToken, TokenType::ClosingCurlyBracket); + break; + } + } + + first = false; + + const Token& token = Peek(); + if (token.type == TokenType::ClosingCurlyBracket) + break; + + auto& extVar = externalStatement->externalVars.emplace_back(); + if (token.type == TokenType::OpenAttribute) - extVar.attributes = ParseAttributes(); + { + for (const auto& [attributeType, arg] : ParseAttributes()) + { + switch (attributeType) + { + case ShaderAst::AttributeType::Binding: + { + if (extVar.bindingIndex) + throw AttributeError{ "attribute binding must be present once" }; - extVar.name = ParseIdentifierAsName(); - Expect(Advance(), TokenType::Colon); + if (!std::holds_alternative(arg)) + throw AttributeError{ "attribute binding requires a string parameter" }; + + std::optional bindingIndex = BoundCast(std::get(arg)); + if (!bindingIndex) + throw AttributeError{ "invalid binding index" }; + + extVar.bindingIndex = bindingIndex.value(); + break; + } + + default: + throw AttributeError{ "unhandled attribute for external variable" }; + } + } + } + + extVar.name = ParseIdentifierAsName(); + Expect(Advance(), TokenType::Colon); extVar.type = ParseType(); - RegisterVariable(extVar.name); - } + RegisterVariable(extVar.name); + } + + Expect(Advance(), TokenType::ClosingCurlyBracket); + + return externalStatement; + } + + std::vector Parser::ParseFunctionBody() + { + return ParseStatementList(); + } + + ShaderAst::StatementPtr Parser::ParseFunctionDeclaration(std::vector attributes) + { + Expect(Advance(), TokenType::FunctionDeclaration); + + std::string functionName = ParseIdentifierAsName(); + + Expect(Advance(), TokenType::OpenParenthesis); + + std::vector parameters; + + bool firstParameter = true; + for (;;) + { + const Token& t = Peek(); + ExpectNot(t, TokenType::EndOfStream); + + if (t.type == TokenType::ClosingParenthesis) + break; + + if (!firstParameter) + Expect(Advance(), TokenType::Comma); + + parameters.push_back(ParseFunctionParameter()); + firstParameter = false; + } + + Expect(Advance(), TokenType::ClosingParenthesis); + + ShaderAst::ExpressionType returnType; + if (Peek().type == TokenType::FunctionReturn) + { + Consume(); + returnType = ParseType(); + } + + Expect(Advance(), TokenType::OpenCurlyBracket); - Expect(Advance(), TokenType::ClosingCurlyBracket); - - return externalStatement; - } - - std::vector Parser::ParseFunctionBody() - { - return ParseStatementList(); - } - - ShaderAst::StatementPtr Parser::ParseFunctionDeclaration(std::vector attributes) - { - Expect(Advance(), TokenType::FunctionDeclaration); - - std::string functionName = ParseIdentifierAsName(); - - Expect(Advance(), TokenType::OpenParenthesis); - - std::vector parameters; - - bool firstParameter = true; - for (;;) - { - const Token& t = Peek(); - ExpectNot(t, TokenType::EndOfStream); - - if (t.type == TokenType::ClosingParenthesis) - break; - - if (!firstParameter) - Expect(Advance(), TokenType::Comma); - - parameters.push_back(ParseFunctionParameter()); - firstParameter = false; - } - - Expect(Advance(), TokenType::ClosingParenthesis); - - ShaderAst::ExpressionType returnType; - if (Peek().type == TokenType::FunctionReturn) - { - Consume(); - returnType = ParseType(); - } - - Expect(Advance(), TokenType::OpenCurlyBracket); - - EnterScope(); + EnterScope(); for (const auto& parameter : parameters) RegisterVariable(parameter.name); + + std::vector functionBody = ParseFunctionBody(); - std::vector functionBody = ParseFunctionBody(); - - LeaveScope(); - - Expect(Advance(), TokenType::ClosingCurlyBracket); - - return ShaderBuilder::DeclareFunction(std::move(attributes), std::move(functionName), std::move(parameters), std::move(functionBody), std::move(returnType)); - } - - ShaderAst::DeclareFunctionStatement::Parameter Parser::ParseFunctionParameter() - { - std::string parameterName = ParseIdentifierAsName(); - - Expect(Advance(), TokenType::Colon); - - ShaderAst::ExpressionType parameterType = ParseType(); - - return { parameterName, parameterType }; - } - - ShaderAst::StatementPtr Parser::ParseStructDeclaration(std::vector attributes) - { - Expect(Advance(), TokenType::Struct); - - ShaderAst::StructDescription description; - description.name = ParseIdentifierAsName(); - - Expect(Advance(), TokenType::OpenCurlyBracket); - - bool first = true; - - for (;;) - { - if (!first) - { - const Token& nextToken = Peek(); - if (nextToken.type == TokenType::Comma) - Consume(); - else - { - Expect(nextToken, TokenType::ClosingCurlyBracket); - break; - } - } - - first = false; - - const Token& token = Peek(); - if (token.type == TokenType::ClosingCurlyBracket) - break; - - auto& structField = description.members.emplace_back(); + LeaveScope(); + + Expect(Advance(), TokenType::ClosingCurlyBracket); + std::optional entryPoint; + for (const auto& [attributeType, arg] : attributes) + { + switch (attributeType) + { + case ShaderAst::AttributeType::Entry: + { + if (entryPoint) + throw AttributeError{ "attribute entry must be present once" }; + + if (!std::holds_alternative(arg)) + throw AttributeError{ "attribute entry requires a string parameter" }; + + const std::string& argStr = std::get(arg); + + auto it = s_entryPoints.find(argStr); + if (it == s_entryPoints.end()) + throw AttributeError{ ("invalid parameter " + argStr + " for entry attribute").c_str() }; + + entryPoint = it->second; + break; + } + + default: + throw AttributeError{ "unhandled attribute for function" }; + } + } + + return ShaderBuilder::DeclareFunction(entryPoint, std::move(functionName), std::move(parameters), std::move(functionBody), std::move(returnType)); + } + + ShaderAst::DeclareFunctionStatement::Parameter Parser::ParseFunctionParameter() + { + std::string parameterName = ParseIdentifierAsName(); + + Expect(Advance(), TokenType::Colon); + + ShaderAst::ExpressionType parameterType = ParseType(); + + return { parameterName, parameterType }; + } + + ShaderAst::StatementPtr Parser::ParseStructDeclaration(std::vector attributes) + { + Expect(Advance(), TokenType::Struct); + + ShaderAst::StructDescription description; + description.name = ParseIdentifierAsName(); + + Expect(Advance(), TokenType::OpenCurlyBracket); + + bool first = true; + + for (;;) + { + if (!first) + { + const Token& nextToken = Peek(); + if (nextToken.type == TokenType::Comma) + Consume(); + else + { + Expect(nextToken, TokenType::ClosingCurlyBracket); + break; + } + } + + first = false; + + const Token& token = Peek(); + if (token.type == TokenType::ClosingCurlyBracket) + break; + + auto& structField = description.members.emplace_back(); + if (token.type == TokenType::OpenAttribute) - structField.attributes = ParseAttributes(); - - structField.name = ParseIdentifierAsName(); - - Expect(Advance(), TokenType::Colon); - - structField.type = ParseType(); - } - - Expect(Advance(), TokenType::ClosingCurlyBracket); - - return ShaderBuilder::DeclareStruct(std::move(attributes), std::move(description)); - } - - ShaderAst::StatementPtr Parser::ParseReturnStatement() - { - Expect(Advance(), TokenType::Return); - - ShaderAst::ExpressionPtr expr; - if (Peek().type != TokenType::Semicolon) - expr = ParseExpression(); - - return ShaderBuilder::Return(std::move(expr)); - } - - ShaderAst::StatementPtr Parser::ParseStatement() - { - const Token& token = Peek(); - - ShaderAst::StatementPtr statement; - switch (token.type) - { - case TokenType::Let: - statement = ParseVariableDeclaration(); - break; - - case TokenType::Identifier: - statement = ShaderBuilder::ExpressionStatement(ParseVariableAssignation()); - break; - - case TokenType::Return: - statement = ParseReturnStatement(); - break; - - default: - break; - } - - Expect(Advance(), TokenType::Semicolon); - - return statement; - } - - std::vector Parser::ParseStatementList() - { - std::vector statements; - while (Peek().type != TokenType::ClosingCurlyBracket) - { - ExpectNot(Peek(), TokenType::EndOfStream); - statements.push_back(ParseStatement()); - } - - return statements; - } - - ShaderAst::ExpressionPtr Parser::ParseVariableAssignation() - { - ShaderAst::ExpressionPtr left = ParseIdentifier(); - Expect(Advance(), TokenType::Assign); - - ShaderAst::ExpressionPtr right = ParseExpression(); - - return ShaderBuilder::Assign(ShaderAst::AssignType::Simple, std::move(left), std::move(right)); - } - - ShaderAst::StatementPtr Parser::ParseVariableDeclaration() - { - Expect(Advance(), TokenType::Let); - - std::string variableName = ParseIdentifierAsName(); - RegisterVariable(variableName); - - Expect(Advance(), TokenType::Colon); - - ShaderAst::ExpressionType variableType = ParseType(); - - ShaderAst::ExpressionPtr expression; - if (Peek().type == TokenType::Assign) - { - Consume(); - expression = ParseExpression(); - } - - return ShaderBuilder::DeclareVariable(std::move(variableName), std::move(variableType), std::move(expression)); - } - - ShaderAst::ExpressionPtr Parser::ParseBinOpRhs(int exprPrecedence, ShaderAst::ExpressionPtr lhs) - { - for (;;) - { - const Token& currentOp = Peek(); - ExpectNot(currentOp, TokenType::EndOfStream); - - int tokenPrecedence = GetTokenPrecedence(currentOp.type); - if (tokenPrecedence < exprPrecedence) - return lhs; - - Consume(); - ShaderAst::ExpressionPtr rhs = ParsePrimaryExpression(); - - const Token& nextOp = Peek(); - - int nextTokenPrecedence = GetTokenPrecedence(nextOp.type); - if (tokenPrecedence < nextTokenPrecedence) - rhs = ParseBinOpRhs(tokenPrecedence + 1, std::move(rhs)); - - ShaderAst::BinaryType binaryType; { - switch (currentOp.type) + for (const auto& [attributeType, attributeParam] : ParseAttributes()) { - case TokenType::Plus: binaryType = ShaderAst::BinaryType::Add; break; - case TokenType::Minus: binaryType = ShaderAst::BinaryType::Subtract; break; - case TokenType::Multiply: binaryType = ShaderAst::BinaryType::Multiply; break; - case TokenType::Divide: binaryType = ShaderAst::BinaryType::Divide; break; - default: throw UnexpectedToken{}; + switch (attributeType) + { + case ShaderAst::AttributeType::Builtin: + { + if (structField.builtin) + throw AttributeError{ "attribute builtin must be present once" }; + + auto it = s_builtinMapping.find(std::get(attributeParam)); + if (it == s_builtinMapping.end()) + throw AttributeError{ "unknown builtin" }; + + structField.builtin = it->second; + break; + } + + case ShaderAst::AttributeType::Location: + { + if (structField.locationIndex) + throw AttributeError{ "attribute location must be present once" }; + + structField.locationIndex = BoundCast(std::get(attributeParam)); + if (!structField.locationIndex) + throw AttributeError{ "invalid location index" }; + + break; + } + } } - } - lhs = ShaderBuilder::Binary(binaryType, std::move(lhs), std::move(rhs)); - } - } - - ShaderAst::ExpressionPtr Parser::ParseExpression() - { - return ParseBinOpRhs(0, ParsePrimaryExpression()); - } - - ShaderAst::ExpressionPtr Parser::ParseFloatingPointExpression(bool minus) - { - const Token& floatingPointToken = Expect(Advance(), TokenType::FloatingPointValue); - return ShaderBuilder::Constant(((minus) ? -1.f : 1.f) * float(std::get(floatingPointToken.data))); //< FIXME - } - - ShaderAst::ExpressionPtr Parser::ParseIdentifier() - { - const Token& identifierToken = Expect(Advance(), TokenType::Identifier); - const std::string& identifier = std::get(identifierToken.data); - - ShaderAst::ExpressionPtr identifierExpr = ShaderBuilder::Identifier(identifier); - - if (Peek().type == TokenType::Dot) - { - std::unique_ptr accessMemberNode = std::make_unique(); - accessMemberNode->structExpr = std::move(identifierExpr); - - do - { - Consume(); - - accessMemberNode->memberIdentifiers.push_back(ParseIdentifierAsName()); - } while (Peek().type == TokenType::Dot); - - identifierExpr = std::move(accessMemberNode); - } - - return identifierExpr; - } - - ShaderAst::ExpressionPtr Parser::ParseIntegerExpression(bool minus) - { - const Token& integerToken = Expect(Advance(), TokenType::IntegerValue); - return ShaderBuilder::Constant(((minus) ? -1 : 1) * static_cast(std::get(integerToken.data))); - } - - std::vector Parser::ParseParameters() - { + if (structField.builtin && structField.locationIndex) + throw AttributeError{ "A struct field cannot have both builtin and location attributes" }; + } + + structField.name = ParseIdentifierAsName(); + + Expect(Advance(), TokenType::Colon); + + structField.type = ParseType(); + } + + Expect(Advance(), TokenType::ClosingCurlyBracket); + + return ShaderBuilder::DeclareStruct(std::move(description)); + } + + ShaderAst::StatementPtr Parser::ParseReturnStatement() + { + Expect(Advance(), TokenType::Return); + + ShaderAst::ExpressionPtr expr; + if (Peek().type != TokenType::Semicolon) + expr = ParseExpression(); + + return ShaderBuilder::Return(std::move(expr)); + } + + ShaderAst::StatementPtr Parser::ParseStatement() + { + const Token& token = Peek(); + + ShaderAst::StatementPtr statement; + switch (token.type) + { + case TokenType::Let: + statement = ParseVariableDeclaration(); + break; + + case TokenType::Identifier: + statement = ShaderBuilder::ExpressionStatement(ParseVariableAssignation()); + break; + + case TokenType::Return: + statement = ParseReturnStatement(); + break; + + default: + break; + } + + Expect(Advance(), TokenType::Semicolon); + + return statement; + } + + std::vector Parser::ParseStatementList() + { + std::vector statements; + while (Peek().type != TokenType::ClosingCurlyBracket) + { + ExpectNot(Peek(), TokenType::EndOfStream); + statements.push_back(ParseStatement()); + } + + return statements; + } + + ShaderAst::ExpressionPtr Parser::ParseVariableAssignation() + { + ShaderAst::ExpressionPtr left = ParseIdentifier(); + Expect(Advance(), TokenType::Assign); + + ShaderAst::ExpressionPtr right = ParseExpression(); + + return ShaderBuilder::Assign(ShaderAst::AssignType::Simple, std::move(left), std::move(right)); + } + + ShaderAst::StatementPtr Parser::ParseVariableDeclaration() + { + Expect(Advance(), TokenType::Let); + + std::string variableName = ParseIdentifierAsName(); + RegisterVariable(variableName); + + Expect(Advance(), TokenType::Colon); + + ShaderAst::ExpressionType variableType = ParseType(); + + ShaderAst::ExpressionPtr expression; + if (Peek().type == TokenType::Assign) + { + Consume(); + expression = ParseExpression(); + } + + return ShaderBuilder::DeclareVariable(std::move(variableName), std::move(variableType), std::move(expression)); + } + + ShaderAst::ExpressionPtr Parser::ParseBinOpRhs(int exprPrecedence, ShaderAst::ExpressionPtr lhs) + { + for (;;) + { + const Token& currentOp = Peek(); + ExpectNot(currentOp, TokenType::EndOfStream); + + int tokenPrecedence = GetTokenPrecedence(currentOp.type); + if (tokenPrecedence < exprPrecedence) + return lhs; + + Consume(); + ShaderAst::ExpressionPtr rhs = ParsePrimaryExpression(); + + const Token& nextOp = Peek(); + + int nextTokenPrecedence = GetTokenPrecedence(nextOp.type); + if (tokenPrecedence < nextTokenPrecedence) + rhs = ParseBinOpRhs(tokenPrecedence + 1, std::move(rhs)); + + ShaderAst::BinaryType binaryType; + { + switch (currentOp.type) + { + case TokenType::Plus: binaryType = ShaderAst::BinaryType::Add; break; + case TokenType::Minus: binaryType = ShaderAst::BinaryType::Subtract; break; + case TokenType::Multiply: binaryType = ShaderAst::BinaryType::Multiply; break; + case TokenType::Divide: binaryType = ShaderAst::BinaryType::Divide; break; + default: throw UnexpectedToken{}; + } + } + + lhs = ShaderBuilder::Binary(binaryType, std::move(lhs), std::move(rhs)); + } + } + + ShaderAst::ExpressionPtr Parser::ParseExpression() + { + return ParseBinOpRhs(0, ParsePrimaryExpression()); + } + + ShaderAst::ExpressionPtr Parser::ParseFloatingPointExpression(bool minus) + { + const Token& floatingPointToken = Expect(Advance(), TokenType::FloatingPointValue); + return ShaderBuilder::Constant(((minus) ? -1.f : 1.f) * float(std::get(floatingPointToken.data))); //< FIXME + } + + ShaderAst::ExpressionPtr Parser::ParseIdentifier() + { + const Token& identifierToken = Expect(Advance(), TokenType::Identifier); + const std::string& identifier = std::get(identifierToken.data); + + ShaderAst::ExpressionPtr identifierExpr = ShaderBuilder::Identifier(identifier); + + if (Peek().type == TokenType::Dot) + { + std::unique_ptr accessMemberNode = std::make_unique(); + accessMemberNode->structExpr = std::move(identifierExpr); + + do + { + Consume(); + + accessMemberNode->memberIdentifiers.push_back(ParseIdentifierAsName()); + } while (Peek().type == TokenType::Dot); + + identifierExpr = std::move(accessMemberNode); + } + + return identifierExpr; + } + + ShaderAst::ExpressionPtr Parser::ParseIntegerExpression(bool minus) + { + const Token& integerToken = Expect(Advance(), TokenType::IntegerValue); + return ShaderBuilder::Constant(((minus) ? -1 : 1) * static_cast(std::get(integerToken.data))); + } + + std::vector Parser::ParseParameters() + { Expect(Advance(), TokenType::OpenParenthesis); std::vector parameters; @@ -638,37 +744,37 @@ namespace Nz::ShaderLang first = false; parameters.push_back(ParseExpression()); } - + Expect(Advance(), TokenType::ClosingParenthesis); return parameters; - } - - ShaderAst::ExpressionPtr Parser::ParseParenthesisExpression() - { - Expect(Advance(), TokenType::OpenParenthesis); - ShaderAst::ExpressionPtr expression = ParseExpression(); - Expect(Advance(), TokenType::ClosingParenthesis); - - return expression; - } - - ShaderAst::ExpressionPtr Parser::ParsePrimaryExpression() - { - const Token& token = Peek(); - switch (token.type) - { - case TokenType::BoolFalse: - Consume(); - return ShaderBuilder::Constant(false); - - case TokenType::BoolTrue: - Consume(); - return ShaderBuilder::Constant(true); - - case TokenType::FloatingPointValue: - return ParseFloatingPointExpression(); - + } + + ShaderAst::ExpressionPtr Parser::ParseParenthesisExpression() + { + Expect(Advance(), TokenType::OpenParenthesis); + ShaderAst::ExpressionPtr expression = ParseExpression(); + Expect(Advance(), TokenType::ClosingParenthesis); + + return expression; + } + + ShaderAst::ExpressionPtr Parser::ParsePrimaryExpression() + { + const Token& token = Peek(); + switch (token.type) + { + case TokenType::BoolFalse: + Consume(); + return ShaderBuilder::Constant(false); + + case TokenType::BoolTrue: + Consume(); + return ShaderBuilder::Constant(true); + + case TokenType::FloatingPointValue: + return ParseFloatingPointExpression(); + case TokenType::Identifier: { const std::string& identifier = std::get(token.data); @@ -682,7 +788,7 @@ namespace Nz::ShaderLang } } - if (IsVariableInScope(identifier)) + if (IsVariableInScope(identifier)) { auto node = ParseIdentifier(); if (node->GetType() == ShaderAst::NodeType::AccessMemberIdentifierExpression) @@ -707,11 +813,11 @@ namespace Nz::ShaderLang ShaderAst::ExpressionType exprType = DecodeType(identifier); - return ShaderBuilder::Cast(std::move(exprType), ParseParameters()); - } - - case TokenType::IntegerValue: - return ParseIntegerExpression(); + return ShaderBuilder::Cast(std::move(exprType), ParseParameters()); + } + + case TokenType::IntegerValue: + return ParseIntegerExpression(); case TokenType::Minus: //< FIXME: Handle this with an unary node @@ -729,78 +835,78 @@ namespace Nz::ShaderLang throw UnexpectedToken{}; break; + + case TokenType::OpenParenthesis: + return ParseParenthesisExpression(); + + default: + throw UnexpectedToken{}; + } + } + + ShaderAst::AttributeType Parser::ParseIdentifierAsAttributeType() + { + const Token& identifierToken = Expect(Advance(), TokenType::Identifier); + const std::string& identifier = std::get(identifierToken.data); + + auto it = identifierToAttributeType.find(identifier); + if (it == identifierToAttributeType.end()) + throw UnknownAttribute{}; + + return it->second; + } + + const std::string& Parser::ParseIdentifierAsName() + { + const Token& identifierToken = Expect(Advance(), TokenType::Identifier); + const std::string& identifier = std::get(identifierToken.data); + + auto it = identifierToBasicType.find(identifier); + if (it != identifierToBasicType.end()) + throw ReservedKeyword{}; + + return identifier; + } + + ShaderAst::PrimitiveType Parser::ParsePrimitiveType() + { + const Token& identifierToken = Expect(Advance(), TokenType::Identifier); + const std::string& identifier = std::get(identifierToken.data); + + auto it = identifierToBasicType.find(identifier); + if (it == identifierToBasicType.end()) + throw UnknownType{}; + + return it->second; + } + + ShaderAst::ExpressionType Parser::ParseType() + { + // Handle () as no type + if (Peek().type == TokenType::OpenParenthesis) + { + Consume(); + Expect(Advance(), TokenType::ClosingParenthesis); + + return ShaderAst::NoType{}; + } + + const Token& identifierToken = Expect(Advance(), TokenType::Identifier); + const std::string& identifier = std::get(identifierToken.data); - case TokenType::OpenParenthesis: - return ParseParenthesisExpression(); - - default: - throw UnexpectedToken{}; - } - } - - ShaderAst::AttributeType Parser::ParseIdentifierAsAttributeType() - { - const Token& identifierToken = Expect(Advance(), TokenType::Identifier); - const std::string& identifier = std::get(identifierToken.data); - - auto it = identifierToAttributeType.find(identifier); - if (it == identifierToAttributeType.end()) - throw UnknownAttribute{}; - - return it->second; - } - - const std::string& Parser::ParseIdentifierAsName() - { - const Token& identifierToken = Expect(Advance(), TokenType::Identifier); - const std::string& identifier = std::get(identifierToken.data); - - auto it = identifierToBasicType.find(identifier); - if (it != identifierToBasicType.end()) - throw ReservedKeyword{}; - - return identifier; - } - - ShaderAst::PrimitiveType Parser::ParsePrimitiveType() - { - const Token& identifierToken = Expect(Advance(), TokenType::Identifier); - const std::string& identifier = std::get(identifierToken.data); - - auto it = identifierToBasicType.find(identifier); - if (it == identifierToBasicType.end()) - throw UnknownType{}; - - return it->second; - } - - ShaderAst::ExpressionType Parser::ParseType() - { - // Handle () as no type - if (Peek().type == TokenType::OpenParenthesis) - { - Consume(); - Expect(Advance(), TokenType::ClosingParenthesis); - - return ShaderAst::NoType{}; - } - - const Token& identifierToken = Expect(Advance(), TokenType::Identifier); - const std::string& identifier = std::get(identifierToken.data); - - return DecodeType(identifier); - } - - int Parser::GetTokenPrecedence(TokenType token) - { - switch (token) - { - case TokenType::Plus: return 20; - case TokenType::Divide: return 40; - case TokenType::Multiply: return 40; - case TokenType::Minus: return 20; - default: return -1; - } - } - -} + return DecodeType(identifier); + } + + int Parser::GetTokenPrecedence(TokenType token) + { + switch (token) + { + case TokenType::Plus: return 20; + case TokenType::Divide: return 40; + case TokenType::Multiply: return 40; + case TokenType::Minus: return 20; + default: return -1; + } + } + +} diff --git a/src/Nazara/Shader/SpirvWriter.cpp b/src/Nazara/Shader/SpirvWriter.cpp index 82a1d360c..af994659a 100644 --- a/src/Nazara/Shader/SpirvWriter.cpp +++ b/src/Nazara/Shader/SpirvWriter.cpp @@ -27,12 +27,6 @@ namespace Nz { namespace { - //FIXME: Have this only once - std::unordered_map s_entryPoints = { - { "frag", ShaderStageType::Fragment }, - { "vert", ShaderStageType::Vertex }, - }; - struct Builtin { const char* debugName; @@ -40,8 +34,8 @@ namespace Nz SpirvBuiltIn decoration; }; - std::unordered_map s_builtinMapping = { - { "position", { "VertexPosition", ShaderStageType::Vertex, SpirvBuiltIn::Position } } + std::unordered_map s_builtinMapping = { + { ShaderAst::BuiltinEntry::VertexPosition, { "VertexPosition", ShaderStageType::Vertex, SpirvBuiltIn::Position } } }; class PreVisitor : public ShaderAst::AstScopedVisitor @@ -129,32 +123,13 @@ namespace Nz UniformVar& uniformVar = extVars[varIndex++]; uniformVar.pointerId = m_constantCache.Register(variable); - - for (const auto& [attributeType, attributeParam] : extVar.attributes) - { - if (attributeType == ShaderAst::AttributeType::Binding) - { - uniformVar.bindingIndex = std::get(attributeParam); - break; - } - } + uniformVar.bindingIndex = extVar.bindingIndex; } } void Visit(ShaderAst::DeclareFunctionStatement& node) override { - std::optional entryPointType; - for (auto& attribute : node.attributes) - { - if (attribute.type == ShaderAst::AttributeType::Entry) - { - auto it = s_entryPoints.find(std::get(attribute.args)); - assert(it != s_entryPoints.end()); - - entryPointType = it->second; - break; - } - } + std::optional entryPointType = node.entryStage; assert(node.funcIndex); std::size_t funcIndex = *node.funcIndex; @@ -325,29 +300,12 @@ namespace Nz UInt32 HandleEntryInOutType(ShaderStageType entryPointType, std::size_t funcIndex, const ShaderAst::StructDescription::StructMember& member, SpirvStorageClass storageClass) { - std::optional> builtinOpt; - std::optional attributeLocation; - for (const auto& [attributeType, attributeParam] : member.attributes) + if (member.builtin) { - if (attributeType == ShaderAst::AttributeType::Builtin) - { - auto it = s_builtinMapping.find(std::get(attributeParam)); - if (it != s_builtinMapping.end()) - { - builtinOpt = it->second; - break; - } - } - else if (attributeType == ShaderAst::AttributeType::Location) - { - attributeLocation = std::get(attributeParam); - break; - } - } + auto it = s_builtinMapping.find(*member.builtin); + assert(it != s_builtinMapping.end()); - if (builtinOpt) - { - Builtin& builtin = *builtinOpt; + Builtin& builtin = it->second; if ((builtin.compatibleStages & entryPointType) == 0) return 0; @@ -364,7 +322,7 @@ namespace Nz return varId; } - else if (attributeLocation) + else if (member.locationIndex) { SpirvConstantCache::Variable variable; variable.debugName = member.name; @@ -373,7 +331,7 @@ namespace Nz variable.type = m_constantCache.BuildPointerType(member.type, storageClass); UInt32 varId = m_constantCache.Register(variable); - locationDecorations[varId] = *attributeLocation; + locationDecorations[varId] = *member.locationIndex; return varId; } From 0f15387c6c8d6f6ef0a89315f13af48d8689dd36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 14 Apr 2021 17:49:16 +0200 Subject: [PATCH 099/278] Shader: Add ShaderAst::Clone free function --- include/Nazara/Shader/ShaderAstCloner.hpp | 3 +++ include/Nazara/Shader/ShaderAstCloner.inl | 13 ++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/include/Nazara/Shader/ShaderAstCloner.hpp b/include/Nazara/Shader/ShaderAstCloner.hpp index 33b6acf3a..08bb53227 100644 --- a/include/Nazara/Shader/ShaderAstCloner.hpp +++ b/include/Nazara/Shader/ShaderAstCloner.hpp @@ -81,6 +81,9 @@ namespace Nz::ShaderAst std::vector m_expressionStack; std::vector m_statementStack; }; + + inline ExpressionPtr Clone(ExpressionPtr& node); + inline StatementPtr Clone(StatementPtr& node); } #include diff --git a/include/Nazara/Shader/ShaderAstCloner.inl b/include/Nazara/Shader/ShaderAstCloner.inl index 1182f110d..20a829343 100644 --- a/include/Nazara/Shader/ShaderAstCloner.inl +++ b/include/Nazara/Shader/ShaderAstCloner.inl @@ -5,8 +5,19 @@ #include #include -namespace Nz +namespace Nz::ShaderAst { + inline ExpressionPtr Clone(ExpressionPtr& node) + { + AstCloner cloner; + return cloner.Clone(node); + } + + inline StatementPtr Clone(StatementPtr& node) + { + AstCloner cloner; + return cloner.Clone(node); + } } #include From b234134abc3cff482afeb05af56e5b266b557746 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 14 Apr 2021 17:56:33 +0200 Subject: [PATCH 100/278] Shader/ShaderLang: Add type inference for variable declaration --- examples/RenderTest/main.cpp | 4 ++-- include/Nazara/Shader/ShaderAstValidator.hpp | 1 + include/Nazara/Shader/ShaderBuilder.hpp | 1 + include/Nazara/Shader/ShaderBuilder.inl | 9 +++++++++ src/Nazara/Shader/ShaderAstValidator.cpp | 15 +++++++++++++++ src/Nazara/Shader/ShaderLangParser.cpp | 14 +++++++++----- 6 files changed, 37 insertions(+), 7 deletions(-) diff --git a/examples/RenderTest/main.cpp b/examples/RenderTest/main.cpp index 23a2c8cf9..5dcde7161 100644 --- a/examples/RenderTest/main.cpp +++ b/examples/RenderTest/main.cpp @@ -45,8 +45,8 @@ struct FragOut [[entry(frag)]] fn main(fragIn: VertOut) -> FragOut { - let lightDir: vec3 = vec3(0.0, -0.707, 0.707); - let lightFactor: f32 = dot(fragIn.normal, lightDir); + let lightDir = vec3(0.0, -0.707, 0.707); + let lightFactor = dot(fragIn.normal, lightDir); let fragOut: FragOut; fragOut.color = lightFactor * tex.Sample(fragIn.uv); diff --git a/include/Nazara/Shader/ShaderAstValidator.hpp b/include/Nazara/Shader/ShaderAstValidator.hpp index 9556eee0f..14a491682 100644 --- a/include/Nazara/Shader/ShaderAstValidator.hpp +++ b/include/Nazara/Shader/ShaderAstValidator.hpp @@ -49,6 +49,7 @@ namespace Nz::ShaderAst void Visit(DeclareExternalStatement& node) override; void Visit(DeclareFunctionStatement& node) override; void Visit(DeclareStructStatement& node) override; + void Visit(DeclareVariableStatement& node) override; void Visit(ExpressionStatement& node) override; void Visit(MultiStatement& node) override; diff --git a/include/Nazara/Shader/ShaderBuilder.hpp b/include/Nazara/Shader/ShaderBuilder.hpp index ed6b3f624..5f01128e3 100644 --- a/include/Nazara/Shader/ShaderBuilder.hpp +++ b/include/Nazara/Shader/ShaderBuilder.hpp @@ -70,6 +70,7 @@ namespace Nz::ShaderBuilder struct DeclareVariable { + inline std::unique_ptr operator()(std::string name, ShaderAst::ExpressionPtr initialValue) const; inline std::unique_ptr operator()(std::string name, ShaderAst::ExpressionType type, ShaderAst::ExpressionPtr initialValue = nullptr) const; }; diff --git a/include/Nazara/Shader/ShaderBuilder.inl b/include/Nazara/Shader/ShaderBuilder.inl index a034d35f9..f72c98dbe 100644 --- a/include/Nazara/Shader/ShaderBuilder.inl +++ b/include/Nazara/Shader/ShaderBuilder.inl @@ -128,6 +128,15 @@ namespace Nz::ShaderBuilder return declareStructNode; } + inline std::unique_ptr Nz::ShaderBuilder::Impl::DeclareVariable::operator()(std::string name, ShaderAst::ExpressionPtr initialValue) const + { + auto declareVariableNode = std::make_unique(); + declareVariableNode->varName = std::move(name); + declareVariableNode->initialExpression = std::move(initialValue); + + return declareVariableNode; + } + inline std::unique_ptr Nz::ShaderBuilder::Impl::DeclareVariable::operator()(std::string name, ShaderAst::ExpressionType type, ShaderAst::ExpressionPtr initialValue) const { auto declareVariableNode = std::make_unique(); diff --git a/src/Nazara/Shader/ShaderAstValidator.cpp b/src/Nazara/Shader/ShaderAstValidator.cpp index ed7dcff50..c979ff4b0 100644 --- a/src/Nazara/Shader/ShaderAstValidator.cpp +++ b/src/Nazara/Shader/ShaderAstValidator.cpp @@ -594,6 +594,21 @@ namespace Nz::ShaderAst AstScopedVisitor::Visit(node); } + void AstValidator::Visit(DeclareVariableStatement& node) + { + if (IsNoType(node.varType)) + { + if (!node.initialExpression) + throw AstError{ "variable must either have a type or an initial value" }; + + node.initialExpression->Visit(*this); + + node.varType = GetExpressionType(*node.initialExpression); + } + + AstScopedVisitor::Visit(node); + } + void AstValidator::Visit(ExpressionStatement& node) { MandatoryExpr(node.expression); diff --git a/src/Nazara/Shader/ShaderLangParser.cpp b/src/Nazara/Shader/ShaderLangParser.cpp index b0636f7be..6df94d266 100644 --- a/src/Nazara/Shader/ShaderLangParser.cpp +++ b/src/Nazara/Shader/ShaderLangParser.cpp @@ -637,15 +637,19 @@ namespace Nz::ShaderLang std::string variableName = ParseIdentifierAsName(); RegisterVariable(variableName); + + ShaderAst::ExpressionType variableType = ShaderAst::NoType{}; + if (Peek().type == TokenType::Colon) + { + Expect(Advance(), TokenType::Colon); - Expect(Advance(), TokenType::Colon); - - ShaderAst::ExpressionType variableType = ParseType(); + variableType = ParseType(); + } ShaderAst::ExpressionPtr expression; - if (Peek().type == TokenType::Assign) + if (IsNoType(variableType) || Peek().type == TokenType::Assign) { - Consume(); + Expect(Advance(), TokenType::Assign); expression = ParseExpression(); } From 4bca87b1cb044a47c19965bb29cac43da927eb51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 14 Apr 2021 17:58:15 +0200 Subject: [PATCH 101/278] Shader: Add IsExpression/IsStatement --- include/Nazara/Shader/ShaderNodes.hpp | 2 ++ include/Nazara/Shader/ShaderNodes.inl | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/include/Nazara/Shader/ShaderNodes.hpp b/include/Nazara/Shader/ShaderNodes.hpp index e5663c5d1..0e84c8d1f 100644 --- a/include/Nazara/Shader/ShaderNodes.hpp +++ b/include/Nazara/Shader/ShaderNodes.hpp @@ -296,6 +296,8 @@ namespace Nz::ShaderAst }; inline const ShaderAst::ExpressionType& GetExpressionType(ShaderAst::Expression& expr); + inline bool IsExpression(NodeType nodeType); + inline bool IsStatement(NodeType nodeType); } #include diff --git a/include/Nazara/Shader/ShaderNodes.inl b/include/Nazara/Shader/ShaderNodes.inl index d8b320b72..c9c3b875b 100644 --- a/include/Nazara/Shader/ShaderNodes.inl +++ b/include/Nazara/Shader/ShaderNodes.inl @@ -12,6 +12,30 @@ namespace Nz::ShaderAst assert(expr.cachedExpressionType); return expr.cachedExpressionType.value(); } + + inline bool IsExpression(NodeType nodeType) + { + switch (nodeType) + { +#define NAZARA_SHADERAST_EXPRESSION(Node) case NodeType::Node: return true; +#include + + default: + return false; + } + } + + inline bool IsStatement(NodeType nodeType) + { + switch (nodeType) + { +#define NAZARA_SHADERAST_STATEMENT(Node) case NodeType::Node: return true; +#include + + default: + return false; + } + } } #include From a90937eb4f58614b380969815f88b14fe96ee389 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 14 Apr 2021 18:00:06 +0200 Subject: [PATCH 102/278] Update ShaderNode --- include/Nazara/Shader/ShaderBuilder.hpp | 8 +- include/Nazara/Shader/ShaderBuilder.inl | 16 +- include/Nazara/Shader/ShaderNodes.hpp | 4 + src/ShaderNode/DataModels/BinOp.hpp | 20 +- src/ShaderNode/DataModels/BinOp.inl | 30 +- src/ShaderNode/DataModels/BoolValue.cpp | 2 +- src/ShaderNode/DataModels/BoolValue.hpp | 2 +- src/ShaderNode/DataModels/BufferField.cpp | 27 +- src/ShaderNode/DataModels/BufferField.hpp | 2 +- src/ShaderNode/DataModels/Cast.hpp | 2 +- src/ShaderNode/DataModels/Cast.inl | 27 +- src/ShaderNode/DataModels/CompOp.hpp | 28 +- src/ShaderNode/DataModels/CompOp.inl | 30 +- .../DataModels/ConditionalExpression.cpp | 4 +- .../DataModels/ConditionalExpression.hpp | 2 +- src/ShaderNode/DataModels/Discard.cpp | 9 +- src/ShaderNode/DataModels/Discard.hpp | 2 +- src/ShaderNode/DataModels/FloatValue.cpp | 2 +- src/ShaderNode/DataModels/FloatValue.hpp | 2 +- src/ShaderNode/DataModels/InputValue.cpp | 4 +- src/ShaderNode/DataModels/InputValue.hpp | 2 +- src/ShaderNode/DataModels/Mat4BinOp.hpp | 16 +- src/ShaderNode/DataModels/Mat4BinOp.inl | 26 +- src/ShaderNode/DataModels/Mat4VecMul.cpp | 6 +- src/ShaderNode/DataModels/Mat4VecMul.hpp | 2 +- src/ShaderNode/DataModels/OutputValue.cpp | 10 +- src/ShaderNode/DataModels/OutputValue.hpp | 2 +- .../DataModels/PositionOutputValue.cpp | 9 +- .../DataModels/PositionOutputValue.hpp | 2 +- src/ShaderNode/DataModels/SampleTexture.cpp | 8 +- src/ShaderNode/DataModels/SampleTexture.hpp | 2 +- src/ShaderNode/DataModels/ShaderNode.hpp | 2 +- src/ShaderNode/DataModels/TextureValue.cpp | 16 +- src/ShaderNode/DataModels/TextureValue.hpp | 2 +- src/ShaderNode/DataModels/VecComposition.hpp | 2 +- src/ShaderNode/DataModels/VecComposition.inl | 9 +- .../DataModels/VecDecomposition.cpp | 8 +- .../DataModels/VecDecomposition.hpp | 2 +- src/ShaderNode/DataModels/VecDot.cpp | 10 +- src/ShaderNode/DataModels/VecDot.hpp | 2 +- src/ShaderNode/DataModels/VecFloatMul.cpp | 6 +- src/ShaderNode/DataModels/VecFloatMul.hpp | 2 +- src/ShaderNode/DataModels/VecValue.hpp | 2 +- src/ShaderNode/DataModels/VecValue.inl | 2 +- src/ShaderNode/DataTypes/VecData.cpp | 18 - src/ShaderNode/DataTypes/VecData.hpp | 31 -- src/ShaderNode/ShaderGraph.cpp | 425 ++++++++++-------- src/ShaderNode/ShaderGraph.hpp | 11 +- src/ShaderNode/Widgets/CodeOutputWidget.cpp | 11 +- src/ShaderNode/Widgets/CodeOutputWidget.hpp | 1 - src/ShaderNode/Widgets/MainWindow.cpp | 5 +- src/ShaderNode/Widgets/MainWindow.hpp | 5 - 52 files changed, 439 insertions(+), 441 deletions(-) delete mode 100644 src/ShaderNode/DataTypes/VecData.cpp diff --git a/include/Nazara/Shader/ShaderBuilder.hpp b/include/Nazara/Shader/ShaderBuilder.hpp index 5f01128e3..502dbed73 100644 --- a/include/Nazara/Shader/ShaderBuilder.hpp +++ b/include/Nazara/Shader/ShaderBuilder.hpp @@ -89,10 +89,15 @@ namespace Nz::ShaderBuilder inline std::unique_ptr operator()(ShaderAst::IntrinsicType intrinsicType, std::vector parameters) const; }; + struct Multi + { + inline std::unique_ptr operator()(std::vector statements) const; + }; + template struct NoParam { - std::unique_ptr operator()() const; + inline std::unique_ptr operator()() const; }; struct Return @@ -121,6 +126,7 @@ namespace Nz::ShaderBuilder constexpr Impl::NoParam Discard; constexpr Impl::Identifier Identifier; constexpr Impl::Intrinsic Intrinsic; + constexpr Impl::Multi MultiStatement; constexpr Impl::NoParam NoOp; constexpr Impl::Return Return; constexpr Impl::Swizzle Swizzle; diff --git a/include/Nazara/Shader/ShaderBuilder.inl b/include/Nazara/Shader/ShaderBuilder.inl index f72c98dbe..d27cbd5fd 100644 --- a/include/Nazara/Shader/ShaderBuilder.inl +++ b/include/Nazara/Shader/ShaderBuilder.inl @@ -172,12 +172,12 @@ namespace Nz::ShaderBuilder return intrinsicExpression; } - inline std::unique_ptr Impl::Return::operator()(ShaderAst::ExpressionPtr expr) const + inline std::unique_ptr Impl::Multi::operator()(std::vector statements) const { - auto returnNode = std::make_unique(); - returnNode->returnExpr = std::move(expr); + auto multiStatement = std::make_unique(); + multiStatement->statements = std::move(statements); - return returnNode; + return multiStatement; } template @@ -186,6 +186,14 @@ namespace Nz::ShaderBuilder return std::make_unique(); } + inline std::unique_ptr Impl::Return::operator()(ShaderAst::ExpressionPtr expr) const + { + auto returnNode = std::make_unique(); + returnNode->returnExpr = std::move(expr); + + return returnNode; + } + inline std::unique_ptr Impl::Swizzle::operator()(ShaderAst::ExpressionPtr expression, std::vector swizzleComponents) const { auto swizzleNode = std::make_unique(); diff --git a/include/Nazara/Shader/ShaderNodes.hpp b/include/Nazara/Shader/ShaderNodes.hpp index 0e84c8d1f..5a6a2bae7 100644 --- a/include/Nazara/Shader/ShaderNodes.hpp +++ b/include/Nazara/Shader/ShaderNodes.hpp @@ -26,6 +26,10 @@ namespace Nz::ShaderAst class AstExpressionVisitor; class AstStatementVisitor; + struct Node; + + using NodePtr = std::unique_ptr; + struct NAZARA_SHADER_API Node { Node() = default; diff --git a/src/ShaderNode/DataModels/BinOp.hpp b/src/ShaderNode/DataModels/BinOp.hpp index a4ac0a189..e8dcfd8a1 100644 --- a/src/ShaderNode/DataModels/BinOp.hpp +++ b/src/ShaderNode/DataModels/BinOp.hpp @@ -7,14 +7,14 @@ #include #include -template +template class BinOp : public ShaderNode { public: BinOp(ShaderGraph& graph); ~BinOp() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; virtual QString GetOperationString() const = 0; @@ -45,40 +45,40 @@ class BinOp : public ShaderNode template -class BinAdd : public BinOp +class BinAdd : public BinOp { public: - using BinOp::BinOp; + using BinOp::BinOp; void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; QString GetOperationString() const final; }; template -class BinMul : public BinOp +class BinMul : public BinOp { public: - using BinOp::BinOp; + using BinOp::BinOp; void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; QString GetOperationString() const final; }; template -class BinSub : public BinOp +class BinSub : public BinOp { public: - using BinOp::BinOp; + using BinOp::BinOp; void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; QString GetOperationString() const final; }; template -class BinDiv : public BinOp +class BinDiv : public BinOp { public: - using BinOp::BinOp; + using BinOp::BinOp; void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; QString GetOperationString() const final; diff --git a/src/ShaderNode/DataModels/BinOp.inl b/src/ShaderNode/DataModels/BinOp.inl index 10031254c..b91999e18 100644 --- a/src/ShaderNode/DataModels/BinOp.inl +++ b/src/ShaderNode/DataModels/BinOp.inl @@ -1,25 +1,23 @@ #include #include -template +template BinOp::BinOp(ShaderGraph& graph) : ShaderNode(graph) { UpdateOutput(); } -template -Nz::ShaderNodes::NodePtr BinOp::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +template +Nz::ShaderAst::NodePtr BinOp::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == 2); assert(outputIndex == 0); - using BuilderType = typename Nz::ShaderBuilder::template BinOpBuilder; - constexpr BuilderType builder; - return builder(expressions[0], expressions[1]); + return Nz::ShaderBuilder::Binary(Op, std::move(expressions[0]), std::move(expressions[1])); } -template +template QtNodes::NodeDataType BinOp::dataType(QtNodes::PortType /*portType*/, QtNodes::PortIndex portIndex) const { assert(portIndex == 0 || portIndex == 1); @@ -27,7 +25,7 @@ QtNodes::NodeDataType BinOp::dataType(QtNodes::PortType /*portType return DataType::Type(); } -template +template unsigned int BinOp::nPorts(QtNodes::PortType portType) const { switch (portType) @@ -41,14 +39,14 @@ unsigned int BinOp::nPorts(QtNodes::PortType portType) const throw std::runtime_error("invalid port type"); } -template +template std::shared_ptr BinOp::outData(QtNodes::PortIndex port) { assert(port == 0); return m_output; } -template +template QString BinOp::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const { switch (portType) @@ -81,14 +79,14 @@ QString BinOp::portCaption(QtNodes::PortType portType, QtNodes::Po return QString{}; } -template +template bool BinOp::portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const { assert(portIndex == 0 || portIndex == 1); return portType == QtNodes::PortType::In || portType == QtNodes::PortType::Out; } -template +template void BinOp::setInData(std::shared_ptr value, int index) { assert(index == 0 || index == 1); @@ -105,7 +103,7 @@ void BinOp::setInData(std::shared_ptr value, in UpdateOutput(); } -template +template QtNodes::NodeValidationState BinOp::validationState() const { if (!m_lhs || !m_rhs) @@ -120,7 +118,7 @@ QtNodes::NodeValidationState BinOp::validationState() const return QtNodes::NodeValidationState::Valid; } -template +template QString BinOp::validationMessage() const { if (!m_lhs || !m_rhs) @@ -135,7 +133,7 @@ QString BinOp::validationMessage() const return QString(); } -template +template bool BinOp::ComputePreview(QPixmap& pixmap) { if (!m_lhs || !m_rhs) @@ -145,7 +143,7 @@ bool BinOp::ComputePreview(QPixmap& pixmap) return true; } -template +template void BinOp::UpdateOutput() { if (validationState() != QtNodes::NodeValidationState::Valid) diff --git a/src/ShaderNode/DataModels/BoolValue.cpp b/src/ShaderNode/DataModels/BoolValue.cpp index 940d8f0fb..2e06c627e 100644 --- a/src/ShaderNode/DataModels/BoolValue.cpp +++ b/src/ShaderNode/DataModels/BoolValue.cpp @@ -89,7 +89,7 @@ void BoolValue::BuildNodeEdition(QFormLayout* layout) layout->addRow(tr("Value"), checkbox); } -Nz::ShaderNodes::NodePtr BoolValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr BoolValue::BuildNode(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count, std::size_t outputIndex) const { assert(count == 0); assert(outputIndex == 0); diff --git a/src/ShaderNode/DataModels/BoolValue.hpp b/src/ShaderNode/DataModels/BoolValue.hpp index d3e664d9d..8e906e97b 100644 --- a/src/ShaderNode/DataModels/BoolValue.hpp +++ b/src/ShaderNode/DataModels/BoolValue.hpp @@ -17,7 +17,7 @@ class BoolValue : public ShaderNode BoolValue(ShaderGraph& graph); ~BoolValue() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; void BuildNodeEdition(QFormLayout* layout) override; QString caption() const override; diff --git a/src/ShaderNode/DataModels/BufferField.cpp b/src/ShaderNode/DataModels/BufferField.cpp index 6f2c506fe..b191aeba4 100644 --- a/src/ShaderNode/DataModels/BufferField.cpp +++ b/src/ShaderNode/DataModels/BufferField.cpp @@ -49,7 +49,7 @@ ShaderNode(graph) UpdatePreview(); } -Nz::ShaderNodes::NodePtr BufferField::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr BufferField::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == 0); assert(outputIndex == 0); @@ -62,23 +62,13 @@ Nz::ShaderNodes::NodePtr BufferField::BuildNode(Nz::ShaderNodes::ExpressionPtr* const auto& bufferEntry = graph.GetBuffer(*m_currentBufferIndex); const auto& structEntry = graph.GetStruct(bufferEntry.structIndex); - Nz::ShaderNodes::VariablePtr varPtr; - switch (bufferEntry.type) - { - case BufferType::UniformBufferObject: - varPtr = Nz::ShaderBuilder::Uniform(bufferEntry.name, structEntry.name); - break; - } - - assert(varPtr); - assert(m_currentFieldIndex); const CurrentField& currentField = *m_currentFieldIndex; - Nz::ShaderNodes::ExpressionPtr sourceExpr = Nz::ShaderBuilder::Identifier(varPtr); + Nz::ShaderAst::ExpressionPtr sourceExpr = Nz::ShaderBuilder::Identifier(bufferEntry.name); - std::vector memberIndices; - memberIndices.reserve(currentField.nestedFields.size() + 1); + std::vector memberIdentifiers; + memberIdentifiers.reserve(currentField.nestedFields.size() + 1); const ShaderGraph::StructEntry* sourceStruct = &structEntry; for (std::size_t nestedIndex : currentField.nestedFields) @@ -90,16 +80,17 @@ Nz::ShaderNodes::NodePtr BufferField::BuildNode(Nz::ShaderNodes::ExpressionPtr* std::size_t nestedStructIndex = std::get(memberEntry.type); sourceStruct = &graph.GetStruct(nestedStructIndex); - memberIndices.push_back(nestedIndex); + memberIdentifiers.push_back(memberEntry.name); } - memberIndices.push_back(currentField.finalFieldIndex); - assert(currentField.finalFieldIndex < sourceStruct->members.size()); const auto& memberEntry = sourceStruct->members[currentField.finalFieldIndex]; assert(std::holds_alternative(memberEntry.type)); - return Nz::ShaderBuilder::AccessMember(std::move(sourceExpr), std::move(memberIndices), graph.ToShaderExpressionType(std::get(memberEntry.type))); + memberIdentifiers.push_back(memberEntry.name); + + using namespace Nz; + return ShaderBuilder::AccessMember(std::move(sourceExpr), std::move(memberIdentifiers)); } unsigned int BufferField::nPorts(QtNodes::PortType portType) const diff --git a/src/ShaderNode/DataModels/BufferField.hpp b/src/ShaderNode/DataModels/BufferField.hpp index 7e5e46be4..eed42d9e1 100644 --- a/src/ShaderNode/DataModels/BufferField.hpp +++ b/src/ShaderNode/DataModels/BufferField.hpp @@ -15,7 +15,7 @@ class BufferField : public ShaderNode BufferField(ShaderGraph& graph); ~BufferField() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; void BuildNodeEdition(QFormLayout* layout) override; QString caption() const override { return "BufferField"; } diff --git a/src/ShaderNode/DataModels/Cast.hpp b/src/ShaderNode/DataModels/Cast.hpp index ea3303dd3..47f954f81 100644 --- a/src/ShaderNode/DataModels/Cast.hpp +++ b/src/ShaderNode/DataModels/Cast.hpp @@ -17,7 +17,7 @@ class CastVec : public ShaderNode CastVec(ShaderGraph& graph); ~CastVec() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const; void BuildNodeEdition(QFormLayout* layout) override; QString caption() const override; diff --git a/src/ShaderNode/DataModels/Cast.inl b/src/ShaderNode/DataModels/Cast.inl index a8e932fed..f52efbb74 100644 --- a/src/ShaderNode/DataModels/Cast.inl +++ b/src/ShaderNode/DataModels/Cast.inl @@ -18,7 +18,7 @@ ShaderNode(graph) } template -Nz::ShaderNodes::NodePtr CastVec::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr CastVec::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(m_input); assert(count == 1); @@ -30,29 +30,27 @@ Nz::ShaderNodes::NodePtr CastVec::BuildNode(Nz::ShaderNodes::E { std::size_t overflowComponentCount = ToComponentCount - fromComponentCount; - std::array expr; - expr[0] = expressions[0]; + std::vector params; + params.emplace_back(std::move(params[0])); for (std::size_t i = 0; i < overflowComponentCount; ++i) - expr[i + 1] = Nz::ShaderBuilder::Constant(m_overflowComponents[i]); + params.emplace_back(Nz::ShaderBuilder::Constant(m_overflowComponents[i])); - constexpr auto ExpressionType = VecExpressionType; - - return Nz::ShaderBuilder::Cast(expr.data(), 1 + overflowComponentCount); + return Nz::ShaderBuilder::Cast(Nz::ShaderAst::VectorType{ ToComponentCount, Nz::ShaderAst::PrimitiveType::Float32 }, std::move(params)); } else if (ToComponentCount < fromComponentCount) { - std::array swizzleComponents; + std::array swizzleComponents; for (std::size_t i = 0; i < ToComponentCount; ++i) - swizzleComponents[i] = static_cast(static_cast(Nz::ShaderNodes::SwizzleComponent::First) + i); + swizzleComponents[i] = static_cast(static_cast(Nz::ShaderAst::SwizzleComponent::First) + i); return std::apply([&](auto... components) - { - std::initializer_list componentList{ components... }; - return Nz::ShaderBuilder::Swizzle(expressions[0], componentList); - }, swizzleComponents); + { + std::initializer_list componentList{ components... }; + return Nz::ShaderBuilder::Swizzle(std::move(expressions[0]), componentList); + }, swizzleComponents); } else - return expressions[0]; //< no-op + return std::move(expressions[0]); //< no-op } template @@ -110,6 +108,7 @@ QtNodes::NodeDataType CastVec::dataType(QtNodes::PortType port { case QtNodes::PortType::In: return VecData::Type(); case QtNodes::PortType::Out: return VecData::Type(); + default: break; } assert(false); diff --git a/src/ShaderNode/DataModels/CompOp.hpp b/src/ShaderNode/DataModels/CompOp.hpp index cb7da53e4..134fe87ca 100644 --- a/src/ShaderNode/DataModels/CompOp.hpp +++ b/src/ShaderNode/DataModels/CompOp.hpp @@ -8,14 +8,14 @@ #include #include -template +template class CompOp : public ShaderNode { public: CompOp(ShaderGraph& graph); ~CompOp() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; virtual QString GetOperationString() const = 0; @@ -46,60 +46,60 @@ class CompOp : public ShaderNode template -class CompEq : public CompOp +class CompEq : public CompOp { public: - using CompOp::CompOp; + using CompOp::CompOp; void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; QString GetOperationString() const final; }; template -class CompGe : public CompOp +class CompGe : public CompOp { public: - using CompOp::CompOp; + using CompOp::CompOp; void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; QString GetOperationString() const final; }; template -class CompGt : public CompOp +class CompGt : public CompOp { public: - using CompOp::CompOp; + using CompOp::CompOp; void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; QString GetOperationString() const final; }; template -class CompLe : public CompOp +class CompLe : public CompOp { public: - using CompOp::CompOp; + using CompOp::CompOp; void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; QString GetOperationString() const final; }; template -class CompLt : public CompOp +class CompLt : public CompOp { public: - using CompOp::CompOp; + using CompOp::CompOp; void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; QString GetOperationString() const final; }; template -class CompNe : public CompOp +class CompNe : public CompOp { public: - using CompOp::CompOp; + using CompOp::CompOp; void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; QString GetOperationString() const final; diff --git a/src/ShaderNode/DataModels/CompOp.inl b/src/ShaderNode/DataModels/CompOp.inl index 4ca0a122e..ba4b55ad8 100644 --- a/src/ShaderNode/DataModels/CompOp.inl +++ b/src/ShaderNode/DataModels/CompOp.inl @@ -1,25 +1,23 @@ #include #include -template +template CompOp::CompOp(ShaderGraph& graph) : ShaderNode(graph) { UpdateOutput(); } -template -Nz::ShaderNodes::NodePtr CompOp::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +template +Nz::ShaderAst::NodePtr CompOp::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == 2); assert(outputIndex == 0); - using BuilderType = typename Nz::ShaderBuilder::template BinOpBuilder; - constexpr BuilderType builder; - return builder(expressions[0], expressions[1]); + return Nz::ShaderBuilder::Binary(Op, std::move(expressions[0]), std::move(expressions[1])); } -template +template QtNodes::NodeDataType CompOp::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const { switch (portType) @@ -43,7 +41,7 @@ QtNodes::NodeDataType CompOp::dataType(QtNodes::PortType portType, throw std::runtime_error("invalid port type"); } -template +template unsigned int CompOp::nPorts(QtNodes::PortType portType) const { switch (portType) @@ -57,14 +55,14 @@ unsigned int CompOp::nPorts(QtNodes::PortType portType) const throw std::runtime_error("invalid port type"); } -template +template std::shared_ptr CompOp::outData(QtNodes::PortIndex port) { assert(port == 0); return m_output; } -template +template QString CompOp::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const { switch (portType) @@ -97,14 +95,14 @@ QString CompOp::portCaption(QtNodes::PortType portType, QtNodes::P return QString{}; } -template +template bool CompOp::portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const { assert(portIndex == 0 || portIndex == 1); return portType == QtNodes::PortType::In || portType == QtNodes::PortType::Out; } -template +template void CompOp::setInData(std::shared_ptr value, int index) { assert(index == 0 || index == 1); @@ -121,7 +119,7 @@ void CompOp::setInData(std::shared_ptr value, i UpdateOutput(); } -template +template QtNodes::NodeValidationState CompOp::validationState() const { if (!m_lhs || !m_rhs) @@ -136,7 +134,7 @@ QtNodes::NodeValidationState CompOp::validationState() const return QtNodes::NodeValidationState::Valid; } -template +template QString CompOp::validationMessage() const { if (!m_lhs || !m_rhs) @@ -151,7 +149,7 @@ QString CompOp::validationMessage() const return QString(); } -template +template bool CompOp::ComputePreview(QPixmap& pixmap) { if (!m_lhs || !m_rhs) @@ -161,7 +159,7 @@ bool CompOp::ComputePreview(QPixmap& pixmap) return true; } -template +template void CompOp::UpdateOutput() { if (validationState() != QtNodes::NodeValidationState::Valid) diff --git a/src/ShaderNode/DataModels/ConditionalExpression.cpp b/src/ShaderNode/DataModels/ConditionalExpression.cpp index 27224e8d6..3b49f2237 100644 --- a/src/ShaderNode/DataModels/ConditionalExpression.cpp +++ b/src/ShaderNode/DataModels/ConditionalExpression.cpp @@ -35,7 +35,7 @@ ShaderNode(graph) UpdatePreview(); } -Nz::ShaderNodes::NodePtr ConditionalExpression::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr ConditionalExpression::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == 2); assert(outputIndex == 0); @@ -46,7 +46,7 @@ Nz::ShaderNodes::NodePtr ConditionalExpression::BuildNode(Nz::ShaderNodes::Expre const ShaderGraph& graph = GetGraph(); const auto& conditionEntry = graph.GetCondition(*m_currentConditionIndex); - return Nz::ShaderBuilder::ConditionalExpression(conditionEntry.name, expressions[0], expressions[1]); + return Nz::ShaderBuilder::ConditionalExpression(conditionEntry.name, std::move(expressions[0]), std::move(expressions[1])); } QString ConditionalExpression::caption() const diff --git a/src/ShaderNode/DataModels/ConditionalExpression.hpp b/src/ShaderNode/DataModels/ConditionalExpression.hpp index 1c732243d..a2bd1eb3a 100644 --- a/src/ShaderNode/DataModels/ConditionalExpression.hpp +++ b/src/ShaderNode/DataModels/ConditionalExpression.hpp @@ -15,7 +15,7 @@ class ConditionalExpression : public ShaderNode ConditionalExpression(ShaderGraph& graph); ~ConditionalExpression() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; void BuildNodeEdition(QFormLayout* layout) override; QString caption() const override; diff --git a/src/ShaderNode/DataModels/Discard.cpp b/src/ShaderNode/DataModels/Discard.cpp index 968e8d53c..aa3035155 100644 --- a/src/ShaderNode/DataModels/Discard.cpp +++ b/src/ShaderNode/DataModels/Discard.cpp @@ -16,14 +16,15 @@ ShaderNode(graph) DisableCustomVariableName(); } -Nz::ShaderNodes::NodePtr Discard::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr Discard::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { - using namespace Nz::ShaderBuilder; - assert(count == 1); assert(outputIndex == 0); - return Branch(Equal(expressions[0], Constant(true)), Nz::ShaderBuilder::Discard(), nullptr); + using namespace Nz; + + auto condition = ShaderBuilder::Binary(ShaderAst::BinaryType::CompEq, std::move(expressions[0]), ShaderBuilder::Constant(true)); + return ShaderBuilder::Branch(std::move(condition), ShaderBuilder::Discard()); } int Discard::GetOutputOrder() const diff --git a/src/ShaderNode/DataModels/Discard.hpp b/src/ShaderNode/DataModels/Discard.hpp index 55f6be153..91f88edea 100644 --- a/src/ShaderNode/DataModels/Discard.hpp +++ b/src/ShaderNode/DataModels/Discard.hpp @@ -14,7 +14,7 @@ class Discard : public ShaderNode public: Discard(ShaderGraph& graph); - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; int GetOutputOrder() const; QString caption() const override { return "Discard"; } diff --git a/src/ShaderNode/DataModels/FloatValue.cpp b/src/ShaderNode/DataModels/FloatValue.cpp index 4efc10585..49513baa6 100644 --- a/src/ShaderNode/DataModels/FloatValue.cpp +++ b/src/ShaderNode/DataModels/FloatValue.cpp @@ -89,7 +89,7 @@ void FloatValue::BuildNodeEdition(QFormLayout* layout) layout->addRow(tr("Value"), spinbox); } -Nz::ShaderNodes::NodePtr FloatValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr FloatValue::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == 0); assert(outputIndex == 0); diff --git a/src/ShaderNode/DataModels/FloatValue.hpp b/src/ShaderNode/DataModels/FloatValue.hpp index 6dfb110f8..722ee44ca 100644 --- a/src/ShaderNode/DataModels/FloatValue.hpp +++ b/src/ShaderNode/DataModels/FloatValue.hpp @@ -17,7 +17,7 @@ class FloatValue : public ShaderNode FloatValue(ShaderGraph& graph); ~FloatValue() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; void BuildNodeEdition(QFormLayout* layout) override; QString caption() const override; diff --git a/src/ShaderNode/DataModels/InputValue.cpp b/src/ShaderNode/DataModels/InputValue.cpp index f6926278b..51dc4953b 100644 --- a/src/ShaderNode/DataModels/InputValue.cpp +++ b/src/ShaderNode/DataModels/InputValue.cpp @@ -109,7 +109,7 @@ void InputValue::BuildNodeEdition(QFormLayout* layout) layout->addRow(tr("Input"), inputSelection); } -Nz::ShaderNodes::NodePtr InputValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr InputValue::BuildNode(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count, std::size_t outputIndex) const { assert(count == 0); assert(outputIndex == 0); @@ -118,7 +118,7 @@ Nz::ShaderNodes::NodePtr InputValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* / throw std::runtime_error("no input"); const auto& inputEntry = GetGraph().GetInput(*m_currentInputIndex); - return Nz::ShaderBuilder::Identifier(Nz::ShaderBuilder::Input(inputEntry.name, ShaderGraph::ToShaderExpressionType(inputEntry.type))); + return Nz::ShaderBuilder::AccessMember(Nz::ShaderBuilder::Identifier("input"), { inputEntry.name }); } auto InputValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const -> QtNodes::NodeDataType diff --git a/src/ShaderNode/DataModels/InputValue.hpp b/src/ShaderNode/DataModels/InputValue.hpp index 9863d7b98..63cbf197c 100644 --- a/src/ShaderNode/DataModels/InputValue.hpp +++ b/src/ShaderNode/DataModels/InputValue.hpp @@ -19,7 +19,7 @@ class InputValue : public ShaderNode void BuildNodeEdition(QFormLayout* layout) override; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override { return "Input"; } QString name() const override { return "Input"; } diff --git a/src/ShaderNode/DataModels/Mat4BinOp.hpp b/src/ShaderNode/DataModels/Mat4BinOp.hpp index 1d6d71eee..e752b21a4 100644 --- a/src/ShaderNode/DataModels/Mat4BinOp.hpp +++ b/src/ShaderNode/DataModels/Mat4BinOp.hpp @@ -6,14 +6,14 @@ #include #include -template +template class Mat4BinOp : public ShaderNode { public: Mat4BinOp(ShaderGraph& graph); ~Mat4BinOp() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const; unsigned int nPorts(QtNodes::PortType portType) const override; @@ -35,28 +35,28 @@ class Mat4BinOp : public ShaderNode std::shared_ptr m_output; }; -class Mat4Add : public Mat4BinOp +class Mat4Add : public Mat4BinOp { public: - using Mat4BinOp::Mat4BinOp; + using Mat4BinOp::Mat4BinOp; QString caption() const override; QString name() const override; }; -class Mat4Mul : public Mat4BinOp +class Mat4Mul : public Mat4BinOp { public: - using Mat4BinOp::Mat4BinOp; + using Mat4BinOp::Mat4BinOp; QString caption() const override; QString name() const override; }; -class Mat4Sub : public Mat4BinOp +class Mat4Sub : public Mat4BinOp { public: - using Mat4BinOp::Mat4BinOp; + using Mat4BinOp::Mat4BinOp; QString caption() const override; QString name() const override; diff --git a/src/ShaderNode/DataModels/Mat4BinOp.inl b/src/ShaderNode/DataModels/Mat4BinOp.inl index 50c4102e4..894328be9 100644 --- a/src/ShaderNode/DataModels/Mat4BinOp.inl +++ b/src/ShaderNode/DataModels/Mat4BinOp.inl @@ -1,25 +1,23 @@ #include #include -template +template Mat4BinOp::Mat4BinOp(ShaderGraph& graph) : ShaderNode(graph) { UpdateOutput(); } -template -Nz::ShaderNodes::NodePtr Mat4BinOp::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +template +Nz::ShaderAst::NodePtr Mat4BinOp::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == 2); assert(outputIndex == 0); - using BuilderType = typename Nz::ShaderBuilder::template BinOpBuilder; - constexpr BuilderType builder; - return builder(expressions[0], expressions[1]); + return Nz::ShaderBuilder::Binary(Op, std::move(expressions[0]), std::move(expressions[1])); } -template +template QtNodes::NodeDataType Mat4BinOp::dataType(QtNodes::PortType /*portType*/, QtNodes::PortIndex portIndex) const { assert(portIndex == 0 || portIndex == 1); @@ -27,7 +25,7 @@ QtNodes::NodeDataType Mat4BinOp::dataType(QtNodes::PortType /*portType*/, Qt return Matrix4Data::Type(); } -template +template unsigned int Mat4BinOp::nPorts(QtNodes::PortType portType) const { switch (portType) @@ -41,14 +39,14 @@ unsigned int Mat4BinOp::nPorts(QtNodes::PortType portType) const throw std::runtime_error("invalid port type"); } -template +template std::shared_ptr Mat4BinOp::outData(QtNodes::PortIndex port) { assert(port == 0); return m_output; } -template +template void Mat4BinOp::setInData(std::shared_ptr value, int index) { assert(index == 0 || index == 1); @@ -68,7 +66,7 @@ void Mat4BinOp::setInData(std::shared_ptr value, int inde UpdateOutput(); } -template +template QtNodes::NodeValidationState Mat4BinOp::validationState() const { if (!m_lhs || !m_rhs) @@ -77,7 +75,7 @@ QtNodes::NodeValidationState Mat4BinOp::validationState() const return QtNodes::NodeValidationState::Valid; } -template +template QString Mat4BinOp::validationMessage() const { if (!m_lhs || !m_rhs) @@ -86,7 +84,7 @@ QString Mat4BinOp::validationMessage() const return QString(); } -template +template bool Mat4BinOp::ComputePreview(QPixmap& pixmap) { if (!m_lhs || !m_rhs) @@ -98,7 +96,7 @@ bool Mat4BinOp::ComputePreview(QPixmap& pixmap) //return true; } -template +template void Mat4BinOp::UpdateOutput() { if (validationState() != QtNodes::NodeValidationState::Valid) diff --git a/src/ShaderNode/DataModels/Mat4VecMul.cpp b/src/ShaderNode/DataModels/Mat4VecMul.cpp index 426c0bde1..f859166c1 100644 --- a/src/ShaderNode/DataModels/Mat4VecMul.cpp +++ b/src/ShaderNode/DataModels/Mat4VecMul.cpp @@ -1,4 +1,5 @@ #include +#include #include Mat4VecMul::Mat4VecMul(ShaderGraph& graph) : @@ -7,13 +8,12 @@ ShaderNode(graph) UpdateOutput(); } -Nz::ShaderNodes::NodePtr Mat4VecMul::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr Mat4VecMul::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == 2); assert(outputIndex == 0); - using namespace Nz::ShaderNodes; - return BinaryOp::Build(BinaryType::Multiply, expressions[0], expressions[1]); + return Nz::ShaderBuilder::Binary(Nz::ShaderAst::BinaryType::Multiply, std::move(expressions[0]), std::move(expressions[1])); } QString Mat4VecMul::caption() const diff --git a/src/ShaderNode/DataModels/Mat4VecMul.hpp b/src/ShaderNode/DataModels/Mat4VecMul.hpp index d3b25b3b1..76debc88f 100644 --- a/src/ShaderNode/DataModels/Mat4VecMul.hpp +++ b/src/ShaderNode/DataModels/Mat4VecMul.hpp @@ -13,7 +13,7 @@ class Mat4VecMul : public ShaderNode Mat4VecMul(ShaderGraph& graph); ~Mat4VecMul() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override; QString name() const override; diff --git a/src/ShaderNode/DataModels/OutputValue.cpp b/src/ShaderNode/DataModels/OutputValue.cpp index 22d4bfb72..e3471fff8 100644 --- a/src/ShaderNode/DataModels/OutputValue.cpp +++ b/src/ShaderNode/DataModels/OutputValue.cpp @@ -54,11 +54,8 @@ void OutputValue::BuildNodeEdition(QFormLayout* layout) layout->addRow(tr("Output"), outputSelection); } -Nz::ShaderNodes::NodePtr OutputValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr OutputValue::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { - using namespace Nz::ShaderBuilder; - using namespace Nz::ShaderNodes; - assert(count == 1); assert(outputIndex == 0); @@ -66,9 +63,10 @@ Nz::ShaderNodes::NodePtr OutputValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* throw std::runtime_error("no output"); const auto& outputEntry = GetGraph().GetOutput(*m_currentOutputIndex); - auto output = Nz::ShaderBuilder::Identifier(Nz::ShaderBuilder::Output(outputEntry.name, ShaderGraph::ToShaderExpressionType(outputEntry.type))); + auto output = Nz::ShaderBuilder::AccessMember(Nz::ShaderBuilder::Identifier("output"), { outputEntry.name }); - return Nz::ShaderBuilder::Assign(std::move(output), *expressions); + using namespace Nz; + return Nz::ShaderBuilder::Assign(ShaderAst::AssignType::Simple, std::move(output), std::move(expressions[0])); } std::shared_ptr OutputValue::outData(QtNodes::PortIndex /*port*/) diff --git a/src/ShaderNode/DataModels/OutputValue.hpp b/src/ShaderNode/DataModels/OutputValue.hpp index e798b7e82..a44284e1a 100644 --- a/src/ShaderNode/DataModels/OutputValue.hpp +++ b/src/ShaderNode/DataModels/OutputValue.hpp @@ -16,7 +16,7 @@ class OutputValue : public ShaderNode void BuildNodeEdition(QFormLayout* layout) override; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override { return "Output"; } QString name() const override { return "Output"; } diff --git a/src/ShaderNode/DataModels/PositionOutputValue.cpp b/src/ShaderNode/DataModels/PositionOutputValue.cpp index 2f9f59716..14745fb45 100644 --- a/src/ShaderNode/DataModels/PositionOutputValue.cpp +++ b/src/ShaderNode/DataModels/PositionOutputValue.cpp @@ -14,16 +14,15 @@ ShaderNode(graph) DisableCustomVariableName(); } -Nz::ShaderNodes::NodePtr PositionOutputValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr PositionOutputValue::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { - using namespace Nz::ShaderBuilder; - using namespace Nz::ShaderNodes; + using namespace Nz; assert(count == 1); assert(outputIndex == 0); - auto output = Nz::ShaderBuilder::Identifier(Nz::ShaderBuilder::Builtin(BuiltinEntry::VertexPosition)); - return Nz::ShaderBuilder::Assign(std::move(output), *expressions); + auto output = Nz::ShaderBuilder::AccessMember(Nz::ShaderBuilder::Identifier("OutputData"), { "position" }); + return ShaderBuilder::Assign(ShaderAst::AssignType::Simple, std::move(output), std::move(expressions[0])); } QtNodes::NodeDataType PositionOutputValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const diff --git a/src/ShaderNode/DataModels/PositionOutputValue.hpp b/src/ShaderNode/DataModels/PositionOutputValue.hpp index 6626226e4..1cb8ed8ef 100644 --- a/src/ShaderNode/DataModels/PositionOutputValue.hpp +++ b/src/ShaderNode/DataModels/PositionOutputValue.hpp @@ -14,7 +14,7 @@ class PositionOutputValue : public ShaderNode public: PositionOutputValue(ShaderGraph& graph); - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override { return "PositionOutputValue"; } QString name() const override { return "PositionOutputValue"; } diff --git a/src/ShaderNode/DataModels/SampleTexture.cpp b/src/ShaderNode/DataModels/SampleTexture.cpp index 4d7fcddee..7a697f7a7 100644 --- a/src/ShaderNode/DataModels/SampleTexture.cpp +++ b/src/ShaderNode/DataModels/SampleTexture.cpp @@ -71,14 +71,18 @@ bool SampleTexture::ComputePreview(QPixmap& pixmap) return true; } -Nz::ShaderNodes::NodePtr SampleTexture::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr SampleTexture::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(m_texture); assert(m_uv); assert(count == 2); assert(outputIndex == 0); - return Nz::ShaderBuilder::Sample2D(expressions[0], expressions[1]); + std::vector params; + params.push_back(std::move(expressions[0])); + params.push_back(std::move(expressions[1])); + + return Nz::ShaderBuilder::Intrinsic(Nz::ShaderAst::IntrinsicType::SampleTexture, std::move(params)); } auto SampleTexture::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const -> QtNodes::NodeDataType diff --git a/src/ShaderNode/DataModels/SampleTexture.hpp b/src/ShaderNode/DataModels/SampleTexture.hpp index d819a0df0..d09c71521 100644 --- a/src/ShaderNode/DataModels/SampleTexture.hpp +++ b/src/ShaderNode/DataModels/SampleTexture.hpp @@ -17,7 +17,7 @@ class SampleTexture : public ShaderNode SampleTexture(ShaderGraph& graph); ~SampleTexture() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override { return "Sample texture"; } QString name() const override { return "SampleTexture"; } diff --git a/src/ShaderNode/DataModels/ShaderNode.hpp b/src/ShaderNode/DataModels/ShaderNode.hpp index d3b200768..eeb8d0b3e 100644 --- a/src/ShaderNode/DataModels/ShaderNode.hpp +++ b/src/ShaderNode/DataModels/ShaderNode.hpp @@ -18,7 +18,7 @@ class ShaderNode : public QtNodes::NodeDataModel public: ShaderNode(ShaderGraph& graph); - virtual Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const = 0; + virtual Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const = 0; virtual void BuildNodeEdition(QFormLayout* layout); inline void DisablePreview(); diff --git a/src/ShaderNode/DataModels/TextureValue.cpp b/src/ShaderNode/DataModels/TextureValue.cpp index 9d0d25665..0be18dd88 100644 --- a/src/ShaderNode/DataModels/TextureValue.cpp +++ b/src/ShaderNode/DataModels/TextureValue.cpp @@ -110,7 +110,7 @@ void TextureValue::BuildNodeEdition(QFormLayout* layout) layout->addRow(tr("Texture"), textureSelection); } -Nz::ShaderNodes::NodePtr TextureValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr TextureValue::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { if (!m_currentTextureIndex) throw std::runtime_error("invalid texture input"); @@ -119,19 +119,7 @@ Nz::ShaderNodes::NodePtr TextureValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* assert(outputIndex == 0); const auto& textureEntry = GetGraph().GetTexture(*m_currentTextureIndex); - - Nz::ShaderNodes::BasicType expression = [&] - { - switch (textureEntry.type) - { - case TextureType::Sampler2D: return Nz::ShaderNodes::BasicType::Sampler2D; - } - - assert(false); - throw std::runtime_error("Unhandled texture type"); - }(); - - return Nz::ShaderBuilder::Identifier(Nz::ShaderBuilder::Uniform(textureEntry.name, expression)); + return Nz::ShaderBuilder::Identifier(textureEntry.name); } auto TextureValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const -> QtNodes::NodeDataType diff --git a/src/ShaderNode/DataModels/TextureValue.hpp b/src/ShaderNode/DataModels/TextureValue.hpp index 6d6e6ff27..5de2a556d 100644 --- a/src/ShaderNode/DataModels/TextureValue.hpp +++ b/src/ShaderNode/DataModels/TextureValue.hpp @@ -18,7 +18,7 @@ class TextureValue : public ShaderNode void BuildNodeEdition(QFormLayout* layout) override; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override { return "Texture"; } QString name() const override { return "Texture"; } diff --git a/src/ShaderNode/DataModels/VecComposition.hpp b/src/ShaderNode/DataModels/VecComposition.hpp index 6a41b1e20..d6dfca579 100644 --- a/src/ShaderNode/DataModels/VecComposition.hpp +++ b/src/ShaderNode/DataModels/VecComposition.hpp @@ -17,7 +17,7 @@ class VecComposition : public ShaderNode VecComposition(ShaderGraph& graph); ~VecComposition() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override; QString name() const override; diff --git a/src/ShaderNode/DataModels/VecComposition.inl b/src/ShaderNode/DataModels/VecComposition.inl index 9f17da698..70e8c15a6 100644 --- a/src/ShaderNode/DataModels/VecComposition.inl +++ b/src/ShaderNode/DataModels/VecComposition.inl @@ -14,17 +14,16 @@ ShaderNode(graph) } template -Nz::ShaderNodes::NodePtr VecComposition::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr VecComposition::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == ComponentCount); assert(outputIndex == 0); - std::array expr; + std::vector params; for (std::size_t i = 0; i < count; ++i) - expr[i] = expressions[i]; + params.emplace_back(std::move(expressions[i])); - constexpr auto ExpressionType = VecExpressionType; - return Nz::ShaderBuilder::Cast(expr.data(), expr.size()); + return Nz::ShaderBuilder::Cast(Nz::ShaderAst::VectorType{ ComponentCount, Nz::ShaderAst::PrimitiveType::Float32 }, std::move(params)); } template diff --git a/src/ShaderNode/DataModels/VecDecomposition.cpp b/src/ShaderNode/DataModels/VecDecomposition.cpp index df69df8e6..f36fcea50 100644 --- a/src/ShaderNode/DataModels/VecDecomposition.cpp +++ b/src/ShaderNode/DataModels/VecDecomposition.cpp @@ -16,15 +16,15 @@ ShaderNode(graph) DisableCustomVariableName(); } -Nz::ShaderNodes::NodePtr VecDecomposition::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr VecDecomposition::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == 1); assert(outputIndex < m_outputs.size()); - using namespace Nz::ShaderBuilder; - using namespace Nz::ShaderNodes; + using namespace Nz; - return Nz::ShaderBuilder::Swizzle(expressions[0], static_cast(Nz::UnderlyingCast(SwizzleComponent::First) + outputIndex)); + ShaderAst::SwizzleComponent swizzleComponent = static_cast(Nz::UnderlyingCast(ShaderAst::SwizzleComponent::First) + outputIndex); + return ShaderBuilder::Swizzle(std::move(expressions[0]), { swizzleComponent }); } QString VecDecomposition::caption() const diff --git a/src/ShaderNode/DataModels/VecDecomposition.hpp b/src/ShaderNode/DataModels/VecDecomposition.hpp index c50c95f40..a66326fbf 100644 --- a/src/ShaderNode/DataModels/VecDecomposition.hpp +++ b/src/ShaderNode/DataModels/VecDecomposition.hpp @@ -18,7 +18,7 @@ class VecDecomposition : public ShaderNode VecDecomposition(ShaderGraph& graph); ~VecDecomposition() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override; QString name() const override; diff --git a/src/ShaderNode/DataModels/VecDot.cpp b/src/ShaderNode/DataModels/VecDot.cpp index e327cf06b..0a6e7f0ce 100644 --- a/src/ShaderNode/DataModels/VecDot.cpp +++ b/src/ShaderNode/DataModels/VecDot.cpp @@ -1,4 +1,5 @@ #include +#include #include VecDot::VecDot(ShaderGraph& graph) : @@ -8,13 +9,16 @@ ShaderNode(graph) UpdateOutput(); } -Nz::ShaderNodes::NodePtr VecDot::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr VecDot::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == 2); assert(outputIndex == 0); - using namespace Nz::ShaderNodes; - return IntrinsicCall::Build(IntrinsicType::DotProduct, { expressions[0], expressions[1] }); + std::vector params; + params.push_back(std::move(expressions[0])); + params.push_back(std::move(expressions[1])); + + return Nz::ShaderBuilder::Intrinsic(Nz::ShaderAst::IntrinsicType::DotProduct, std::move(params)); } QString VecDot::caption() const diff --git a/src/ShaderNode/DataModels/VecDot.hpp b/src/ShaderNode/DataModels/VecDot.hpp index 251694ae8..194037bc6 100644 --- a/src/ShaderNode/DataModels/VecDot.hpp +++ b/src/ShaderNode/DataModels/VecDot.hpp @@ -13,7 +13,7 @@ class VecDot : public ShaderNode VecDot(ShaderGraph& graph); ~VecDot() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override; QString name() const override; diff --git a/src/ShaderNode/DataModels/VecFloatMul.cpp b/src/ShaderNode/DataModels/VecFloatMul.cpp index 33237dc25..62abd27e8 100644 --- a/src/ShaderNode/DataModels/VecFloatMul.cpp +++ b/src/ShaderNode/DataModels/VecFloatMul.cpp @@ -1,4 +1,5 @@ #include +#include #include VecFloatMul::VecFloatMul(ShaderGraph& graph) : @@ -7,13 +8,12 @@ ShaderNode(graph) UpdateOutput(); } -Nz::ShaderNodes::NodePtr VecFloatMul::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr VecFloatMul::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == 2); assert(outputIndex == 0); - using namespace Nz::ShaderNodes; - return BinaryOp::Build(BinaryType::Multiply, expressions[0], expressions[1]); + return Nz::ShaderBuilder::Binary(Nz::ShaderAst::BinaryType::Multiply, std::move(expressions[0]), std::move(expressions[1])); } QString VecFloatMul::caption() const diff --git a/src/ShaderNode/DataModels/VecFloatMul.hpp b/src/ShaderNode/DataModels/VecFloatMul.hpp index b7759d4c7..7295d75ce 100644 --- a/src/ShaderNode/DataModels/VecFloatMul.hpp +++ b/src/ShaderNode/DataModels/VecFloatMul.hpp @@ -13,7 +13,7 @@ class VecFloatMul : public ShaderNode VecFloatMul(ShaderGraph& graph); ~VecFloatMul() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override; QString name() const override; diff --git a/src/ShaderNode/DataModels/VecValue.hpp b/src/ShaderNode/DataModels/VecValue.hpp index 3fcebb638..40035655c 100644 --- a/src/ShaderNode/DataModels/VecValue.hpp +++ b/src/ShaderNode/DataModels/VecValue.hpp @@ -18,7 +18,7 @@ class VecValue : public ShaderNode VecValue(ShaderGraph& graph); ~VecValue() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; void BuildNodeEdition(QFormLayout* layout) override; QString caption() const override; diff --git a/src/ShaderNode/DataModels/VecValue.inl b/src/ShaderNode/DataModels/VecValue.inl index ef5ad0622..90b6ca375 100644 --- a/src/ShaderNode/DataModels/VecValue.inl +++ b/src/ShaderNode/DataModels/VecValue.inl @@ -127,7 +127,7 @@ void VecValue::BuildNodeEdition(QFormLayout* layout) } template -Nz::ShaderNodes::NodePtr VecValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr VecValue::BuildNode(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count, std::size_t outputIndex) const { assert(count == 0); assert(outputIndex == 0); diff --git a/src/ShaderNode/DataTypes/VecData.cpp b/src/ShaderNode/DataTypes/VecData.cpp deleted file mode 100644 index 0402864e0..000000000 --- a/src/ShaderNode/DataTypes/VecData.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include -#include -#include - -Nz::ShaderNodes::BasicType VecData::GetExpressionType() const -{ - switch (componentCount) - { - case 2: return Nz::ShaderNodes::BasicType::Float2; - case 3: return Nz::ShaderNodes::BasicType::Float3; - case 4: return Nz::ShaderNodes::BasicType::Float4; - default: - break; - } - - assert(false); - throw std::runtime_error("invalid component count"); -} diff --git a/src/ShaderNode/DataTypes/VecData.hpp b/src/ShaderNode/DataTypes/VecData.hpp index f6e1bfdd9..44ef84e67 100644 --- a/src/ShaderNode/DataTypes/VecData.hpp +++ b/src/ShaderNode/DataTypes/VecData.hpp @@ -13,43 +13,12 @@ struct VecData : public QtNodes::NodeData inline QtNodes::NodeDataType type() const override; - Nz::ShaderNodes::BasicType GetExpressionType() const; - static inline QtNodes::NodeDataType Type(); std::size_t componentCount; PreviewValues preview; }; -template -struct VecExpressionTypeHelper; - -template<> -struct VecExpressionTypeHelper<1> -{ - static constexpr Nz::ShaderNodes::BasicType ExpressionType = Nz::ShaderNodes::BasicType::Float1; -}; - -template<> -struct VecExpressionTypeHelper<2> -{ - static constexpr Nz::ShaderNodes::BasicType ExpressionType = Nz::ShaderNodes::BasicType::Float2; -}; - -template<> -struct VecExpressionTypeHelper<3> -{ - static constexpr Nz::ShaderNodes::BasicType ExpressionType = Nz::ShaderNodes::BasicType::Float3; -}; - -template<> -struct VecExpressionTypeHelper<4> -{ - static constexpr Nz::ShaderNodes::BasicType ExpressionType = Nz::ShaderNodes::BasicType::Float4; -}; - -template constexpr Nz::ShaderNodes::BasicType VecExpressionType = VecExpressionTypeHelper::ExpressionType; - struct VecTypeDummy {}; diff --git a/src/ShaderNode/ShaderGraph.cpp b/src/ShaderNode/ShaderGraph.cpp index 68e11685f..3e3fa273c 100644 --- a/src/ShaderNode/ShaderGraph.cpp +++ b/src/ShaderNode/ShaderGraph.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include #include #include #include @@ -45,6 +47,12 @@ namespace auto creator = [&] { return std::make_unique(graph); }; registry->registerModel(category, std::move(creator)); } + + template + std::unique_ptr static_unique_pointer_cast(std::unique_ptr&& ptr) + { + return std::unique_ptr(static_cast(ptr.release())); + } } ShaderGraph::ShaderGraph() : @@ -442,157 +450,29 @@ QJsonObject ShaderGraph::Save() return sceneJson; } -Nz::ShaderNodes::StatementPtr ShaderGraph::ToAst() const +Nz::ShaderAst::StatementPtr ShaderGraph::ToAst() const { - std::vector statements; + std::vector statements; - using Key = QPair; - auto BuildKey = [](QUuid uuid, std::size_t index) + // Declare all structures + for (const auto& structInfo : m_structs) { - return Key(uuid, index); - }; + Nz::ShaderAst::StructDescription structDesc; + structDesc.layout = Nz::StructLayout_Std140; + structDesc.name = structInfo.name; - QHash usageCount; - - std::function DetectVariables; - DetectVariables = [&](QtNodes::Node* node, std::size_t outputIndex) - { - auto it = usageCount.find(BuildKey(node->id(), outputIndex)); - if (it == usageCount.end()) + for (const auto& memberInfo : structInfo.members) { - for (const auto& connectionSet : node->nodeState().getEntries(QtNodes::PortType::In)) - { - for (const auto& [uuid, conn] : connectionSet) - { - DetectVariables(conn->getNode(QtNodes::PortType::Out), conn->getPortIndex(QtNodes::PortType::Out)); - } - } - - it = usageCount.insert(BuildKey(node->id(), outputIndex), 0); + auto& structMember = structDesc.members.emplace_back(); + structMember.name = memberInfo.name; + structMember.type = ToShaderExpressionType(memberInfo.type); } - (*it)++; - }; - - std::vector outputNodes; - - m_flowScene.iterateOverNodes([&](QtNodes::Node* node) - { - if (node->nodeDataModel()->nPorts(QtNodes::PortType::Out) == 0) - { - DetectVariables(node, 0); - outputNodes.push_back(node); - } - }); - - QHash variableExpressions; - - unsigned int varCount = 0; - std::unordered_set usedVariableNames; - - std::function HandleNode; - HandleNode = [&](QtNodes::Node* node, std::size_t portIndex) -> Nz::ShaderNodes::NodePtr - { - ShaderNode* shaderNode = static_cast(node->nodeDataModel()); - if (shaderNode->validationState() != QtNodes::NodeValidationState::Valid) - throw std::runtime_error(shaderNode->validationMessage().toStdString()); - - qDebug() << shaderNode->name() << node->id(); - if (auto it = variableExpressions.find(BuildKey(node->id(), portIndex)); it != variableExpressions.end()) - return *it; - - auto it = usageCount.find(BuildKey(node->id(), portIndex)); - assert(it != usageCount.end()); - - std::size_t inputCount = shaderNode->nPorts(QtNodes::PortType::In); - Nz::StackArray expressions = NazaraStackArray(Nz::ShaderNodes::ExpressionPtr, inputCount); - std::size_t i = 0; - - for (const auto& connectionSet : node->nodeState().getEntries(QtNodes::PortType::In)) - { - for (const auto& [uuid, conn] : connectionSet) - { - assert(i < expressions.size()); - Nz::ShaderNodes::NodePtr inputNode = HandleNode(conn->getNode(QtNodes::PortType::Out), conn->getPortIndex(QtNodes::PortType::Out)); - if (inputNode->IsStatement()) - throw std::runtime_error("unexpected statement"); - - expressions[i] = std::static_pointer_cast(inputNode); - i++; - } - } - - auto astNode = shaderNode->BuildNode(expressions.data(), expressions.size(), portIndex); - - const std::string& variableName = shaderNode->GetVariableName(); - if (*it > 1 || !variableName.empty()) - { - if (astNode->IsStatement()) - throw std::runtime_error("unexpected statement"); - - auto expression = std::static_pointer_cast(astNode); - - Nz::ShaderNodes::ExpressionPtr varExpression; - if (Nz::GetExpressionCategory(expression) == Nz::ShaderNodes::ExpressionCategory::RValue) - { - std::string name; - if (variableName.empty()) - name = "var" + std::to_string(varCount++); - else - name = variableName; - - if (usedVariableNames.find(name) != usedVariableNames.end()) - throw std::runtime_error("duplicate variable found: " + name); - - usedVariableNames.insert(name); - - auto variable = Nz::ShaderBuilder::Local(std::move(name), expression->GetExpressionType()); - statements.emplace_back(Nz::ShaderBuilder::DeclareVariable(variable, std::move(expression))); - - varExpression = Nz::ShaderBuilder::Identifier(variable); - } - else - varExpression = std::move(expression); - - variableExpressions.insert(BuildKey(node->id(), portIndex), varExpression); - - return varExpression; - } - else - return astNode; - }; - - std::sort(outputNodes.begin(), outputNodes.end(), [](QtNodes::Node* lhs, QtNodes::Node* rhs) - { - ShaderNode* leftNode = static_cast(lhs->nodeDataModel()); - ShaderNode* rightNode = static_cast(rhs->nodeDataModel()); - - return leftNode->GetOutputOrder() < rightNode->GetOutputOrder(); - }); - - for (QtNodes::Node* node : outputNodes) - { - auto astNode = HandleNode(node, 0); - if (!astNode->IsStatement()) - statements.emplace_back(Nz::ShaderBuilder::ExprStatement(std::static_pointer_cast(astNode))); - else - statements.emplace_back(std::static_pointer_cast(astNode)); + statements.push_back(Nz::ShaderBuilder::DeclareStruct(std::move(structDesc))); } - return Nz::ShaderNodes::StatementBlock::Build(std::move(statements)); -} - -Nz::ShaderAst ShaderGraph::ToShader() const -{ - Nz::ShaderAst shader(ShaderGraph::ToShaderStageType(m_type)); //< FIXME - for (const auto& condition : m_conditions) - shader.AddCondition(condition.name); - - for (const auto& input : m_inputs) - shader.AddInput(input.name, ToShaderExpressionType(input.type), input.locationIndex); - - for (const auto& output : m_outputs) - shader.AddOutput(output.name, ToShaderExpressionType(output.type), output.locationIndex); + // External block + auto external = std::make_unique(); for (const auto& buffer : m_buffers) { @@ -600,46 +480,74 @@ Nz::ShaderAst ShaderGraph::ToShader() const throw std::runtime_error("buffer " + buffer.name + " references out-of-bounds struct #" + std::to_string(buffer.structIndex)); const auto& structInfo = m_structs[buffer.structIndex]; - shader.AddUniform(buffer.name, structInfo.name, buffer.bindingIndex, Nz::ShaderNodes::MemoryLayout::Std140); + + auto& extVar = external->externalVars.emplace_back(); + extVar.bindingIndex = buffer.bindingIndex; + extVar.name = buffer.name; + extVar.type = Nz::ShaderAst::IdentifierType{ structInfo.name }; } - for (const auto& uniform : m_textures) - shader.AddUniform(uniform.name, ToShaderExpressionType(uniform.type), uniform.bindingIndex, {}); - - for (const auto& s : m_structs) + for (const auto& texture : m_textures) { - std::vector members; - for (const auto& sMember : s.members) + auto& extVar = external->externalVars.emplace_back(); + extVar.bindingIndex = texture.bindingIndex; + extVar.name = texture.name; + extVar.type = ToShaderExpressionType(texture.type); + } + + if (!external->externalVars.empty()) + statements.push_back(std::move(external)); + + // Inputs / outputs + if (!m_inputs.empty()) + { + Nz::ShaderAst::StructDescription structDesc; + structDesc.name = "InputData"; + + for (const auto& input : m_inputs) { - auto& member = members.emplace_back(); - member.name = sMember.name; - - std::visit([&](auto&& arg) - { - using T = std::decay_t; - if constexpr (std::is_same_v) - member.type = ToShaderExpressionType(arg); - else if constexpr (std::is_same_v) - { - if (arg >= m_structs.size()) - throw std::runtime_error("struct " + s.name + " references out-of-bounds struct #" + std::to_string(arg)); - - member.type = m_structs[arg].name; - } - else - static_assert(AlwaysFalse::value, "non-exhaustive visitor"); - }, sMember.type); + auto& structMember = structDesc.members.emplace_back(); + structMember.name = input.name; + structMember.type = ToShaderExpressionType(input.type); + structMember.locationIndex = input.locationIndex; } - shader.AddStruct(s.name, std::move(members)); + statements.push_back(Nz::ShaderBuilder::DeclareStruct(std::move(structDesc))); } - return shader; + Nz::ShaderAst::ExpressionType returnType; + if (!m_outputs.empty()) + { + Nz::ShaderAst::StructDescription structDesc; + structDesc.name = "OutputData"; + + for (const auto& output : m_outputs) + { + auto& structMember = structDesc.members.emplace_back(); + structMember.name = output.name; + structMember.type = ToShaderExpressionType(output.type); + structMember.locationIndex = output.locationIndex; + } + + if (m_type == ShaderType::Vertex) + { + auto& position = structDesc.members.emplace_back(); + position.name = "position"; + position.type = Nz::ShaderAst::VectorType{ 4, Nz::ShaderAst::PrimitiveType::Float32 }; + } + + statements.push_back(Nz::ShaderBuilder::DeclareStruct(std::move(structDesc))); + } + + // Functions + statements.push_back(ToFunction()); + + return Nz::ShaderBuilder::MultiStatement(std::move(statements)); } -Nz::ShaderExpressionType ShaderGraph::ToShaderExpressionType(const std::variant& type) const +Nz::ShaderAst::ExpressionType ShaderGraph::ToShaderExpressionType(const std::variant& type) const { - return std::visit([&](auto&& arg) -> Nz::ShaderExpressionType + return std::visit([&](auto&& arg) -> Nz::ShaderAst::ExpressionType { using T = std::decay_t; if constexpr (std::is_same_v) @@ -648,7 +556,7 @@ Nz::ShaderExpressionType ShaderGraph::ToShaderExpressionType(const std::variant< { assert(arg < m_structs.size()); const auto& s = m_structs[arg]; - return s.name; + return Nz::ShaderAst::IdentifierType{ s.name }; } else static_assert(Nz::AlwaysFalse::value, "non-exhaustive visitor"); @@ -763,27 +671,27 @@ QtNodes::NodeDataType ShaderGraph::ToNodeDataType(PrimitiveType type) throw std::runtime_error("Unhandled input type"); } -Nz::ShaderExpressionType ShaderGraph::ToShaderExpressionType(PrimitiveType type) +Nz::ShaderAst::ExpressionType ShaderGraph::ToShaderExpressionType(PrimitiveType type) { switch (type) { - case PrimitiveType::Bool: return Nz::ShaderNodes::BasicType::Boolean; - case PrimitiveType::Float1: return Nz::ShaderNodes::BasicType::Float1; - case PrimitiveType::Float2: return Nz::ShaderNodes::BasicType::Float2; - case PrimitiveType::Float3: return Nz::ShaderNodes::BasicType::Float3; - case PrimitiveType::Float4: return Nz::ShaderNodes::BasicType::Float4; - case PrimitiveType::Mat4x4: return Nz::ShaderNodes::BasicType::Mat4x4; + case PrimitiveType::Bool: return Nz::ShaderAst::PrimitiveType::Boolean; + case PrimitiveType::Float1: return Nz::ShaderAst::PrimitiveType::Float32; + case PrimitiveType::Float2: return Nz::ShaderAst::VectorType{ 2, Nz::ShaderAst::PrimitiveType::Float32 }; + case PrimitiveType::Float3: return Nz::ShaderAst::VectorType{ 3, Nz::ShaderAst::PrimitiveType::Float32 }; + case PrimitiveType::Float4: return Nz::ShaderAst::VectorType{ 4, Nz::ShaderAst::PrimitiveType::Float32 }; + case PrimitiveType::Mat4x4: return Nz::ShaderAst::MatrixType{ 4, 4, Nz::ShaderAst::PrimitiveType::Float32 }; } assert(false); throw std::runtime_error("Unhandled primitive type"); } -Nz::ShaderExpressionType ShaderGraph::ToShaderExpressionType(TextureType type) +Nz::ShaderAst::ExpressionType ShaderGraph::ToShaderExpressionType(TextureType type) { switch (type) { - case TextureType::Sampler2D: return Nz::ShaderNodes::BasicType::Sampler2D; + case TextureType::Sampler2D: return Nz::ShaderAst::SamplerType{ Nz::ImageType_2D, Nz::ShaderAst::PrimitiveType::Float32 }; } assert(false); @@ -879,3 +787,158 @@ std::shared_ptr ShaderGraph::BuildRegistry() return registry; } + +std::unique_ptr ShaderGraph::ToFunction() const +{ + std::vector statements; + + std::vector parameters; + if (!m_inputs.empty()) + { + parameters.push_back({ + "input", + Nz::ShaderAst::IdentifierType{ "InputData" } + }); + } + + Nz::ShaderAst::ExpressionType returnType; + if (!m_outputs.empty()) + { + returnType = Nz::ShaderAst::IdentifierType{ "OutputData" }; + + statements.push_back(Nz::ShaderBuilder::DeclareVariable("output", returnType)); + } + + using Key = QPair; + auto BuildKey = [](QUuid uuid, std::size_t index) + { + return Key(uuid, index); + }; + + std::map usageCount; + + std::function DetectVariables; + DetectVariables = [&](QtNodes::Node* node, std::size_t outputIndex) + { + auto it = usageCount.find(BuildKey(node->id(), outputIndex)); + if (it == usageCount.end()) + { + for (const auto& connectionSet : node->nodeState().getEntries(QtNodes::PortType::In)) + { + for (const auto& [uuid, conn] : connectionSet) + { + DetectVariables(conn->getNode(QtNodes::PortType::Out), conn->getPortIndex(QtNodes::PortType::Out)); + } + } + + it = usageCount.emplace(BuildKey(node->id(), outputIndex), 0).first; + } + + it->second++; + }; + + std::vector outputNodes; + + m_flowScene.iterateOverNodes([&](QtNodes::Node* node) + { + if (node->nodeDataModel()->nPorts(QtNodes::PortType::Out) == 0) + { + DetectVariables(node, 0); + outputNodes.push_back(node); + } + }); + + std::map variableExpressions; + + unsigned int varCount = 0; + std::unordered_set usedVariableNames; + + std::function HandleNode; + HandleNode = [&](QtNodes::Node* node, std::size_t portIndex) -> Nz::ShaderAst::NodePtr + { + ShaderNode* shaderNode = static_cast(node->nodeDataModel()); + if (shaderNode->validationState() != QtNodes::NodeValidationState::Valid) + throw std::runtime_error(shaderNode->validationMessage().toStdString()); + + qDebug() << shaderNode->name() << node->id(); + if (auto it = variableExpressions.find(BuildKey(node->id(), portIndex)); it != variableExpressions.end()) + return Nz::ShaderAst::Clone(it->second); + + auto it = usageCount.find(BuildKey(node->id(), portIndex)); + assert(it != usageCount.end()); + + std::size_t inputCount = shaderNode->nPorts(QtNodes::PortType::In); + Nz::StackArray expressions = NazaraStackArray(Nz::ShaderAst::ExpressionPtr, inputCount); + std::size_t i = 0; + + for (const auto& connectionSet : node->nodeState().getEntries(QtNodes::PortType::In)) + { + for (const auto& [uuid, conn] : connectionSet) + { + assert(i < expressions.size()); + Nz::ShaderAst::NodePtr inputNode = HandleNode(conn->getNode(QtNodes::PortType::Out), conn->getPortIndex(QtNodes::PortType::Out)); + if (!Nz::ShaderAst::IsExpression(inputNode->GetType())) + throw std::runtime_error("unexpected statement"); + + expressions[i] = static_unique_pointer_cast(std::move(inputNode)); + i++; + } + } + + auto astNode = shaderNode->BuildNode(expressions.data(), expressions.size(), portIndex); + if (!Nz::ShaderAst::IsExpression(astNode->GetType())) + return astNode; + + Nz::ShaderAst::ExpressionPtr expression = static_unique_pointer_cast(std::move(astNode)); + + const std::string& variableName = shaderNode->GetVariableName(); + if (it->second > 1 || !variableName.empty()) + { + Nz::ShaderAst::ExpressionPtr varExpression; + if (Nz::ShaderAst::GetExpressionCategory(*expression) == Nz::ShaderAst::ExpressionCategory::RValue) + { + std::string name; + if (variableName.empty()) + name = "var" + std::to_string(varCount++); + else + name = variableName; + + if (usedVariableNames.find(name) != usedVariableNames.end()) + throw std::runtime_error("duplicate variable found: " + name); + + usedVariableNames.insert(name); + + statements.emplace_back(Nz::ShaderBuilder::DeclareVariable(name, std::move(expression))); + + varExpression = Nz::ShaderBuilder::Identifier(name); + } + else + varExpression = std::move(expression); + + variableExpressions[BuildKey(node->id(), portIndex)] = Nz::ShaderAst::Clone(varExpression); + + return varExpression; + } + else + return expression; + }; + + std::sort(outputNodes.begin(), outputNodes.end(), [](QtNodes::Node* lhs, QtNodes::Node* rhs) + { + ShaderNode* leftNode = static_cast(lhs->nodeDataModel()); + ShaderNode* rightNode = static_cast(rhs->nodeDataModel()); + + return leftNode->GetOutputOrder() < rightNode->GetOutputOrder(); + }); + + for (QtNodes::Node* node : outputNodes) + { + auto astNode = HandleNode(node, 0); + if (!Nz::ShaderAst::IsStatement(astNode->GetType())) + statements.emplace_back(Nz::ShaderBuilder::ExpressionStatement(static_unique_pointer_cast(std::move(astNode)))); + else + statements.emplace_back(static_unique_pointer_cast(std::move(astNode))); + } + + return Nz::ShaderBuilder::DeclareFunction(ToShaderStageType(m_type), "main", std::move(parameters), std::move(statements), std::move(returnType)); +} diff --git a/src/ShaderNode/ShaderGraph.hpp b/src/ShaderNode/ShaderGraph.hpp index 1ca776305..19dcb6813 100644 --- a/src/ShaderNode/ShaderGraph.hpp +++ b/src/ShaderNode/ShaderGraph.hpp @@ -5,7 +5,6 @@ #include #include -#include #include #include #include @@ -67,9 +66,8 @@ class ShaderGraph void Load(const QJsonObject& data); QJsonObject Save(); - Nz::ShaderNodes::StatementPtr ToAst() const; - Nz::ShaderAst ToShader() const; - Nz::ShaderExpressionType ToShaderExpressionType(const std::variant& type) const; + Nz::ShaderAst::StatementPtr ToAst() const; + Nz::ShaderAst::ExpressionType ToShaderExpressionType(const std::variant& type) const; void UpdateBuffer(std::size_t bufferIndex, std::string name, BufferType bufferType, std::size_t structIndex, std::size_t bindingIndex); void UpdateCondition(std::size_t conditionIndex, std::string condition); @@ -147,12 +145,13 @@ class ShaderGraph NazaraSignal(OnTypeUpdated, ShaderGraph*); static QtNodes::NodeDataType ToNodeDataType(PrimitiveType type); - static Nz::ShaderExpressionType ToShaderExpressionType(PrimitiveType type); - static Nz::ShaderExpressionType ToShaderExpressionType(TextureType type); + static Nz::ShaderAst::ExpressionType ToShaderExpressionType(PrimitiveType type); + static Nz::ShaderAst::ExpressionType ToShaderExpressionType(TextureType type); static Nz::ShaderStageType ToShaderStageType(ShaderType type); private: std::shared_ptr BuildRegistry(); + std::unique_ptr ToFunction() const; mutable QtNodes::FlowScene m_flowScene; std::vector m_buffers; diff --git a/src/ShaderNode/Widgets/CodeOutputWidget.cpp b/src/ShaderNode/Widgets/CodeOutputWidget.cpp index 73e9c7d3f..9e20057e1 100644 --- a/src/ShaderNode/Widgets/CodeOutputWidget.cpp +++ b/src/ShaderNode/Widgets/CodeOutputWidget.cpp @@ -58,17 +58,14 @@ void CodeOutputWidget::Refresh() enabledConditions = Nz::SetBit(enabledConditions, i); } - Nz::ShaderAst shaderAst = m_shaderGraph.ToShader(); + Nz::ShaderAst::StatementPtr shaderAst = m_shaderGraph.ToAst(); - Nz::ShaderNodes::StatementPtr mainAst = m_shaderGraph.ToAst(); if (m_optimisationCheckbox->isChecked()) { - Nz::ShaderAstOptimizer optimiser; - mainAst = optimiser.Optimise(mainAst, shaderAst, enabledConditions); + Nz::ShaderAst::AstOptimizer optimiser; + shaderAst = optimiser.Optimise(shaderAst, enabledConditions); } - shaderAst.AddFunction("main", mainAst); - Nz::ShaderWriter::States states; states.enabledConditions = enabledConditions; @@ -79,7 +76,7 @@ void CodeOutputWidget::Refresh() case OutputLanguage::GLSL: { Nz::GlslWriter writer; - output = writer.Generate(shaderAst, states); + output = writer.Generate(ShaderGraph::ToShaderStageType(m_shaderGraph.GetType()), shaderAst, states); break; } diff --git a/src/ShaderNode/Widgets/CodeOutputWidget.hpp b/src/ShaderNode/Widgets/CodeOutputWidget.hpp index ecea4d54b..47945ca34 100644 --- a/src/ShaderNode/Widgets/CodeOutputWidget.hpp +++ b/src/ShaderNode/Widgets/CodeOutputWidget.hpp @@ -3,7 +3,6 @@ #ifndef NAZARA_SHADERNODES_CODEOUTPUTWIDGET_HPP #define NAZARA_SHADERNODES_CODEOUTPUTWIDGET_HPP -#include #include #include diff --git a/src/ShaderNode/Widgets/MainWindow.cpp b/src/ShaderNode/Widgets/MainWindow.cpp index 67b50dd91..5777964b2 100644 --- a/src/ShaderNode/Widgets/MainWindow.cpp +++ b/src/ShaderNode/Widgets/MainWindow.cpp @@ -181,8 +181,7 @@ void MainWindow::OnCompile() { try { - auto shader = m_shaderGraph.ToShader(); - shader.AddFunction("main", m_shaderGraph.ToAst()); + auto shader = m_shaderGraph.ToAst(); QString fileName = QFileDialog::getSaveFileName(nullptr, tr("Save shader"), QString(), tr("Shader Files (*.shader)")); if (fileName.isEmpty()) @@ -192,7 +191,7 @@ void MainWindow::OnCompile() fileName += ".shader"; Nz::File file(fileName.toStdString(), Nz::OpenMode_WriteOnly); - file.Write(Nz::SerializeShader(shader)); + file.Write(Nz::ShaderAst::SerializeShader(shader)); } catch (const std::exception& e) { diff --git a/src/ShaderNode/Widgets/MainWindow.hpp b/src/ShaderNode/Widgets/MainWindow.hpp index 1031eca9a..eaedd6aea 100644 --- a/src/ShaderNode/Widgets/MainWindow.hpp +++ b/src/ShaderNode/Widgets/MainWindow.hpp @@ -9,11 +9,6 @@ class NodeEditor; -namespace Nz -{ - class ShaderAst; -} - class MainWindow : public QMainWindow { public: From 0860a0689f139a5a7e769a326fa62b61bdfb3ad7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 14 Apr 2021 20:10:11 +0200 Subject: [PATCH 103/278] Shader/GlslWriter: Improve GLSL readability --- include/Nazara/Shader/GlslWriter.hpp | 1 + src/Nazara/Shader/GlslWriter.cpp | 39 ++++++++++++++++------------ 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/include/Nazara/Shader/GlslWriter.hpp b/include/Nazara/Shader/GlslWriter.hpp index 9f228c51e..ffc19987d 100644 --- a/include/Nazara/Shader/GlslWriter.hpp +++ b/include/Nazara/Shader/GlslWriter.hpp @@ -64,6 +64,7 @@ namespace Nz void AppendHeader(); void AppendLine(const std::string& txt = {}); template void AppendLine(Args&&... params); + void AppendStatementList(std::vector& statements); void EnterScope(); void LeaveScope(bool skipLine = true); diff --git a/src/Nazara/Shader/GlslWriter.cpp b/src/Nazara/Shader/GlslWriter.cpp index 08088d24f..e80bd1c3a 100644 --- a/src/Nazara/Shader/GlslWriter.cpp +++ b/src/Nazara/Shader/GlslWriter.cpp @@ -311,6 +311,20 @@ namespace Nz AppendLine(); } + void GlslWriter::AppendStatementList(std::vector& statements) + { + bool first = true; + for (const ShaderAst::StatementPtr& statement : statements) + { + if (!first && statement->GetType() != ShaderAst::NodeType::NoOpStatement) + AppendLine(); + + statement->Visit(*this); + + first = false; + } + } + void GlslWriter::EnterScope() { NazaraAssert(m_currentState, "This function should only be called while processing an AST"); @@ -361,8 +375,7 @@ namespace Nz // Output struct is handled on return node m_currentState->isInEntryPoint = true; - for (auto& statement : node.statements) - statement->Visit(*this); + AppendStatementList(node.statements); m_currentState->isInEntryPoint = false; } @@ -711,8 +724,7 @@ namespace Nz EnterScope(); { - for (auto& statement : node.statements) - statement->Visit(*this); + AppendStatementList(node.statements); } LeaveScope(); } @@ -758,7 +770,7 @@ namespace Nz node.initialExpression->Visit(*this); } - AppendLine(";"); + Append(";"); } void GlslWriter::Visit(ShaderAst::DiscardStatement& /*node*/) @@ -769,7 +781,7 @@ namespace Nz void GlslWriter::Visit(ShaderAst::ExpressionStatement& node) { node.expression->Visit(*this); - AppendLine(";"); + Append(";"); } void GlslWriter::Visit(ShaderAst::IntrinsicExpression& node) @@ -802,16 +814,7 @@ namespace Nz void GlslWriter::Visit(ShaderAst::MultiStatement& node) { - bool first = true; - for (const ShaderAst::StatementPtr& statement : node.statements) - { - if (!first && statement->GetType() != ShaderAst::NodeType::NoOpStatement) - AppendLine(); - - statement->Visit(*this); - - first = false; - } + AppendStatementList(node.statements); } void GlslWriter::Visit(ShaderAst::NoOpStatement& /*node*/) @@ -843,6 +846,8 @@ namespace Nz outputStructVarName = s_outputVarName; } + AppendLine(); + for (const auto& [name, targetName] : m_currentState->outputFields) { bool isOutputPosition = (m_currentState->stage == ShaderStageType::Vertex && m_environment.flipYPosition && targetName == "gl_Position"); @@ -853,7 +858,7 @@ namespace Nz if (isOutputPosition) Append(" * vec4(1.0, ", s_flipYUniformName, ", 1.0, 1.0)"); - Append(";"); + AppendLine(";"); } AppendLine(); From 85ce6a4f43422abbefd42b7659cd8ace0737c1bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 14 Apr 2021 20:10:39 +0200 Subject: [PATCH 104/278] Shader: Fix struct nesting --- src/Nazara/Shader/Ast/TransformVisitor.cpp | 3 +++ src/Nazara/Shader/ShaderAstValidator.cpp | 10 +++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Nazara/Shader/Ast/TransformVisitor.cpp b/src/Nazara/Shader/Ast/TransformVisitor.cpp index 14f127697..5e8e660ab 100644 --- a/src/Nazara/Shader/Ast/TransformVisitor.cpp +++ b/src/Nazara/Shader/Ast/TransformVisitor.cpp @@ -127,6 +127,9 @@ namespace Nz::ShaderAst void TransformVisitor::Visit(DeclareStructStatement& node) { + for (auto& member : node.description.members) + member.type = ResolveType(member.type); + node.structIndex = RegisterStruct(node.description.name, node.description); AstCloner::Visit(node); diff --git a/src/Nazara/Shader/ShaderAstValidator.cpp b/src/Nazara/Shader/ShaderAstValidator.cpp index c979ff4b0..d83e0dbce 100644 --- a/src/Nazara/Shader/ShaderAstValidator.cpp +++ b/src/Nazara/Shader/ShaderAstValidator.cpp @@ -589,7 +589,15 @@ namespace Nz::ShaderAst { assert(m_context); - //TODO: check members attributes + std::unordered_set declaredMembers; + + for (auto& member : node.description.members) + { + if (declaredMembers.find(member.name) != declaredMembers.end()) + throw AstError{ "struct member " + member.name + " found multiple time" }; + + declaredMembers.insert(member.name); + } AstScopedVisitor::Visit(node); } From 3e704b9ea64cd2e507471a101e4d743fe7884a2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 14 Apr 2021 20:11:18 +0200 Subject: [PATCH 105/278] Shader: Minor fixes --- include/Nazara/Shader/ShaderBuilder.hpp | 1 + include/Nazara/Shader/ShaderBuilder.inl | 12 +++++++++++- src/Nazara/Shader/SpirvPrinter.cpp | 4 ++-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/include/Nazara/Shader/ShaderBuilder.hpp b/include/Nazara/Shader/ShaderBuilder.hpp index 502dbed73..9394624b1 100644 --- a/include/Nazara/Shader/ShaderBuilder.hpp +++ b/include/Nazara/Shader/ShaderBuilder.hpp @@ -59,6 +59,7 @@ namespace Nz::ShaderBuilder struct DeclareFunction { + inline std::unique_ptr operator()(std::string name, ShaderAst::StatementPtr statement) const; inline std::unique_ptr operator()(std::string name, std::vector parameters, std::vector statements, ShaderAst::ExpressionType returnType = ShaderAst::NoType{}) const; inline std::unique_ptr operator()(std::optional entryStage, std::string name, std::vector parameters, std::vector statements, ShaderAst::ExpressionType returnType = ShaderAst::NoType{}) const; }; diff --git a/include/Nazara/Shader/ShaderBuilder.inl b/include/Nazara/Shader/ShaderBuilder.inl index d27cbd5fd..d48263e01 100644 --- a/include/Nazara/Shader/ShaderBuilder.inl +++ b/include/Nazara/Shader/ShaderBuilder.inl @@ -97,6 +97,15 @@ namespace Nz::ShaderBuilder return constantNode; } + inline std::unique_ptr Impl::DeclareFunction::operator()(std::string name, ShaderAst::StatementPtr statement) const + { + auto declareFunctionNode = std::make_unique(); + declareFunctionNode->name = std::move(name); + declareFunctionNode->statements.push_back(std::move(statement)); + + return declareFunctionNode; + } + inline std::unique_ptr Impl::DeclareFunction::operator()(std::string name, std::vector parameters, std::vector statements, ShaderAst::ExpressionType returnType) const { auto declareFunctionNode = std::make_unique(); @@ -200,7 +209,8 @@ namespace Nz::ShaderBuilder swizzleNode->expression = std::move(expression); assert(swizzleComponents.size() <= swizzleNode->components.size()); - for (std::size_t i = 0; i < swizzleComponents.size(); ++i) + swizzleNode->componentCount = swizzleComponents.size(); + for (std::size_t i = 0; i < swizzleNode->componentCount; ++i) swizzleNode->components[i] = swizzleComponents[i]; return swizzleNode; diff --git a/src/Nazara/Shader/SpirvPrinter.cpp b/src/Nazara/Shader/SpirvPrinter.cpp index 373d7e2c9..f8bbf4f18 100644 --- a/src/Nazara/Shader/SpirvPrinter.cpp +++ b/src/Nazara/Shader/SpirvPrinter.cpp @@ -203,14 +203,14 @@ namespace Nz m_currentState->stream << std::string(m_currentState->resultOffset, ' '); m_currentState->stream << instructionStream.str(); + + assert(GetCurrentPtr() == startPtr + wordCount - 1); } else m_currentState->stream << instruction.name; m_currentState->stream << "\n"; - assert(GetCurrentPtr() == startPtr + wordCount - 1); - return true; } } From 54c34869a4e7ca6bdaa19056a90c7e505246e497 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 14 Apr 2021 20:11:41 +0200 Subject: [PATCH 106/278] Fix Shader unit tests --- include/Nazara/Shader/GlslWriter.hpp | 3 +- src/Nazara/Shader/GlslWriter.cpp | 32 ++++++++---- tests/Engine/Shader/AccessMember.cpp | 78 ++++++++++++++++------------ 3 files changed, 68 insertions(+), 45 deletions(-) diff --git a/include/Nazara/Shader/GlslWriter.hpp b/include/Nazara/Shader/GlslWriter.hpp index ffc19987d..99e68d9f0 100644 --- a/include/Nazara/Shader/GlslWriter.hpp +++ b/include/Nazara/Shader/GlslWriter.hpp @@ -29,7 +29,8 @@ namespace Nz GlslWriter(GlslWriter&&) = delete; ~GlslWriter() = default; - std::string Generate(ShaderStageType shaderStage, ShaderAst::StatementPtr& shader, const States& conditions = {}); + std::string Generate(ShaderAst::StatementPtr& shader, const States& conditions = {}); + std::string Generate(std::optional shaderStage, ShaderAst::StatementPtr& shader, const States& conditions = {}); void SetEnv(Environment environment); diff --git a/src/Nazara/Shader/GlslWriter.cpp b/src/Nazara/Shader/GlslWriter.cpp index e80bd1c3a..a509245e4 100644 --- a/src/Nazara/Shader/GlslWriter.cpp +++ b/src/Nazara/Shader/GlslWriter.cpp @@ -43,19 +43,27 @@ namespace Nz ShaderAst::DeclareFunctionStatement* func = static_cast(clone.get()); // Remove function if it's an entry point of another type than the one selected - if (node.entryStage) + if (selectedStage) { - ShaderStageType stage = *node.entryStage; - if (stage != selectedStage) - return ShaderBuilder::NoOp(); + if (node.entryStage) + { + ShaderStageType stage = *node.entryStage; + if (stage != *selectedStage) + return ShaderBuilder::NoOp(); + entryPoint = func; + } + } + else + { + assert(!entryPoint); entryPoint = func; } return clone; } - ShaderStageType selectedStage; + std::optional selectedStage; ShaderAst::DeclareFunctionStatement* entryPoint = nullptr; }; @@ -79,7 +87,7 @@ namespace Nz std::string targetName; }; - ShaderStageType stage; + std::optional stage; const States* states = nullptr; ShaderAst::DeclareFunctionStatement* entryFunc = nullptr; std::stringstream stream; @@ -97,7 +105,12 @@ namespace Nz { } - std::string GlslWriter::Generate(ShaderStageType shaderStage, ShaderAst::StatementPtr& shader, const States& conditions) + std::string GlslWriter::Generate(ShaderAst::StatementPtr& shader, const States& conditions) + { + return Generate(std::nullopt, shader, conditions); + } + + std::string GlslWriter::Generate(std::optional shaderStage, ShaderAst::StatementPtr& shader, const States& conditions) { State state; state.stage = shaderStage; @@ -394,7 +407,7 @@ namespace Nz assert(it != s_builtinMapping.end()); const Builtin& builtin = it->second; - if (!builtin.stageFlags.Test(m_currentState->stage)) + if (m_currentState->stage && !builtin.stageFlags.Test(*m_currentState->stage)) continue; //< This builtin is not active in this stage, skip it fields.push_back({ @@ -852,8 +865,6 @@ namespace Nz { bool isOutputPosition = (m_currentState->stage == ShaderStageType::Vertex && m_environment.flipYPosition && targetName == "gl_Position"); - AppendLine(); - Append(targetName, " = ", outputStructVarName, ".", name); if (isOutputPosition) Append(" * vec4(1.0, ", s_flipYUniformName, ", 1.0, 1.0)"); @@ -861,7 +872,6 @@ namespace Nz AppendLine(";"); } - AppendLine(); Append("return;"); //< TODO: Don't return if it's the last statement of the function } else diff --git a/tests/Engine/Shader/AccessMember.cpp b/tests/Engine/Shader/AccessMember.cpp index 7ed92bd9c..104c76a9d 100644 --- a/tests/Engine/Shader/AccessMember.cpp +++ b/tests/Engine/Shader/AccessMember.cpp @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -18,7 +17,7 @@ std::string_view Trim(std::string_view str) return str; } -void ExpectingGLSL(const Nz::ShaderAst& shader, std::string_view expectedOutput) +void ExpectingGLSL(Nz::ShaderAst::StatementPtr& shader, std::string_view expectedOutput) { Nz::GlslWriter writer; @@ -30,7 +29,7 @@ void ExpectingGLSL(const Nz::ShaderAst& shader, std::string_view expectedOutput) REQUIRE(subset == expectedOutput); } -void ExpectingSpirV(const Nz::ShaderAst& shader, std::string_view expectedOutput) +void ExpectingSpirV(Nz::ShaderAst::StatementPtr& shader, std::string_view expectedOutput) { Nz::SpirvWriter writer; auto spirv = writer.Generate(shader); @@ -53,42 +52,53 @@ SCENARIO("Shader generation", "[Shader]") { SECTION("Nested member loading") { - Nz::ShaderAst baseShader(Nz::ShaderStageType::Vertex); - baseShader.AddStruct("innerStruct", { - { - "field", - Nz::ShaderNodes::BasicType::Float3 - } - }); - - baseShader.AddStruct("outerStruct", { - { - "s", - "innerStruct" - } - }); + std::vector statements; - baseShader.AddUniform("ubo", "outerStruct"); - baseShader.AddOutput("result", Nz::ShaderNodes::BasicType::Float1); + Nz::ShaderAst::StructDescription innerStructDesc; + { + innerStructDesc.name = "innerStruct"; + auto& member = innerStructDesc.members.emplace_back(); + member.name = "field"; + member.type = Nz::ShaderAst::VectorType{ 3, Nz::ShaderAst::PrimitiveType::Float32 }; + } + statements.push_back(Nz::ShaderBuilder::DeclareStruct(std::move(innerStructDesc))); + + Nz::ShaderAst::StructDescription outerStruct; + { + outerStruct.name = "outerStruct"; + auto& member = outerStruct.members.emplace_back(); + member.name = "s"; + member.type = Nz::ShaderAst::IdentifierType{ "innerStruct" }; + } + statements.push_back(Nz::ShaderBuilder::DeclareStruct(std::move(outerStruct))); + + auto external = std::make_unique(); + external->externalVars.push_back({ + std::nullopt, + "ubo", + Nz::ShaderAst::IdentifierType{ "outerStruct" } + }); + statements.push_back(std::move(external)); SECTION("Nested AccessMember") { - Nz::ShaderAst shader = baseShader; + auto ubo = Nz::ShaderBuilder::Identifier("ubo"); + auto firstAccess = Nz::ShaderBuilder::AccessMember(std::move(ubo), { "s" }); + auto secondAccess = Nz::ShaderBuilder::AccessMember(std::move(firstAccess), { "field" }); - auto uniform = Nz::ShaderBuilder::Uniform("ubo", "outerStruct"); - auto output = Nz::ShaderBuilder::Output("result", Nz::ShaderNodes::BasicType::Float1); + auto swizzle = Nz::ShaderBuilder::Swizzle(std::move(secondAccess), { Nz::ShaderAst::SwizzleComponent::Third }); + auto varDecl = Nz::ShaderBuilder::DeclareVariable("result", Nz::ShaderAst::PrimitiveType::Float32, std::move(swizzle)); - auto access = Nz::ShaderBuilder::Swizzle(Nz::ShaderBuilder::AccessMember(Nz::ShaderBuilder::AccessMember(Nz::ShaderBuilder::Identifier(uniform), 0, "innerStruct"), 0, Nz::ShaderNodes::BasicType::Float3), Nz::ShaderNodes::SwizzleComponent::Third); - auto assign = Nz::ShaderBuilder::Assign(Nz::ShaderBuilder::Identifier(output), access); + statements.push_back(Nz::ShaderBuilder::DeclareFunction("main", std::move(varDecl))); - shader.AddFunction("main", Nz::ShaderBuilder::ExprStatement(assign)); + Nz::ShaderAst::StatementPtr shader = Nz::ShaderBuilder::MultiStatement(std::move(statements)); SECTION("Generating GLSL") { ExpectingGLSL(shader, R"( void main() { - result = ubo.s.field.z; + float result = ubo.s.field.z; } )"); } @@ -97,6 +107,7 @@ void main() ExpectingSpirV(shader, R"( OpFunction OpLabel +OpVariable OpAccessChain OpAccessChain OpLoad @@ -109,22 +120,22 @@ OpFunctionEnd)"); SECTION("AccessMember with multiples fields") { - Nz::ShaderAst shader = baseShader; + auto ubo = Nz::ShaderBuilder::Identifier("ubo"); + auto access = Nz::ShaderBuilder::AccessMember(std::move(ubo), { "s", "field" }); - auto uniform = Nz::ShaderBuilder::Uniform("ubo", "outerStruct"); - auto output = Nz::ShaderBuilder::Output("result", Nz::ShaderNodes::BasicType::Float1); + auto swizzle = Nz::ShaderBuilder::Swizzle(std::move(access), { Nz::ShaderAst::SwizzleComponent::Third }); + auto varDecl = Nz::ShaderBuilder::DeclareVariable("result", Nz::ShaderAst::PrimitiveType::Float32, std::move(swizzle)); - auto access = Nz::ShaderBuilder::Swizzle(Nz::ShaderBuilder::AccessMember(Nz::ShaderBuilder::Identifier(uniform), std::vector{ 0, 0 }, Nz::ShaderNodes::BasicType::Float3), Nz::ShaderNodes::SwizzleComponent::Third); - auto assign = Nz::ShaderBuilder::Assign(Nz::ShaderBuilder::Identifier(output), access); + statements.push_back(Nz::ShaderBuilder::DeclareFunction("main", std::move(varDecl))); - shader.AddFunction("main", Nz::ShaderBuilder::ExprStatement(assign)); + Nz::ShaderAst::StatementPtr shader = Nz::ShaderBuilder::MultiStatement(std::move(statements)); SECTION("Generating GLSL") { ExpectingGLSL(shader, R"( void main() { - result = ubo.s.field.z; + float result = ubo.s.field.z; } )"); } @@ -133,6 +144,7 @@ void main() ExpectingSpirV(shader, R"( OpFunction OpLabel +OpVariable OpAccessChain OpLoad OpCompositeExtract From 0bb9c37a388af0a972adbf2dc87e585e12c5a71a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 14 Apr 2021 20:20:37 +0200 Subject: [PATCH 107/278] Shader/Lang: [[attribute]] => [attribute] --- include/Nazara/Shader/ShaderLangTokenList.hpp | 2 -- src/Nazara/Shader/ShaderLangLexer.cpp | 30 ++----------------- src/Nazara/Shader/ShaderLangParser.cpp | 16 +++++----- 3 files changed, 10 insertions(+), 38 deletions(-) diff --git a/include/Nazara/Shader/ShaderLangTokenList.hpp b/include/Nazara/Shader/ShaderLangTokenList.hpp index 9b818cd0b..183a16062 100644 --- a/include/Nazara/Shader/ShaderLangTokenList.hpp +++ b/include/Nazara/Shader/ShaderLangTokenList.hpp @@ -13,7 +13,6 @@ NAZARA_SHADERLANG_TOKEN(Assign) NAZARA_SHADERLANG_TOKEN(BoolFalse) NAZARA_SHADERLANG_TOKEN(BoolTrue) -NAZARA_SHADERLANG_TOKEN(ClosingAttribute) NAZARA_SHADERLANG_TOKEN(ClosingParenthesis) NAZARA_SHADERLANG_TOKEN(ClosingCurlyBracket) NAZARA_SHADERLANG_TOKEN(ClosingSquareBracket) @@ -38,7 +37,6 @@ NAZARA_SHADERLANG_TOKEN(Multiply) NAZARA_SHADERLANG_TOKEN(Minus) NAZARA_SHADERLANG_TOKEN(NotEqual) NAZARA_SHADERLANG_TOKEN(Plus) -NAZARA_SHADERLANG_TOKEN(OpenAttribute) NAZARA_SHADERLANG_TOKEN(OpenCurlyBracket) NAZARA_SHADERLANG_TOKEN(OpenSquareBracket) NAZARA_SHADERLANG_TOKEN(OpenParenthesis) diff --git a/src/Nazara/Shader/ShaderLangLexer.cpp b/src/Nazara/Shader/ShaderLangLexer.cpp index fbede99d0..0b084a014 100644 --- a/src/Nazara/Shader/ShaderLangLexer.cpp +++ b/src/Nazara/Shader/ShaderLangLexer.cpp @@ -227,34 +227,6 @@ namespace Nz::ShaderLang break; } - case '[': - { - char next = Peek(); - if (next == '[') - { - currentPos++; - tokenType = TokenType::OpenAttribute; - } - else - tokenType = TokenType::OpenSquareBracket; - - break; - } - - case ']': - { - char next = Peek(); - if (next == ']') - { - currentPos++; - tokenType = TokenType::ClosingAttribute; - } - else - tokenType = TokenType::ClosingSquareBracket; - - break; - } - case '=': { char next = Peek(); @@ -307,6 +279,8 @@ namespace Nz::ShaderLang case '}': tokenType = TokenType::ClosingCurlyBracket; break; case '(': tokenType = TokenType::OpenParenthesis; break; case ')': tokenType = TokenType::ClosingParenthesis; break; + case '[': tokenType = TokenType::OpenSquareBracket; break; + case ']': tokenType = TokenType::ClosingSquareBracket; break; default: { diff --git a/src/Nazara/Shader/ShaderLangParser.cpp b/src/Nazara/Shader/ShaderLangParser.cpp index 6df94d266..1bc9316b5 100644 --- a/src/Nazara/Shader/ShaderLangParser.cpp +++ b/src/Nazara/Shader/ShaderLangParser.cpp @@ -82,7 +82,7 @@ namespace Nz::ShaderLang attributes.clear(); break; - case TokenType::OpenAttribute: + case TokenType::OpenSquareBracket: assert(attributes.empty()); attributes = ParseAttributes(); break; @@ -262,7 +262,7 @@ namespace Nz::ShaderLang { std::vector attributes; - Expect(Advance(), TokenType::OpenAttribute); + Expect(Advance(), TokenType::OpenSquareBracket); bool expectComma = false; for (;;) @@ -270,10 +270,10 @@ namespace Nz::ShaderLang const Token& t = Peek(); ExpectNot(t, TokenType::EndOfStream); - if (t.type == TokenType::ClosingAttribute) + if (t.type == TokenType::ClosingSquareBracket) { - // Parse [[attribute1]] [[attribute2]] the same as [[attribute1, attribute2]] - if (Peek(1).type == TokenType::OpenAttribute) + // Parse [attribute1] [attribute2] the same as [attribute1, attribute2] + if (Peek(1).type == TokenType::OpenSquareBracket) { Consume(2); expectComma = false; @@ -316,7 +316,7 @@ namespace Nz::ShaderLang }); } - Expect(Advance(), TokenType::ClosingAttribute); + Expect(Advance(), TokenType::ClosingSquareBracket); return attributes; } @@ -354,7 +354,7 @@ namespace Nz::ShaderLang auto& extVar = externalStatement->externalVars.emplace_back(); - if (token.type == TokenType::OpenAttribute) + if (token.type == TokenType::OpenSquareBracket) { for (const auto& [attributeType, arg] : ParseAttributes()) { @@ -521,7 +521,7 @@ namespace Nz::ShaderLang auto& structField = description.members.emplace_back(); - if (token.type == TokenType::OpenAttribute) + if (token.type == TokenType::OpenSquareBracket) { for (const auto& [attributeType, attributeParam] : ParseAttributes()) { From 8515c9cea1b5fc08d5a07b371285a0e813ee6449 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 15 Apr 2021 08:10:13 +0200 Subject: [PATCH 108/278] Shader: Improve ShaderAstCloner --- include/Nazara/Shader/ShaderAstCloner.hpp | 54 ++-- src/Nazara/Shader/ShaderAstCloner.cpp | 315 ++++++++++------------ 2 files changed, 163 insertions(+), 206 deletions(-) diff --git a/include/Nazara/Shader/ShaderAstCloner.hpp b/include/Nazara/Shader/ShaderAstCloner.hpp index 08bb53227..8bd43c4fb 100644 --- a/include/Nazara/Shader/ShaderAstCloner.hpp +++ b/include/Nazara/Shader/ShaderAstCloner.hpp @@ -33,43 +33,33 @@ namespace Nz::ShaderAst virtual ExpressionPtr CloneExpression(ExpressionPtr& expr); virtual StatementPtr CloneStatement(StatementPtr& statement); + + virtual ExpressionPtr Clone(AccessMemberIdentifierExpression& node); + virtual ExpressionPtr Clone(AccessMemberIndexExpression& node); + virtual ExpressionPtr Clone(AssignExpression& node); + virtual ExpressionPtr Clone(BinaryExpression& node); + virtual ExpressionPtr Clone(CastExpression& node); + virtual ExpressionPtr Clone(ConditionalExpression& node); + virtual ExpressionPtr Clone(ConstantExpression& node); + virtual ExpressionPtr Clone(IdentifierExpression& node); + virtual ExpressionPtr Clone(IntrinsicExpression& node); + virtual ExpressionPtr Clone(SwizzleExpression& node); + virtual ExpressionPtr Clone(VariableExpression& node); + + virtual StatementPtr Clone(BranchStatement& node); + virtual StatementPtr Clone(ConditionalStatement& node); virtual StatementPtr Clone(DeclareExternalStatement& node); virtual StatementPtr Clone(DeclareFunctionStatement& node); virtual StatementPtr Clone(DeclareStructStatement& node); virtual StatementPtr Clone(DeclareVariableStatement& node); + virtual StatementPtr Clone(DiscardStatement& node); + virtual StatementPtr Clone(ExpressionStatement& node); + virtual StatementPtr Clone(MultiStatement& node); + virtual StatementPtr Clone(NoOpStatement& node); + virtual StatementPtr Clone(ReturnStatement& node); - virtual ExpressionPtr Clone(AccessMemberIdentifierExpression& node); - virtual ExpressionPtr Clone(AccessMemberIndexExpression& node); - virtual ExpressionPtr Clone(CastExpression& node); - virtual ExpressionPtr Clone(IdentifierExpression& node); - virtual ExpressionPtr Clone(VariableExpression& node); - - using AstExpressionVisitor::Visit; - using AstStatementVisitor::Visit; - - void Visit(AccessMemberIdentifierExpression& node) override; - void Visit(AccessMemberIndexExpression& node) override; - void Visit(AssignExpression& node) override; - void Visit(BinaryExpression& node) override; - void Visit(CastExpression& node) override; - void Visit(ConditionalExpression& node) override; - void Visit(ConstantExpression& node) override; - void Visit(IdentifierExpression& node) override; - void Visit(IntrinsicExpression& node) override; - void Visit(SwizzleExpression& node) override; - void Visit(VariableExpression& node) override; - - void Visit(BranchStatement& node) override; - void Visit(ConditionalStatement& node) override; - void Visit(DeclareExternalStatement& node) override; - void Visit(DeclareFunctionStatement& node) override; - void Visit(DeclareStructStatement& node) override; - void Visit(DeclareVariableStatement& node) override; - void Visit(DiscardStatement& node) override; - void Visit(ExpressionStatement& node) override; - void Visit(MultiStatement& node) override; - void Visit(NoOpStatement& node) override; - void Visit(ReturnStatement& node) override; +#define NAZARA_SHADERAST_NODE(NodeType) void Visit(NodeType& node) override; +#include void PushExpression(ExpressionPtr expression); void PushStatement(StatementPtr statement); diff --git a/src/Nazara/Shader/ShaderAstCloner.cpp b/src/Nazara/Shader/ShaderAstCloner.cpp index 1a80e654f..efa5be3a5 100644 --- a/src/Nazara/Shader/ShaderAstCloner.cpp +++ b/src/Nazara/Shader/ShaderAstCloner.cpp @@ -42,6 +42,32 @@ namespace Nz::ShaderAst return PopStatement(); } + StatementPtr AstCloner::Clone(BranchStatement& node) + { + auto clone = std::make_unique(); + clone->condStatements.reserve(node.condStatements.size()); + + for (auto& cond : node.condStatements) + { + auto& condStatement = clone->condStatements.emplace_back(); + condStatement.condition = CloneExpression(cond.condition); + condStatement.statement = CloneStatement(cond.statement); + } + + clone->elseStatement = CloneStatement(node.elseStatement); + + return clone; + } + + StatementPtr AstCloner::Clone(ConditionalStatement& node) + { + auto clone = std::make_unique(); + clone->conditionName = node.conditionName; + clone->statement = CloneStatement(node.statement); + + return clone; + } + StatementPtr AstCloner::Clone(DeclareExternalStatement& node) { auto clone = std::make_unique(); @@ -88,6 +114,42 @@ namespace Nz::ShaderAst return clone; } + StatementPtr AstCloner::Clone(DiscardStatement& /*node*/) + { + return std::make_unique(); + } + + StatementPtr AstCloner::Clone(ExpressionStatement& node) + { + auto clone = std::make_unique(); + clone->expression = CloneExpression(node.expression); + + return clone; + } + + StatementPtr AstCloner::Clone(MultiStatement& node) + { + auto clone = std::make_unique(); + clone->statements.reserve(node.statements.size()); + for (auto& statement : node.statements) + clone->statements.push_back(CloneStatement(statement)); + + return clone; + } + + StatementPtr AstCloner::Clone(NoOpStatement& /*node*/) + { + return std::make_unique(); + } + + StatementPtr AstCloner::Clone(ReturnStatement& node) + { + auto clone = std::make_unique(); + clone->returnExpr = CloneExpression(node.returnExpr); + + return clone; + } + ExpressionPtr AstCloner::Clone(AccessMemberIdentifierExpression& node) { auto clone = std::make_unique(); @@ -110,6 +172,30 @@ namespace Nz::ShaderAst return clone; } + ExpressionPtr AstCloner::Clone(AssignExpression& node) + { + auto clone = std::make_unique(); + clone->op = node.op; + clone->left = CloneExpression(node.left); + clone->right = CloneExpression(node.right); + + clone->cachedExpressionType = node.cachedExpressionType; + + return clone; + } + + ExpressionPtr AstCloner::Clone(BinaryExpression& node) + { + auto clone = std::make_unique(); + clone->op = node.op; + clone->left = CloneExpression(node.left); + clone->right = CloneExpression(node.right); + + clone->cachedExpressionType = node.cachedExpressionType; + + return clone; + } + ExpressionPtr AstCloner::Clone(CastExpression& node) { auto clone = std::make_unique(); @@ -129,6 +215,28 @@ namespace Nz::ShaderAst return clone; } + ExpressionPtr AstCloner::Clone(ConditionalExpression& node) + { + auto clone = std::make_unique(); + clone->conditionName = node.conditionName; + clone->falsePath = CloneExpression(node.falsePath); + clone->truePath = CloneExpression(node.truePath); + + clone->cachedExpressionType = node.cachedExpressionType; + + return clone; + } + + ExpressionPtr AstCloner::Clone(ConstantExpression& node) + { + auto clone = std::make_unique(); + clone->value = node.value; + + clone->cachedExpressionType = node.cachedExpressionType; + + return clone; + } + ExpressionPtr AstCloner::Clone(IdentifierExpression& node) { auto clone = std::make_unique(); @@ -139,6 +247,32 @@ namespace Nz::ShaderAst return clone; } + ExpressionPtr AstCloner::Clone(IntrinsicExpression& node) + { + auto clone = std::make_unique(); + clone->intrinsic = node.intrinsic; + + clone->parameters.reserve(node.parameters.size()); + for (auto& parameter : node.parameters) + clone->parameters.push_back(CloneExpression(parameter)); + + clone->cachedExpressionType = node.cachedExpressionType; + + return clone; + } + + ExpressionPtr AstCloner::Clone(SwizzleExpression& node) + { + auto clone = std::make_unique(); + clone->componentCount = node.componentCount; + clone->components = node.components; + clone->expression = CloneExpression(node.expression); + + clone->cachedExpressionType = node.cachedExpressionType; + + return clone; + } + ExpressionPtr AstCloner::Clone(VariableExpression& node) { auto clone = std::make_unique(); @@ -149,184 +283,17 @@ namespace Nz::ShaderAst return clone; } - void AstCloner::Visit(AccessMemberIdentifierExpression& node) - { - return PushExpression(Clone(node)); +#define NAZARA_SHADERAST_EXPRESSION(NodeType) void AstCloner::Visit(NodeType& node) \ + { \ + PushExpression(Clone(node)); \ } - void AstCloner::Visit(AccessMemberIndexExpression& node) - { - return PushExpression(Clone(node)); +#define NAZARA_SHADERAST_STATEMENT(NodeType) void AstCloner::Visit(NodeType& node) \ + { \ + PushStatement(Clone(node)); \ } - void AstCloner::Visit(AssignExpression& node) - { - auto clone = std::make_unique(); - clone->op = node.op; - clone->left = CloneExpression(node.left); - clone->right = CloneExpression(node.right); - - clone->cachedExpressionType = node.cachedExpressionType; - - PushExpression(std::move(clone)); - } - - void AstCloner::Visit(BinaryExpression& node) - { - auto clone = std::make_unique(); - clone->op = node.op; - clone->left = CloneExpression(node.left); - clone->right = CloneExpression(node.right); - - clone->cachedExpressionType = node.cachedExpressionType; - - PushExpression(std::move(clone)); - } - - void AstCloner::Visit(CastExpression& node) - { - PushExpression(Clone(node)); - } - - void AstCloner::Visit(ConditionalExpression& node) - { - auto clone = std::make_unique(); - clone->conditionName = node.conditionName; - clone->falsePath = CloneExpression(node.falsePath); - clone->truePath = CloneExpression(node.truePath); - - clone->cachedExpressionType = node.cachedExpressionType; - - PushExpression(std::move(clone)); - } - - void AstCloner::Visit(ConstantExpression& node) - { - auto clone = std::make_unique(); - clone->value = node.value; - - clone->cachedExpressionType = node.cachedExpressionType; - - PushExpression(std::move(clone)); - } - - void AstCloner::Visit(IdentifierExpression& node) - { - PushExpression(Clone(node)); - } - - void AstCloner::Visit(IntrinsicExpression& node) - { - auto clone = std::make_unique(); - clone->intrinsic = node.intrinsic; - - clone->parameters.reserve(node.parameters.size()); - for (auto& parameter : node.parameters) - clone->parameters.push_back(CloneExpression(parameter)); - - clone->cachedExpressionType = node.cachedExpressionType; - - PushExpression(std::move(clone)); - } - - void AstCloner::Visit(SwizzleExpression& node) - { - auto clone = std::make_unique(); - clone->componentCount = node.componentCount; - clone->components = node.components; - clone->expression = CloneExpression(node.expression); - - clone->cachedExpressionType = node.cachedExpressionType; - - PushExpression(std::move(clone)); - } - - void AstCloner::Visit(VariableExpression& node) - { - PushExpression(Clone(node)); - } - - void AstCloner::Visit(BranchStatement& node) - { - auto clone = std::make_unique(); - clone->condStatements.reserve(node.condStatements.size()); - - for (auto& cond : node.condStatements) - { - auto& condStatement = clone->condStatements.emplace_back(); - condStatement.condition = CloneExpression(cond.condition); - condStatement.statement = CloneStatement(cond.statement); - } - - clone->elseStatement = CloneStatement(node.elseStatement); - - PushStatement(std::move(clone)); - } - - void AstCloner::Visit(ConditionalStatement& node) - { - auto clone = std::make_unique(); - clone->conditionName = node.conditionName; - clone->statement = CloneStatement(node.statement); - - PushStatement(std::move(clone)); - } - - void AstCloner::Visit(DeclareExternalStatement& node) - { - PushStatement(Clone(node)); - } - - void AstCloner::Visit(DeclareFunctionStatement& node) - { - PushStatement(Clone(node)); - } - - void AstCloner::Visit(DeclareStructStatement& node) - { - PushStatement(Clone(node)); - } - - void AstCloner::Visit(DeclareVariableStatement& node) - { - PushStatement(Clone(node)); - } - - void AstCloner::Visit(DiscardStatement& /*node*/) - { - PushStatement(std::make_unique()); - } - - void AstCloner::Visit(ExpressionStatement& node) - { - auto clone = std::make_unique(); - clone->expression = CloneExpression(node.expression); - - PushStatement(std::move(clone)); - } - - void AstCloner::Visit(MultiStatement& node) - { - auto clone = std::make_unique(); - clone->statements.reserve(node.statements.size()); - for (auto& statement : node.statements) - clone->statements.push_back(CloneStatement(statement)); - - PushStatement(std::move(clone)); - } - - void AstCloner::Visit(NoOpStatement& /*node*/) - { - PushStatement(std::make_unique()); - } - - void AstCloner::Visit(ReturnStatement& node) - { - auto clone = std::make_unique(); - clone->returnExpr = CloneExpression(node.returnExpr); - - PushStatement(std::move(clone)); - } +#include void AstCloner::PushExpression(ExpressionPtr expression) { From afe3a0ea93c1274b7e1af552d7ddd7972d11e7ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 15 Apr 2021 11:20:56 +0200 Subject: [PATCH 109/278] Shader: Merge AstScopedVisitor, AstValidator and TransformVisitor to SanitizeVisitor --- include/Nazara/Shader.hpp | 1 - include/Nazara/Shader/Ast/SanitizeVisitor.hpp | 112 +++ ...ansformVisitor.inl => SanitizeVisitor.inl} | 24 +- .../Nazara/Shader/Ast/TransformVisitor.hpp | 90 -- include/Nazara/Shader/GlslWriter.hpp | 4 +- include/Nazara/Shader/GlslWriter.inl | 9 + include/Nazara/Shader/ShaderAstCloner.hpp | 6 +- include/Nazara/Shader/ShaderAstCloner.inl | 16 + .../Nazara/Shader/ShaderAstScopedVisitor.hpp | 68 -- .../Nazara/Shader/ShaderAstScopedVisitor.inl | 38 - include/Nazara/Shader/ShaderAstValidator.hpp | 66 -- include/Nazara/Shader/ShaderAstValidator.inl | 16 - src/Nazara/Shader/Ast/SanitizeVisitor.cpp | 832 ++++++++++++++++++ src/Nazara/Shader/Ast/TransformVisitor.cpp | 228 ----- src/Nazara/Shader/GlslWriter.cpp | 58 +- src/Nazara/Shader/ShaderAstCloner.cpp | 14 +- src/Nazara/Shader/ShaderAstScopedVisitor.cpp | 110 --- src/Nazara/Shader/ShaderAstValidator.cpp | 642 -------------- src/Nazara/Shader/SpirvWriter.cpp | 32 +- 19 files changed, 1027 insertions(+), 1339 deletions(-) create mode 100644 include/Nazara/Shader/Ast/SanitizeVisitor.hpp rename include/Nazara/Shader/Ast/{TransformVisitor.inl => SanitizeVisitor.inl} (57%) delete mode 100644 include/Nazara/Shader/Ast/TransformVisitor.hpp delete mode 100644 include/Nazara/Shader/ShaderAstScopedVisitor.hpp delete mode 100644 include/Nazara/Shader/ShaderAstScopedVisitor.inl delete mode 100644 include/Nazara/Shader/ShaderAstValidator.hpp delete mode 100644 include/Nazara/Shader/ShaderAstValidator.inl create mode 100644 src/Nazara/Shader/Ast/SanitizeVisitor.cpp delete mode 100644 src/Nazara/Shader/Ast/TransformVisitor.cpp delete mode 100644 src/Nazara/Shader/ShaderAstScopedVisitor.cpp delete mode 100644 src/Nazara/Shader/ShaderAstValidator.cpp diff --git a/include/Nazara/Shader.hpp b/include/Nazara/Shader.hpp index 65cd2025e..122296819 100644 --- a/include/Nazara/Shader.hpp +++ b/include/Nazara/Shader.hpp @@ -41,7 +41,6 @@ #include #include #include -#include #include #include #include diff --git a/include/Nazara/Shader/Ast/SanitizeVisitor.hpp b/include/Nazara/Shader/Ast/SanitizeVisitor.hpp new file mode 100644 index 000000000..43167a7f8 --- /dev/null +++ b/include/Nazara/Shader/Ast/SanitizeVisitor.hpp @@ -0,0 +1,112 @@ +// 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_SHADERAST_TRANSFORMVISITOR_HPP +#define NAZARA_SHADERAST_TRANSFORMVISITOR_HPP + +#include +#include +#include +#include + +namespace Nz::ShaderAst +{ + class NAZARA_SHADER_API SanitizeVisitor final : AstCloner + { + public: + inline SanitizeVisitor(); + SanitizeVisitor(const SanitizeVisitor&) = delete; + SanitizeVisitor(SanitizeVisitor&&) = delete; + ~SanitizeVisitor() = default; + + StatementPtr Sanitize(StatementPtr& statement, std::string* error = nullptr); + + SanitizeVisitor& operator=(const SanitizeVisitor&) = delete; + SanitizeVisitor& operator=(SanitizeVisitor&&) = delete; + + private: + struct Identifier; + + const ExpressionType& CheckField(const ExpressionType& structType, const std::string* memberIdentifier, std::size_t remainingMembers, std::size_t* structIndices); + + using AstCloner::CloneExpression; + + ExpressionPtr Clone(AccessMemberIdentifierExpression& node) override; + ExpressionPtr Clone(AssignExpression& node) override; + ExpressionPtr Clone(BinaryExpression& node) override; + ExpressionPtr Clone(CastExpression& node) override; + ExpressionPtr Clone(ConditionalExpression& node) override; + ExpressionPtr Clone(ConstantExpression& node) override; + ExpressionPtr Clone(IdentifierExpression& node) override; + ExpressionPtr Clone(IntrinsicExpression& node) override; + ExpressionPtr Clone(SwizzleExpression& node) override; + + StatementPtr Clone(BranchStatement& node) override; + StatementPtr Clone(ConditionalStatement& node) override; + StatementPtr Clone(DeclareExternalStatement& node) override; + StatementPtr Clone(DeclareFunctionStatement& node) override; + StatementPtr Clone(DeclareStructStatement& node) override; + StatementPtr Clone(DeclareVariableStatement& node) override; + StatementPtr Clone(ExpressionStatement& node) override; + StatementPtr Clone(MultiStatement& node) override; + + inline const Identifier* FindIdentifier(const std::string_view& identifierName) const; + + Expression& MandatoryExpr(ExpressionPtr& node); + Statement& MandatoryStatement(StatementPtr& node); + void TypeMustMatch(ExpressionPtr& left, ExpressionPtr& right); + void TypeMustMatch(const ExpressionType& left, const ExpressionType& right); + + void PushScope(); + void PopScope(); + + inline std::size_t RegisterFunction(std::string name); + inline std::size_t RegisterStruct(std::string name, StructDescription description); + inline std::size_t RegisterVariable(std::string name, ExpressionType type); + + std::size_t ResolveStruct(const ExpressionType& exprType); + std::size_t ResolveStruct(const IdentifierType& identifierType); + std::size_t ResolveStruct(const StructType& structType); + std::size_t ResolveStruct(const UniformType& uniformType); + ExpressionType ResolveType(const ExpressionType& exprType); + + struct Alias + { + std::variant value; + }; + + struct Struct + { + std::size_t structIndex; + }; + + struct Variable + { + std::size_t varIndex; + }; + + struct Identifier + { + std::string name; + std::variant value; + }; + + std::size_t m_nextFuncIndex; + std::vector m_identifiersInScope; + std::vector m_structs; + std::vector m_variables; + std::vector m_scopeSizes; + + struct Context; + Context* m_context; + }; + + inline StatementPtr Sanitize(StatementPtr& ast, std::string* error = nullptr); +} + +#include + +#endif diff --git a/include/Nazara/Shader/Ast/TransformVisitor.inl b/include/Nazara/Shader/Ast/SanitizeVisitor.inl similarity index 57% rename from include/Nazara/Shader/Ast/TransformVisitor.inl rename to include/Nazara/Shader/Ast/SanitizeVisitor.inl index 07601b026..29a902b8a 100644 --- a/include/Nazara/Shader/Ast/TransformVisitor.inl +++ b/include/Nazara/Shader/Ast/SanitizeVisitor.inl @@ -2,18 +2,17 @@ // This file is part of the "Nazara Engine - Shader generator" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include namespace Nz::ShaderAst { - inline TransformVisitor::TransformVisitor() : - m_nextFuncIndex(0), - m_nextVarIndex(0) + inline SanitizeVisitor::SanitizeVisitor() : + m_nextFuncIndex(0) { } - inline auto TransformVisitor::FindIdentifier(const std::string_view& identifierName) const -> const Identifier* + inline auto SanitizeVisitor::FindIdentifier(const std::string_view& identifierName) const -> const Identifier* { auto it = std::find_if(m_identifiersInScope.rbegin(), m_identifiersInScope.rend(), [&](const Identifier& identifier) { return identifier.name == identifierName; }); if (it == m_identifiersInScope.rend()) @@ -22,14 +21,14 @@ namespace Nz::ShaderAst return &*it; } - inline std::size_t TransformVisitor::RegisterFunction(std::string name) + inline std::size_t SanitizeVisitor::RegisterFunction(std::string name) { std::size_t funcIndex = m_nextFuncIndex++; return funcIndex; } - inline std::size_t TransformVisitor::RegisterStruct(std::string name, StructDescription description) + inline std::size_t SanitizeVisitor::RegisterStruct(std::string name, StructDescription description) { std::size_t structIndex = m_structs.size(); m_structs.emplace_back(std::move(description)); @@ -44,9 +43,10 @@ namespace Nz::ShaderAst return structIndex; } - inline std::size_t TransformVisitor::RegisterVariable(std::string name) + inline std::size_t SanitizeVisitor::RegisterVariable(std::string name, ExpressionType type) { - std::size_t varIndex = m_nextVarIndex++; + std::size_t varIndex = m_variables.size(); + m_variables.emplace_back(std::move(type)); m_identifiersInScope.push_back({ std::move(name), @@ -57,6 +57,12 @@ namespace Nz::ShaderAst return varIndex; } + + StatementPtr Sanitize(StatementPtr& ast, std::string* error) + { + SanitizeVisitor sanitizer; + return sanitizer.Sanitize(ast, error); + } } #include diff --git a/include/Nazara/Shader/Ast/TransformVisitor.hpp b/include/Nazara/Shader/Ast/TransformVisitor.hpp deleted file mode 100644 index d2483a095..000000000 --- a/include/Nazara/Shader/Ast/TransformVisitor.hpp +++ /dev/null @@ -1,90 +0,0 @@ -// 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_SHADERAST_TRANSFORMVISITOR_HPP -#define NAZARA_SHADERAST_TRANSFORMVISITOR_HPP - -#include -#include -#include -#include - -namespace Nz::ShaderAst -{ - class NAZARA_SHADER_API TransformVisitor : AstCloner - { - public: - inline TransformVisitor(); - TransformVisitor(const TransformVisitor&) = delete; - TransformVisitor(TransformVisitor&&) = delete; - ~TransformVisitor() = default; - - StatementPtr Transform(StatementPtr& statement); - - TransformVisitor& operator=(const TransformVisitor&) = delete; - TransformVisitor& operator=(TransformVisitor&&) = delete; - - private: - struct Identifier; - - ExpressionPtr Clone(AccessMemberIdentifierExpression& node) override; - ExpressionPtr Clone(CastExpression& node) override; - ExpressionPtr Clone(IdentifierExpression& node) override; - ExpressionPtr CloneExpression(ExpressionPtr& expr) override; - - inline const Identifier* FindIdentifier(const std::string_view& identifierName) const; - - void PushScope(); - void PopScope(); - - inline std::size_t RegisterFunction(std::string name); - inline std::size_t RegisterStruct(std::string name, StructDescription description); - inline std::size_t RegisterVariable(std::string name); - - ExpressionType ResolveType(const ExpressionType& exprType); - - using AstCloner::Visit; - void Visit(BranchStatement& node) override; - void Visit(ConditionalStatement& node) override; - void Visit(DeclareExternalStatement& node) override; - void Visit(DeclareFunctionStatement& node) override; - void Visit(DeclareStructStatement& node) override; - void Visit(DeclareVariableStatement& node) override; - void Visit(MultiStatement& node) override; - - struct Alias - { - std::variant value; - }; - - struct Struct - { - std::size_t structIndex; - }; - - struct Variable - { - std::size_t varIndex; - }; - - struct Identifier - { - std::string name; - std::variant value; - }; - - private: - std::size_t m_nextFuncIndex; - std::size_t m_nextVarIndex; - std::vector m_identifiersInScope; - std::vector m_structs; - std::vector m_scopeSizes; - }; -} - -#include - -#endif diff --git a/include/Nazara/Shader/GlslWriter.hpp b/include/Nazara/Shader/GlslWriter.hpp index 99e68d9f0..faea46ef7 100644 --- a/include/Nazara/Shader/GlslWriter.hpp +++ b/include/Nazara/Shader/GlslWriter.hpp @@ -24,12 +24,12 @@ namespace Nz struct Environment; using ExtSupportCallback = std::function; - GlslWriter(); + inline GlslWriter(); GlslWriter(const GlslWriter&) = delete; GlslWriter(GlslWriter&&) = delete; ~GlslWriter() = default; - std::string Generate(ShaderAst::StatementPtr& shader, const States& conditions = {}); + inline std::string Generate(ShaderAst::StatementPtr& shader, const States& conditions = {}); std::string Generate(std::optional shaderStage, ShaderAst::StatementPtr& shader, const States& conditions = {}); void SetEnv(Environment environment); diff --git a/include/Nazara/Shader/GlslWriter.inl b/include/Nazara/Shader/GlslWriter.inl index 1ecd13aee..e8c4d052c 100644 --- a/include/Nazara/Shader/GlslWriter.inl +++ b/include/Nazara/Shader/GlslWriter.inl @@ -7,6 +7,15 @@ namespace Nz { + inline GlslWriter::GlslWriter() : + m_currentState(nullptr) + { + } + + inline std::string GlslWriter::Generate(ShaderAst::StatementPtr& shader, const States& conditions) + { + return Generate(std::nullopt, shader, conditions); + } } #include diff --git a/include/Nazara/Shader/ShaderAstCloner.hpp b/include/Nazara/Shader/ShaderAstCloner.hpp index 8bd43c4fb..0d034cab9 100644 --- a/include/Nazara/Shader/ShaderAstCloner.hpp +++ b/include/Nazara/Shader/ShaderAstCloner.hpp @@ -30,9 +30,11 @@ namespace Nz::ShaderAst AstCloner& operator=(AstCloner&&) = delete; protected: - virtual ExpressionPtr CloneExpression(ExpressionPtr& expr); - virtual StatementPtr CloneStatement(StatementPtr& statement); + inline ExpressionPtr CloneExpression(ExpressionPtr& expr); + inline StatementPtr CloneStatement(StatementPtr& statement); + virtual ExpressionPtr CloneExpression(Expression& expr); + virtual StatementPtr CloneStatement(Statement& statement); virtual ExpressionPtr Clone(AccessMemberIdentifierExpression& node); virtual ExpressionPtr Clone(AccessMemberIndexExpression& node); diff --git a/include/Nazara/Shader/ShaderAstCloner.inl b/include/Nazara/Shader/ShaderAstCloner.inl index 20a829343..9d099bf63 100644 --- a/include/Nazara/Shader/ShaderAstCloner.inl +++ b/include/Nazara/Shader/ShaderAstCloner.inl @@ -7,6 +7,22 @@ namespace Nz::ShaderAst { + ExpressionPtr AstCloner::CloneExpression(ExpressionPtr& expr) + { + if (!expr) + return nullptr; + + return CloneExpression(*expr); + } + + StatementPtr AstCloner::CloneStatement(StatementPtr& statement) + { + if (!statement) + return nullptr; + + return CloneStatement(*statement); + } + inline ExpressionPtr Clone(ExpressionPtr& node) { AstCloner cloner; diff --git a/include/Nazara/Shader/ShaderAstScopedVisitor.hpp b/include/Nazara/Shader/ShaderAstScopedVisitor.hpp deleted file mode 100644 index e212a30b5..000000000 --- a/include/Nazara/Shader/ShaderAstScopedVisitor.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// 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_SCOPED_VISITOR_HPP -#define NAZARA_SHADER_SCOPED_VISITOR_HPP - -#include -#include -#include - -namespace Nz::ShaderAst -{ - class NAZARA_SHADER_API AstScopedVisitor : public AstRecursiveVisitor - { - public: - struct Identifier; - - AstScopedVisitor() = default; - ~AstScopedVisitor() = default; - - inline const Identifier* FindIdentifier(const std::string_view& identifierName) const; - - void ScopedVisit(StatementPtr& nodePtr); - - using AstRecursiveVisitor::Visit; - void Visit(BranchStatement& node) override; - void Visit(ConditionalStatement& node) override; - void Visit(DeclareExternalStatement& node) override; - void Visit(DeclareFunctionStatement& node) override; - void Visit(DeclareStructStatement& node) override; - void Visit(DeclareVariableStatement& node) override; - void Visit(MultiStatement& node) override; - - struct Alias - { - std::variant value; - }; - - struct Variable - { - ExpressionType type; - }; - - struct Identifier - { - std::string name; - std::variant value; - }; - - protected: - void PushScope(); - void PopScope(); - - inline void RegisterStruct(StructDescription structDesc); - inline void RegisterVariable(std::string name, ExpressionType type); - - private: - std::vector m_identifiersInScope; - std::vector m_scopeSizes; - }; -} - -#include - -#endif diff --git a/include/Nazara/Shader/ShaderAstScopedVisitor.inl b/include/Nazara/Shader/ShaderAstScopedVisitor.inl deleted file mode 100644 index 67042069a..000000000 --- a/include/Nazara/Shader/ShaderAstScopedVisitor.inl +++ /dev/null @@ -1,38 +0,0 @@ -// 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 -#include - -namespace Nz::ShaderAst -{ - inline auto AstScopedVisitor::FindIdentifier(const std::string_view& identifierName) const -> const Identifier* - { - auto it = std::find_if(m_identifiersInScope.rbegin(), m_identifiersInScope.rend(), [&](const Identifier& identifier) { return identifier.name == identifierName; }); - if (it == m_identifiersInScope.rend()) - return nullptr; - - return &*it; - } - - inline void AstScopedVisitor::RegisterStruct(StructDescription structDesc) - { - std::string name = structDesc.name; - - m_identifiersInScope.push_back({ - std::move(name), - std::move(structDesc) - }); - } - - inline void AstScopedVisitor::RegisterVariable(std::string name, ExpressionType type) - { - m_identifiersInScope.push_back({ - std::move(name), - Variable { std::move(type) } - }); - } -} - -#include diff --git a/include/Nazara/Shader/ShaderAstValidator.hpp b/include/Nazara/Shader/ShaderAstValidator.hpp deleted file mode 100644 index 14a491682..000000000 --- a/include/Nazara/Shader/ShaderAstValidator.hpp +++ /dev/null @@ -1,66 +0,0 @@ -// 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_SHADERVALIDATOR_HPP -#define NAZARA_SHADERVALIDATOR_HPP - -#include -#include -#include -#include - -namespace Nz::ShaderAst -{ - class NAZARA_SHADER_API AstValidator final : public AstScopedVisitor - { - public: - inline AstValidator(); - AstValidator(const AstValidator&) = delete; - AstValidator(AstValidator&&) = delete; - ~AstValidator() = default; - - bool Validate(StatementPtr& node, std::string* error = nullptr); - - private: - const ExpressionType& GetExpressionType(Expression& expression); - Expression& MandatoryExpr(ExpressionPtr& node); - Statement& MandatoryStatement(StatementPtr& node); - void TypeMustMatch(ExpressionPtr& left, ExpressionPtr& right); - void TypeMustMatch(const ExpressionType& left, const ExpressionType& right); - - ExpressionType CheckField(const std::string& structName, const std::string* memberIdentifier, std::size_t remainingMembers); - const ExpressionType& ResolveAlias(const ExpressionType& expressionType); - - void Visit(AccessMemberIdentifierExpression& node) override; - void Visit(AssignExpression& node) override; - void Visit(BinaryExpression& node) override; - void Visit(CastExpression& node) override; - void Visit(ConstantExpression& node) override; - void Visit(ConditionalExpression& node) override; - void Visit(IdentifierExpression& node) override; - void Visit(IntrinsicExpression& node) override; - void Visit(SwizzleExpression& node) override; - - void Visit(BranchStatement& node) override; - void Visit(ConditionalStatement& node) override; - void Visit(DeclareExternalStatement& node) override; - void Visit(DeclareFunctionStatement& node) override; - void Visit(DeclareStructStatement& node) override; - void Visit(DeclareVariableStatement& node) override; - void Visit(ExpressionStatement& node) override; - void Visit(MultiStatement& node) override; - - struct Context; - - Context* m_context; - }; - - NAZARA_SHADER_API bool ValidateAst(StatementPtr& node, std::string* error = nullptr); -} - -#include - -#endif diff --git a/include/Nazara/Shader/ShaderAstValidator.inl b/include/Nazara/Shader/ShaderAstValidator.inl deleted file mode 100644 index 2020badd4..000000000 --- a/include/Nazara/Shader/ShaderAstValidator.inl +++ /dev/null @@ -1,16 +0,0 @@ -// 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 -#include - -namespace Nz::ShaderAst -{ - AstValidator::AstValidator() : - m_context(nullptr) - { - } -} - -#include diff --git a/src/Nazara/Shader/Ast/SanitizeVisitor.cpp b/src/Nazara/Shader/Ast/SanitizeVisitor.cpp new file mode 100644 index 000000000..6da7ef18a --- /dev/null +++ b/src/Nazara/Shader/Ast/SanitizeVisitor.cpp @@ -0,0 +1,832 @@ +// 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 +#include +#include +#include +#include +#include +#include + +namespace Nz::ShaderAst +{ + namespace + { + struct AstError + { + std::string errMsg; + }; + + template + std::unique_ptr static_unique_pointer_cast(std::unique_ptr&& ptr) + { + return std::unique_ptr(static_cast(ptr.release())); + } + } + + struct SanitizeVisitor::Context + { + std::array entryFunctions = {}; + std::unordered_set declaredExternalVar; + std::unordered_set usedBindingIndexes; + }; + + StatementPtr SanitizeVisitor::Sanitize(StatementPtr& nodePtr, std::string* error) + { + StatementPtr clone; + + Context currentContext; + + m_context = ¤tContext; + CallOnExit resetContext([&] { m_context = nullptr; }); + + PushScope(); //< Global scope + { + try + { + clone = AstCloner::Clone(nodePtr); + } + catch (const AstError& err) + { + if (!error) + throw std::runtime_error(err.errMsg); + + *error = err.errMsg; + } + } + PopScope(); + + return clone; + } + + const ExpressionType& SanitizeVisitor::CheckField(const ExpressionType& structType, const std::string* memberIdentifier, std::size_t remainingMembers, std::size_t* structIndices) + { + std::size_t structIndex = ResolveStruct(structType); + + *structIndices++ = structIndex; + + assert(structIndex < m_structs.size()); + const StructDescription& s = m_structs[structIndex]; + + auto memberIt = std::find_if(s.members.begin(), s.members.end(), [&](const auto& field) { return field.name == memberIdentifier[0]; }); + if (memberIt == s.members.end()) + throw AstError{ "unknown field " + memberIdentifier[0] }; + + const auto& member = *memberIt; + + if (remainingMembers > 1) + return CheckField(member.type, memberIdentifier + 1, remainingMembers - 1, structIndices); + else + return member.type; + } + + ExpressionPtr SanitizeVisitor::Clone(AccessMemberIdentifierExpression& node) + { + auto structExpr = CloneExpression(MandatoryExpr(node.structExpr)); + + const ExpressionType& exprType = GetExpressionType(*structExpr); + + // Transform to AccessMemberIndexExpression + auto accessMemberIndex = std::make_unique(); + accessMemberIndex->structExpr = std::move(structExpr); + + StackArray structIndices = NazaraStackArrayNoInit(std::size_t, node.memberIdentifiers.size()); + + accessMemberIndex->cachedExpressionType = ResolveType(CheckField(exprType, node.memberIdentifiers.data(), node.memberIdentifiers.size(), structIndices.data())); + + accessMemberIndex->memberIndices.resize(node.memberIdentifiers.size()); + for (std::size_t i = 0; i < node.memberIdentifiers.size(); ++i) + { + std::size_t structIndex = structIndices[i]; + assert(structIndex < m_structs.size()); + const StructDescription& structDesc = m_structs[structIndex]; + + auto it = std::find_if(structDesc.members.begin(), structDesc.members.end(), [&](const auto& member) { return member.name == node.memberIdentifiers[i]; }); + assert(it != structDesc.members.end()); + + accessMemberIndex->memberIndices[i] = std::distance(structDesc.members.begin(), it); + } + + return accessMemberIndex; + } + + ExpressionPtr SanitizeVisitor::Clone(AssignExpression& node) + { + MandatoryExpr(node.left); + MandatoryExpr(node.right); + + if (GetExpressionCategory(*node.left) != ExpressionCategory::LValue) + throw AstError{ "Assignation is only possible with a l-value" }; + + auto clone = static_unique_pointer_cast(AstCloner::Clone(node)); + + TypeMustMatch(clone->left, clone->right); + clone->cachedExpressionType = GetExpressionType(*clone->right); + + return clone; + } + + ExpressionPtr SanitizeVisitor::Clone(BinaryExpression& node) + { + auto clone = static_unique_pointer_cast(AstCloner::Clone(node)); + + const ExpressionType& leftExprType = GetExpressionType(MandatoryExpr(clone->left)); + if (!IsPrimitiveType(leftExprType) && !IsMatrixType(leftExprType) && !IsVectorType(leftExprType)) + throw AstError{ "left expression type does not support binary operation" }; + + const ExpressionType& rightExprType = GetExpressionType(MandatoryExpr(clone->right)); + if (!IsPrimitiveType(rightExprType) && !IsMatrixType(rightExprType) && !IsVectorType(rightExprType)) + throw AstError{ "right expression type does not support binary operation" }; + + if (IsPrimitiveType(leftExprType)) + { + PrimitiveType leftType = std::get(leftExprType); + switch (clone->op) + { + case BinaryType::CompGe: + case BinaryType::CompGt: + case BinaryType::CompLe: + case BinaryType::CompLt: + if (leftType == PrimitiveType::Boolean) + throw AstError{ "this operation is not supported for booleans" }; + + TypeMustMatch(clone->left, clone->right); + + clone->cachedExpressionType = PrimitiveType::Boolean; + break; + + case BinaryType::Add: + case BinaryType::CompEq: + case BinaryType::CompNe: + case BinaryType::Subtract: + TypeMustMatch(clone->left, clone->right); + + clone->cachedExpressionType = leftExprType; + break; + + case BinaryType::Multiply: + case BinaryType::Divide: + { + switch (leftType) + { + case PrimitiveType::Float32: + case PrimitiveType::Int32: + case PrimitiveType::UInt32: + { + if (IsMatrixType(rightExprType)) + { + TypeMustMatch(leftType, std::get(rightExprType).type); + clone->cachedExpressionType = rightExprType; + } + else if (IsPrimitiveType(rightExprType)) + { + TypeMustMatch(leftType, rightExprType); + clone->cachedExpressionType = leftExprType; + } + else if (IsVectorType(rightExprType)) + { + TypeMustMatch(leftType, std::get(rightExprType).type); + clone->cachedExpressionType = rightExprType; + } + else + throw AstError{ "incompatible types" }; + + break; + } + + case PrimitiveType::Boolean: + throw AstError{ "this operation is not supported for booleans" }; + + default: + throw AstError{ "incompatible types" }; + } + } + } + } + else if (IsMatrixType(leftExprType)) + { + const MatrixType& leftType = std::get(leftExprType); + switch (clone->op) + { + case BinaryType::CompGe: + case BinaryType::CompGt: + case BinaryType::CompLe: + case BinaryType::CompLt: + case BinaryType::CompEq: + case BinaryType::CompNe: + TypeMustMatch(clone->left, clone->right); + clone->cachedExpressionType = PrimitiveType::Boolean; + break; + + case BinaryType::Add: + case BinaryType::Subtract: + TypeMustMatch(clone->left, clone->right); + clone->cachedExpressionType = leftExprType; + break; + + case BinaryType::Multiply: + case BinaryType::Divide: + { + if (IsMatrixType(rightExprType)) + { + TypeMustMatch(leftExprType, rightExprType); + clone->cachedExpressionType = leftExprType; //< FIXME + } + else if (IsPrimitiveType(rightExprType)) + { + TypeMustMatch(leftType.type, rightExprType); + clone->cachedExpressionType = leftExprType; + } + else if (IsVectorType(rightExprType)) + { + const VectorType& rightType = std::get(rightExprType); + TypeMustMatch(leftType.type, rightType.type); + + if (leftType.columnCount != rightType.componentCount) + throw AstError{ "incompatible types" }; + + clone->cachedExpressionType = rightExprType; + } + else + throw AstError{ "incompatible types" }; + } + } + } + else if (IsVectorType(leftExprType)) + { + const VectorType& leftType = std::get(leftExprType); + switch (clone->op) + { + case BinaryType::CompGe: + case BinaryType::CompGt: + case BinaryType::CompLe: + case BinaryType::CompLt: + case BinaryType::CompEq: + case BinaryType::CompNe: + TypeMustMatch(clone->left, clone->right); + clone->cachedExpressionType = PrimitiveType::Boolean; + break; + + case BinaryType::Add: + case BinaryType::Subtract: + TypeMustMatch(clone->left, clone->right); + clone->cachedExpressionType = leftExprType; + break; + + case BinaryType::Multiply: + case BinaryType::Divide: + { + if (IsPrimitiveType(rightExprType)) + { + TypeMustMatch(leftType.type, rightExprType); + clone->cachedExpressionType = rightExprType; + } + else if (IsVectorType(rightExprType)) + { + TypeMustMatch(leftType, rightExprType); + clone->cachedExpressionType = rightExprType; + } + else + throw AstError{ "incompatible types" }; + } + } + } + + return clone; + } + + ExpressionPtr SanitizeVisitor::Clone(CastExpression& node) + { + auto clone = static_unique_pointer_cast(AstCloner::Clone(node)); + + auto GetComponentCount = [](const ExpressionType& exprType) -> std::size_t + { + if (IsVectorType(exprType)) + return std::get(exprType).componentCount; + else + { + assert(IsPrimitiveType(exprType)); + return 1; + } + }; + + std::size_t componentCount = 0; + std::size_t requiredComponents = GetComponentCount(clone->targetType); + + for (auto& exprPtr : clone->expressions) + { + if (!exprPtr) + break; + + const ExpressionType& exprType = GetExpressionType(*exprPtr); + if (!IsPrimitiveType(exprType) && !IsVectorType(exprType)) + throw AstError{ "incompatible type" }; + + componentCount += GetComponentCount(exprType); + } + + if (componentCount != requiredComponents) + throw AstError{ "component count doesn't match required component count" }; + + clone->targetType = ResolveType(clone->targetType); + clone->cachedExpressionType = clone->targetType; + + return clone; + } + + ExpressionPtr SanitizeVisitor::Clone(ConditionalExpression& node) + { + MandatoryExpr(node.truePath); + MandatoryExpr(node.falsePath); + + auto clone = static_unique_pointer_cast(AstCloner::Clone(node)); + + const ExpressionType& leftExprType = GetExpressionType(*clone->truePath); + if (leftExprType != GetExpressionType(*clone->falsePath)) + throw AstError{ "true path type must match false path type" }; + + clone->cachedExpressionType = leftExprType; + + return clone; + } + + ExpressionPtr SanitizeVisitor::Clone(ConstantExpression& node) + { + auto clone = static_unique_pointer_cast(AstCloner::Clone(node)); + clone->cachedExpressionType = std::visit([&](auto&& arg) -> ShaderAst::ExpressionType + { + using T = std::decay_t; + + if constexpr (std::is_same_v) + return PrimitiveType::Boolean; + else if constexpr (std::is_same_v) + return PrimitiveType::Float32; + else if constexpr (std::is_same_v) + return PrimitiveType::Int32; + else if constexpr (std::is_same_v) + return PrimitiveType::UInt32; + else if constexpr (std::is_same_v) + return VectorType{ 2, PrimitiveType::Float32 }; + else if constexpr (std::is_same_v) + return VectorType{ 3, PrimitiveType::Float32 }; + else if constexpr (std::is_same_v) + return VectorType{ 4, PrimitiveType::Float32 }; + else if constexpr (std::is_same_v) + return VectorType{ 2, PrimitiveType::Int32 }; + else if constexpr (std::is_same_v) + return VectorType{ 3, PrimitiveType::Int32 }; + else if constexpr (std::is_same_v) + return VectorType{ 4, PrimitiveType::Int32 }; + else + static_assert(AlwaysFalse::value, "non-exhaustive visitor"); + }, clone->value); + + return clone; + } + + ExpressionPtr SanitizeVisitor::Clone(IdentifierExpression& node) + { + assert(m_context); + + const Identifier* identifier = FindIdentifier(node.identifier); + if (!identifier) + throw AstError{ "unknown identifier " + node.identifier }; + + if (!std::holds_alternative(identifier->value)) + throw AstError{ "expected variable identifier" }; + + const Variable& variable = std::get(identifier->value); + + // Replace IdentifierExpression by VariableExpression + auto varExpr = std::make_unique(); + varExpr->cachedExpressionType = m_variables[variable.varIndex]; + varExpr->variableId = variable.varIndex; + + return varExpr; + } + + ExpressionPtr SanitizeVisitor::Clone(IntrinsicExpression& node) + { + auto clone = static_unique_pointer_cast(AstCloner::Clone(node)); + + // Parameter validation + switch (clone->intrinsic) + { + case IntrinsicType::CrossProduct: + case IntrinsicType::DotProduct: + { + if (clone->parameters.size() != 2) + throw AstError { "Expected two parameters" }; + + for (auto& param : clone->parameters) + MandatoryExpr(param); + + const ExpressionType& type = GetExpressionType(*clone->parameters.front()); + + for (std::size_t i = 1; i < clone->parameters.size(); ++i) + { + if (type != GetExpressionType(*clone->parameters[i])) + throw AstError{ "All type must match" }; + } + + break; + } + + case IntrinsicType::SampleTexture: + { + if (clone->parameters.size() != 2) + throw AstError{ "Expected two parameters" }; + + for (auto& param : clone->parameters) + MandatoryExpr(param); + + if (!IsSamplerType(GetExpressionType(*clone->parameters[0]))) + throw AstError{ "First parameter must be a sampler" }; + + if (!IsVectorType(GetExpressionType(*clone->parameters[1]))) + throw AstError{ "Second parameter must be a vector" }; + } + } + + // Return type attribution + switch (clone->intrinsic) + { + case IntrinsicType::CrossProduct: + { + const ExpressionType& type = GetExpressionType(*clone->parameters.front()); + if (type != ExpressionType{ VectorType{ 3, PrimitiveType::Float32 } }) + throw AstError{ "CrossProduct only works with vec3 expressions" }; + + clone->cachedExpressionType = type; + break; + } + + case IntrinsicType::DotProduct: + { + ExpressionType type = GetExpressionType(*clone->parameters.front()); + if (!IsVectorType(type)) + throw AstError{ "DotProduct expects vector types" }; + + clone->cachedExpressionType = std::get(type).type; + break; + } + + case IntrinsicType::SampleTexture: + { + clone->cachedExpressionType = VectorType{ 4, std::get(GetExpressionType(*clone->parameters.front())).sampledType }; + break; + } + } + + return clone; + } + + ExpressionPtr SanitizeVisitor::Clone(SwizzleExpression& node) + { + if (node.componentCount > 4) + throw AstError{ "Cannot swizzle more than four elements" }; + + MandatoryExpr(node.expression); + + auto clone = static_unique_pointer_cast(AstCloner::Clone(node)); + + const ExpressionType& exprType = GetExpressionType(*clone->expression); + if (!IsPrimitiveType(exprType) && !IsVectorType(exprType)) + throw AstError{ "Cannot swizzle this type" }; + + PrimitiveType baseType; + if (IsPrimitiveType(exprType)) + baseType = std::get(exprType); + else + baseType = std::get(exprType).type; + + if (clone->componentCount > 1) + { + clone->cachedExpressionType = VectorType{ + clone->componentCount, + baseType + }; + } + else + clone->cachedExpressionType = baseType; + + return clone; + } + + StatementPtr SanitizeVisitor::Clone(BranchStatement& node) + { + auto clone = std::make_unique(); + clone->condStatements.reserve(node.condStatements.size()); + + for (auto& cond : node.condStatements) + { + PushScope(); + + auto& condStatement = clone->condStatements.emplace_back(); + condStatement.condition = CloneExpression(MandatoryExpr(cond.condition)); + + const ExpressionType& condType = GetExpressionType(*condStatement.condition); + if (!IsPrimitiveType(condType) || std::get(condType) != PrimitiveType::Boolean) + throw AstError{ "branch expressions must resolve to boolean type" }; + + condStatement.statement = CloneStatement(MandatoryStatement(cond.statement)); + + PopScope(); + } + + if (node.elseStatement) + { + PushScope(); + clone->elseStatement = CloneStatement(node.elseStatement); + PopScope(); + } + + return clone; + } + + StatementPtr SanitizeVisitor::Clone(ConditionalStatement& node) + { + MandatoryStatement(node.statement); + + PushScope(); + + auto clone = static_unique_pointer_cast(AstCloner::Clone(node)); + + PopScope(); + + return clone; + } + + StatementPtr SanitizeVisitor::Clone(DeclareExternalStatement& node) + { + assert(m_context); + + for (const auto& extVar : node.externalVars) + { + if (extVar.bindingIndex) + { + unsigned int bindingIndex = extVar.bindingIndex.value(); + if (m_context->usedBindingIndexes.find(bindingIndex) != m_context->usedBindingIndexes.end()) + throw AstError{ "Binding #" + std::to_string(bindingIndex) + " is already in use" }; + + m_context->usedBindingIndexes.insert(bindingIndex); + } + + if (m_context->declaredExternalVar.find(extVar.name) != m_context->declaredExternalVar.end()) + throw AstError{ "External variable " + extVar.name + " is already declared" }; + + m_context->declaredExternalVar.insert(extVar.name); + } + + auto clone = static_unique_pointer_cast(AstCloner::Clone(node)); + for (auto& extVar : clone->externalVars) + { + extVar.type = ResolveType(extVar.type); + + ExpressionType varType = extVar.type; + if (IsUniformType(extVar.type)) + varType = std::get(std::get(varType).containedType); + + std::size_t varIndex = RegisterVariable(extVar.name, std::move(varType)); + if (!clone->varIndex) + clone->varIndex = varIndex; //< First external variable index is node variable index + } + + return clone; + } + + StatementPtr SanitizeVisitor::Clone(DeclareFunctionStatement& node) + { + if (node.entryStage) + { + ShaderStageType stageType = *node.entryStage; + + if (m_context->entryFunctions[UnderlyingCast(stageType)]) + throw AstError{ "the same entry type has been defined multiple times" }; + + m_context->entryFunctions[UnderlyingCast(stageType)] = &node; + + if (node.parameters.size() > 1) + throw AstError{ "entry functions can either take one struct parameter or no parameter" }; + } + + auto clone = std::make_unique(); + clone->entryStage = node.entryStage; + clone->name = node.name; + clone->funcIndex = m_nextFuncIndex++; + clone->parameters = node.parameters; + clone->returnType = ResolveType(node.returnType); + + PushScope(); + { + for (auto& parameter : clone->parameters) + { + parameter.type = ResolveType(parameter.type); + std::size_t varIndex = RegisterVariable(parameter.name, parameter.type); + if (!clone->varIndex) + clone->varIndex = varIndex; //< First parameter variable index is node variable index + } + + clone->statements.reserve(node.statements.size()); + for (auto& statement : node.statements) + clone->statements.push_back(CloneStatement(MandatoryStatement(statement))); + } + PopScope(); + + return clone; + } + + StatementPtr SanitizeVisitor::Clone(DeclareStructStatement& node) + { + std::unordered_set declaredMembers; + + for (auto& member : node.description.members) + { + if (declaredMembers.find(member.name) != declaredMembers.end()) + throw AstError{ "struct member " + member.name + " found multiple time" }; + + declaredMembers.insert(member.name); + } + + auto clone = static_unique_pointer_cast(AstCloner::Clone(node)); + + for (auto& member : clone->description.members) + member.type = ResolveType(member.type); + + clone->structIndex = RegisterStruct(clone->description.name, clone->description); + + return clone; + } + + StatementPtr SanitizeVisitor::Clone(DeclareVariableStatement& node) + { + auto clone = static_unique_pointer_cast(AstCloner::Clone(node)); + if (IsNoType(clone->varType)) + { + if (!clone->initialExpression) + throw AstError{ "variable must either have a type or an initial value" }; + + clone->varType = ResolveType(GetExpressionType(*clone->initialExpression)); + } + else + clone->varType = ResolveType(clone->varType); + + clone->varIndex = RegisterVariable(clone->varName, clone->varType); + + return clone; + } + + StatementPtr SanitizeVisitor::Clone(ExpressionStatement& node) + { + MandatoryExpr(node.expression); + + return AstCloner::Clone(node); + } + + StatementPtr SanitizeVisitor::Clone(MultiStatement& node) + { + for (auto& statement : node.statements) + MandatoryStatement(statement); + + PushScope(); + + auto clone = static_unique_pointer_cast(AstCloner::Clone(node)); + + PopScope(); + + return clone; + } + + Expression& SanitizeVisitor::MandatoryExpr(ExpressionPtr& node) + { + if (!node) + throw AstError{ "Invalid expression" }; + + return *node; + } + + Statement& SanitizeVisitor::MandatoryStatement(StatementPtr& node) + { + if (!node) + throw AstError{ "Invalid statement" }; + + return *node; + } + + void SanitizeVisitor::PushScope() + { + m_scopeSizes.push_back(m_identifiersInScope.size()); + } + + void SanitizeVisitor::PopScope() + { + assert(!m_scopeSizes.empty()); + m_identifiersInScope.resize(m_scopeSizes.back()); + m_scopeSizes.pop_back(); + } + + std::size_t SanitizeVisitor::ResolveStruct(const ExpressionType& exprType) + { + return std::visit([&](auto&& arg) -> std::size_t + { + using T = std::decay_t; + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + return ResolveStruct(arg); + else if constexpr (std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v) + { + throw AstError{ "expression is not a structure" }; + } + else + static_assert(AlwaysFalse::value, "non-exhaustive visitor"); + }, exprType); + } + + std::size_t SanitizeVisitor::ResolveStruct(const IdentifierType& identifierType) + { + const Identifier* identifier = FindIdentifier(identifierType.name); + if (!identifier) + throw AstError{ "unknown identifier " + identifierType.name }; + + if (!std::holds_alternative(identifier->value)) + throw AstError{ identifierType.name + " is not a struct" }; + + return std::get(identifier->value).structIndex; + } + + std::size_t SanitizeVisitor::ResolveStruct(const StructType& structType) + { + return structType.structIndex; + } + + std::size_t SanitizeVisitor::ResolveStruct(const UniformType& uniformType) + { + return std::visit([&](auto&& arg) -> std::size_t + { + using T = std::decay_t; + + if constexpr (std::is_same_v || std::is_same_v) + return ResolveStruct(arg); + else + static_assert(AlwaysFalse::value, "non-exhaustive visitor"); + }, uniformType.containedType); + } + + ExpressionType SanitizeVisitor::ResolveType(const ExpressionType& exprType) + { + return std::visit([&](auto&& arg) -> ExpressionType + { + using T = std::decay_t; + + if constexpr (std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v) + { + return exprType; + } + else if constexpr (std::is_same_v) + { + const Identifier* identifier = FindIdentifier(arg.name); + if (!identifier) + throw AstError{ "unknown identifier " + arg.name }; + + if (!std::holds_alternative(identifier->value)) + throw AstError{ "expected type identifier" }; + + return StructType{ std::get(identifier->value).structIndex }; + } + else if constexpr (std::is_same_v) + { + return std::visit([&](auto&& containedArg) + { + ExpressionType resolvedType = ResolveType(containedArg); + assert(std::holds_alternative(resolvedType)); + + return UniformType{ std::get(resolvedType) }; + }, arg.containedType); + } + else + static_assert(AlwaysFalse::value, "non-exhaustive visitor"); + }, exprType); + } + + void SanitizeVisitor::TypeMustMatch(ExpressionPtr& left, ExpressionPtr& right) + { + return TypeMustMatch(GetExpressionType(*left), GetExpressionType(*right)); + } + + void SanitizeVisitor::TypeMustMatch(const ExpressionType& left, const ExpressionType& right) + { + if (left != right) + throw AstError{ "Left expression type must match right expression type" }; + } +} diff --git a/src/Nazara/Shader/Ast/TransformVisitor.cpp b/src/Nazara/Shader/Ast/TransformVisitor.cpp deleted file mode 100644 index 5e8e660ab..000000000 --- a/src/Nazara/Shader/Ast/TransformVisitor.cpp +++ /dev/null @@ -1,228 +0,0 @@ -// 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 -#include -#include - -namespace Nz::ShaderAst -{ - StatementPtr TransformVisitor::Transform(StatementPtr& nodePtr) - { - StatementPtr clone; - - PushScope(); //< Global scope - { - clone = AstCloner::Clone(nodePtr); - } - PopScope(); - - return clone; - } - - void TransformVisitor::Visit(BranchStatement& node) - { - for (auto& cond : node.condStatements) - { - PushScope(); - { - cond.condition->Visit(*this); - cond.statement->Visit(*this); - } - PopScope(); - } - - if (node.elseStatement) - { - PushScope(); - { - node.elseStatement->Visit(*this); - } - PopScope(); - } - } - - void TransformVisitor::Visit(ConditionalStatement& node) - { - PushScope(); - { - AstCloner::Visit(node); - } - PopScope(); - } - - ExpressionType TransformVisitor::ResolveType(const ExpressionType& exprType) - { - return std::visit([&](auto&& arg) -> ExpressionType - { - using T = std::decay_t; - - if constexpr (std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v) - { - return exprType; - } - else if constexpr (std::is_same_v) - { - const Identifier* identifier = FindIdentifier(arg.name); - assert(identifier); - assert(std::holds_alternative(identifier->value)); - - return StructType{ std::get(identifier->value).structIndex }; - } - else if constexpr (std::is_same_v) - { - return std::visit([&](auto&& containedArg) - { - ExpressionType resolvedType = ResolveType(containedArg); - assert(std::holds_alternative(resolvedType)); - - return UniformType{ std::get(resolvedType) }; - }, arg.containedType); - } - else - static_assert(AlwaysFalse::value, "non-exhaustive visitor"); - }, exprType); - } - - void TransformVisitor::Visit(DeclareExternalStatement& node) - { - for (auto& extVar : node.externalVars) - { - extVar.type = ResolveType(extVar.type); - - std::size_t varIndex = RegisterVariable(extVar.name); - if (!node.varIndex) - node.varIndex = varIndex; - } - - AstCloner::Visit(node); - } - - void TransformVisitor::Visit(DeclareFunctionStatement& node) - { - node.funcIndex = m_nextFuncIndex++; - node.returnType = ResolveType(node.returnType); - for (auto& parameter : node.parameters) - parameter.type = ResolveType(parameter.type); - - PushScope(); - { - for (auto& parameter : node.parameters) - { - std::size_t varIndex = RegisterVariable(parameter.name); - if (!node.varIndex) - node.varIndex = varIndex; - } - - AstCloner::Visit(node); - } - PopScope(); - } - - void TransformVisitor::Visit(DeclareStructStatement& node) - { - for (auto& member : node.description.members) - member.type = ResolveType(member.type); - - node.structIndex = RegisterStruct(node.description.name, node.description); - - AstCloner::Visit(node); - } - - void TransformVisitor::Visit(DeclareVariableStatement& node) - { - node.varType = ResolveType(node.varType); - node.varIndex = RegisterVariable(node.varName); - - AstCloner::Visit(node); - } - - void TransformVisitor::Visit(MultiStatement& node) - { - PushScope(); - { - AstCloner::Visit(node); - } - PopScope(); - } - - ExpressionPtr TransformVisitor::Clone(AccessMemberIdentifierExpression& node) - { - auto accessMemberIndex = std::make_unique(); - accessMemberIndex->structExpr = CloneExpression(node.structExpr); - accessMemberIndex->cachedExpressionType = node.cachedExpressionType; - accessMemberIndex->memberIndices.resize(node.memberIdentifiers.size()); - - ExpressionType exprType = GetExpressionType(*node.structExpr); - for (std::size_t i = 0; i < node.memberIdentifiers.size(); ++i) - { - exprType = ResolveType(exprType); - assert(std::holds_alternative(exprType)); - - std::size_t structIndex = std::get(exprType).structIndex; - assert(structIndex < m_structs.size()); - const StructDescription& structDesc = m_structs[structIndex]; - - auto it = std::find_if(structDesc.members.begin(), structDesc.members.end(), [&](const auto& member) { return member.name == node.memberIdentifiers[i]; }); - assert(it != structDesc.members.end()); - - accessMemberIndex->memberIndices[i] = std::distance(structDesc.members.begin(), it); - exprType = it->type; - } - - return accessMemberIndex; - } - - ExpressionPtr TransformVisitor::Clone(CastExpression& node) - { - ExpressionPtr expr = AstCloner::Clone(node); - - CastExpression* castExpr = static_cast(expr.get()); - castExpr->targetType = ResolveType(castExpr->targetType); - - return expr; - } - - ExpressionPtr TransformVisitor::Clone(IdentifierExpression& node) - { - const Identifier* identifier = FindIdentifier(node.identifier); - assert(identifier); - assert(std::holds_alternative(identifier->value)); - - auto varExpr = std::make_unique(); - varExpr->cachedExpressionType = node.cachedExpressionType; - varExpr->variableId = std::get(identifier->value).varIndex; - - return varExpr; - } - - ExpressionPtr TransformVisitor::CloneExpression(ExpressionPtr& expr) - { - ExpressionPtr exprPtr = AstCloner::CloneExpression(expr); - if (exprPtr) - { - assert(exprPtr->cachedExpressionType); - *exprPtr->cachedExpressionType = ResolveType(*exprPtr->cachedExpressionType); - } - - return exprPtr; - } - - void TransformVisitor::PushScope() - { - m_scopeSizes.push_back(m_identifiersInScope.size()); - } - - void TransformVisitor::PopScope() - { - assert(!m_scopeSizes.empty()); - m_identifiersInScope.resize(m_scopeSizes.back()); - m_scopeSizes.pop_back(); - } -} diff --git a/src/Nazara/Shader/GlslWriter.cpp b/src/Nazara/Shader/GlslWriter.cpp index a509245e4..c354ffbd1 100644 --- a/src/Nazara/Shader/GlslWriter.cpp +++ b/src/Nazara/Shader/GlslWriter.cpp @@ -8,9 +8,9 @@ #include #include #include +#include #include -#include -#include +#include #include #include #include @@ -31,36 +31,29 @@ namespace Nz return it->second; } - struct PreVisitor : ShaderAst::AstCloner + struct PreVisitor : ShaderAst::AstRecursiveVisitor { - using AstCloner::Clone; + using AstRecursiveVisitor::Visit; - ShaderAst::StatementPtr Clone(ShaderAst::DeclareFunctionStatement& node) override + void Visit(ShaderAst::DeclareFunctionStatement& node) override { - auto clone = AstCloner::Clone(node); - assert(clone->GetType() == ShaderAst::NodeType::DeclareFunctionStatement); - - ShaderAst::DeclareFunctionStatement* func = static_cast(clone.get()); - - // Remove function if it's an entry point of another type than the one selected + // Dismiss function if it's an entry point of another type than the one selected if (selectedStage) { if (node.entryStage) { ShaderStageType stage = *node.entryStage; if (stage != *selectedStage) - return ShaderBuilder::NoOp(); + return; - entryPoint = func; + entryPoint = &node; } } else { assert(!entryPoint); - entryPoint = func; + entryPoint = &node; } - - return clone; } std::optional selectedStage; @@ -99,17 +92,6 @@ namespace Nz unsigned int indentLevel = 0; }; - - GlslWriter::GlslWriter() : - m_currentState(nullptr) - { - } - - std::string GlslWriter::Generate(ShaderAst::StatementPtr& shader, const States& conditions) - { - return Generate(std::nullopt, shader, conditions); - } - std::string GlslWriter::Generate(std::optional shaderStage, ShaderAst::StatementPtr& shader, const States& conditions) { State state; @@ -121,17 +103,11 @@ namespace Nz m_currentState = nullptr; }); - std::string error; - if (!ShaderAst::ValidateAst(shader, &error)) - throw std::runtime_error("Invalid shader AST: " + error); - - ShaderAst::TransformVisitor transformVisitor; - ShaderAst::StatementPtr transformedShader = transformVisitor.Transform(shader); + ShaderAst::StatementPtr sanitizedAst = ShaderAst::Sanitize(shader); PreVisitor previsitor; previsitor.selectedStage = shaderStage; - - ShaderAst::StatementPtr adaptedShader = previsitor.Clone(transformedShader); + sanitizedAst->Visit(previsitor); if (!previsitor.entryPoint) throw std::runtime_error("missing entry point"); @@ -140,7 +116,7 @@ namespace Nz AppendHeader(); - adaptedShader->Visit(*this); + sanitizedAst->Visit(*this); return state.stream.str(); } @@ -361,6 +337,9 @@ namespace Nz void GlslWriter::HandleEntryPoint(ShaderAst::DeclareFunctionStatement& node) { + if (m_currentState->entryFunc != &node) + return; //< Ignore other entry points + HandleInOut(); AppendLine("void main()"); EnterScope(); @@ -712,11 +691,10 @@ namespace Nz { NazaraAssert(m_currentState, "This function should only be called while processing an AST"); - if (m_currentState->entryFunc == &node) + if (node.entryStage) return HandleEntryPoint(node); - assert(node.varIndex); - std::size_t varIndex = *node.varIndex; + std::optional varIndexOpt = node.varIndex; Append(node.returnType); Append(" "); @@ -731,6 +709,8 @@ namespace Nz Append(" "); Append(node.parameters[i].name); + assert(varIndexOpt); + std::size_t& varIndex = *varIndexOpt; RegisterVariable(varIndex++, node.parameters[i].name); } Append(")\n"); diff --git a/src/Nazara/Shader/ShaderAstCloner.cpp b/src/Nazara/Shader/ShaderAstCloner.cpp index efa5be3a5..af1348c72 100644 --- a/src/Nazara/Shader/ShaderAstCloner.cpp +++ b/src/Nazara/Shader/ShaderAstCloner.cpp @@ -24,21 +24,15 @@ namespace Nz::ShaderAst return PopStatement(); } - ExpressionPtr AstCloner::CloneExpression(ExpressionPtr& expr) + ExpressionPtr AstCloner::CloneExpression(Expression& expr) { - if (!expr) - return nullptr; - - expr->Visit(*this); + expr.Visit(*this); return PopExpression(); } - StatementPtr AstCloner::CloneStatement(StatementPtr& statement) + StatementPtr AstCloner::CloneStatement(Statement& statement) { - if (!statement) - return nullptr; - - statement->Visit(*this); + statement.Visit(*this); return PopStatement(); } diff --git a/src/Nazara/Shader/ShaderAstScopedVisitor.cpp b/src/Nazara/Shader/ShaderAstScopedVisitor.cpp deleted file mode 100644 index 39e80470e..000000000 --- a/src/Nazara/Shader/ShaderAstScopedVisitor.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// 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 -#include - -namespace Nz::ShaderAst -{ - void AstScopedVisitor::ScopedVisit(StatementPtr& nodePtr) - { - PushScope(); //< Global scope - { - nodePtr->Visit(*this); - } - PopScope(); - } - - void AstScopedVisitor::Visit(BranchStatement& node) - { - for (auto& cond : node.condStatements) - { - PushScope(); - { - cond.condition->Visit(*this); - cond.statement->Visit(*this); - } - PopScope(); - } - - if (node.elseStatement) - { - PushScope(); - { - node.elseStatement->Visit(*this); - } - PopScope(); - } - } - - void AstScopedVisitor::Visit(ConditionalStatement& node) - { - PushScope(); - { - AstRecursiveVisitor::Visit(node); - } - PopScope(); - } - - void AstScopedVisitor::Visit(DeclareExternalStatement& node) - { - for (auto& extVar : node.externalVars) - { - ExpressionType subType = extVar.type; - if (IsUniformType(subType)) - subType = std::get(std::get(subType).containedType); - - RegisterVariable(extVar.name, std::move(subType)); - } - - AstRecursiveVisitor::Visit(node); - } - - void AstScopedVisitor::Visit(DeclareFunctionStatement& node) - { - PushScope(); - { - for (auto& parameter : node.parameters) - RegisterVariable(parameter.name, parameter.type); - - AstRecursiveVisitor::Visit(node); - } - PopScope(); - } - - void AstScopedVisitor::Visit(DeclareStructStatement& node) - { - RegisterStruct(node.description); - - AstRecursiveVisitor::Visit(node); - } - - void AstScopedVisitor::Visit(DeclareVariableStatement& node) - { - RegisterVariable(node.varName, node.varType); - - AstRecursiveVisitor::Visit(node); - } - - void AstScopedVisitor::Visit(MultiStatement& node) - { - PushScope(); - { - AstRecursiveVisitor::Visit(node); - } - PopScope(); - } - - void AstScopedVisitor::PushScope() - { - m_scopeSizes.push_back(m_identifiersInScope.size()); - } - - void AstScopedVisitor::PopScope() - { - assert(!m_scopeSizes.empty()); - m_identifiersInScope.resize(m_scopeSizes.back()); - m_scopeSizes.pop_back(); - } -} diff --git a/src/Nazara/Shader/ShaderAstValidator.cpp b/src/Nazara/Shader/ShaderAstValidator.cpp deleted file mode 100644 index d83e0dbce..000000000 --- a/src/Nazara/Shader/ShaderAstValidator.cpp +++ /dev/null @@ -1,642 +0,0 @@ -// 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 -#include -#include -#include -#include -#include - -namespace Nz::ShaderAst -{ - struct AstError - { - std::string errMsg; - }; - - struct AstValidator::Context - { - std::array entryFunctions = {}; - std::unordered_set declaredExternalVar; - std::unordered_set usedBindingIndexes; - }; - - bool AstValidator::Validate(StatementPtr& node, std::string* error) - { - try - { - Context currentContext; - - m_context = ¤tContext; - CallOnExit resetContext([&] { m_context = nullptr; }); - - ScopedVisit(node); - return true; - } - catch (const AstError& e) - { - if (error) - *error = e.errMsg; - - return false; - } - } - - const ExpressionType& AstValidator::GetExpressionType(Expression& expression) - { - assert(expression.cachedExpressionType); - return ResolveAlias(expression.cachedExpressionType.value()); - } - - Expression& AstValidator::MandatoryExpr(ExpressionPtr& node) - { - if (!node) - throw AstError{ "Invalid expression" }; - - return *node; - } - - Statement& AstValidator::MandatoryStatement(StatementPtr& node) - { - if (!node) - throw AstError{ "Invalid statement" }; - - return *node; - } - - void AstValidator::TypeMustMatch(ExpressionPtr& left, ExpressionPtr& right) - { - return TypeMustMatch(GetExpressionType(*left), GetExpressionType(*right)); - } - - void AstValidator::TypeMustMatch(const ExpressionType& left, const ExpressionType& right) - { - if (left != right) - throw AstError{ "Left expression type must match right expression type" }; - } - - ExpressionType AstValidator::CheckField(const std::string& structName, const std::string* memberIdentifier, std::size_t remainingMembers) - { - const Identifier* identifier = FindIdentifier(structName); - if (!identifier) - throw AstError{ "unknown identifier " + structName }; - - if (!std::holds_alternative(identifier->value)) - throw AstError{ "identifier is not a struct" }; - - const StructDescription& s = std::get(identifier->value); - - auto memberIt = std::find_if(s.members.begin(), s.members.end(), [&](const auto& field) { return field.name == memberIdentifier[0]; }); - if (memberIt == s.members.end()) - throw AstError{ "unknown field " + memberIdentifier[0]}; - - const auto& member = *memberIt; - - if (remainingMembers > 1) - return CheckField(std::get(member.type).name, memberIdentifier + 1, remainingMembers - 1); - else - return member.type; - } - - const ExpressionType& AstValidator::ResolveAlias(const ExpressionType& expressionType) - { - if (!IsIdentifierType(expressionType)) - return expressionType; - - const Identifier* identifier = FindIdentifier(std::get(expressionType).name); - if (identifier && std::holds_alternative(identifier->value)) - { - const Alias& alias = std::get(identifier->value); - return std::visit([&](auto&& arg) -> const ShaderAst::ExpressionType& - { - using T = std::decay_t; - - if constexpr (std::is_same_v) - return arg; - else - static_assert(AlwaysFalse::value, "non-exhaustive visitor"); - }, alias.value); - } - - return expressionType; - } - - void AstValidator::Visit(AccessMemberIdentifierExpression& node) - { - // Register expressions types - AstScopedVisitor::Visit(node); - - ExpressionType exprType = GetExpressionType(MandatoryExpr(node.structExpr)); - if (!IsIdentifierType(exprType)) - throw AstError{ "expression is not a structure" }; - - const std::string& structName = std::get(exprType).name; - - node.cachedExpressionType = CheckField(structName, node.memberIdentifiers.data(), node.memberIdentifiers.size()); - } - - void AstValidator::Visit(AssignExpression& node) - { - MandatoryExpr(node.left); - MandatoryExpr(node.right); - - // Register expressions types - AstScopedVisitor::Visit(node); - - TypeMustMatch(node.left, node.right); - - if (GetExpressionCategory(*node.left) != ExpressionCategory::LValue) - throw AstError { "Assignation is only possible with a l-value" }; - - node.cachedExpressionType = GetExpressionType(*node.right); - } - - void AstValidator::Visit(BinaryExpression& node) - { - // Register expression type - AstScopedVisitor::Visit(node); - - ExpressionType leftExprType = GetExpressionType(MandatoryExpr(node.left)); - if (!IsPrimitiveType(leftExprType) && !IsMatrixType(leftExprType) && !IsVectorType(leftExprType)) - throw AstError{ "left expression type does not support binary operation" }; - - ExpressionType rightExprType = GetExpressionType(MandatoryExpr(node.right)); - if (!IsPrimitiveType(rightExprType) && !IsMatrixType(rightExprType) && !IsVectorType(rightExprType)) - throw AstError{ "right expression type does not support binary operation" }; - - if (IsPrimitiveType(leftExprType)) - { - PrimitiveType leftType = std::get(leftExprType); - switch (node.op) - { - case BinaryType::CompGe: - case BinaryType::CompGt: - case BinaryType::CompLe: - case BinaryType::CompLt: - if (leftType == PrimitiveType::Boolean) - throw AstError{ "this operation is not supported for booleans" }; - - TypeMustMatch(node.left, node.right); - - node.cachedExpressionType = PrimitiveType::Boolean; - break; - - case BinaryType::Add: - case BinaryType::CompEq: - case BinaryType::CompNe: - case BinaryType::Subtract: - TypeMustMatch(node.left, node.right); - - node.cachedExpressionType = leftExprType; - break; - - case BinaryType::Multiply: - case BinaryType::Divide: - { - switch (leftType) - { - case PrimitiveType::Float32: - case PrimitiveType::Int32: - case PrimitiveType::UInt32: - { - if (IsMatrixType(rightExprType)) - { - TypeMustMatch(leftType, std::get(rightExprType).type); - node.cachedExpressionType = rightExprType; - } - else if (IsPrimitiveType(rightExprType)) - { - TypeMustMatch(leftType, rightExprType); - node.cachedExpressionType = leftExprType; - } - else if (IsVectorType(rightExprType)) - { - TypeMustMatch(leftType, std::get(rightExprType).type); - node.cachedExpressionType = rightExprType; - } - else - throw AstError{ "incompatible types" }; - - break; - } - - case PrimitiveType::Boolean: - throw AstError{ "this operation is not supported for booleans" }; - - default: - throw AstError{ "incompatible types" }; - } - } - } - } - else if (IsMatrixType(leftExprType)) - { - const MatrixType& leftType = std::get(leftExprType); - switch (node.op) - { - case BinaryType::CompGe: - case BinaryType::CompGt: - case BinaryType::CompLe: - case BinaryType::CompLt: - case BinaryType::CompEq: - case BinaryType::CompNe: - TypeMustMatch(node.left, node.right); - node.cachedExpressionType = PrimitiveType::Boolean; - break; - - case BinaryType::Add: - case BinaryType::Subtract: - TypeMustMatch(node.left, node.right); - node.cachedExpressionType = leftExprType; - break; - - case BinaryType::Multiply: - case BinaryType::Divide: - { - if (IsMatrixType(rightExprType)) - { - TypeMustMatch(leftExprType, rightExprType); - node.cachedExpressionType = leftExprType; //< FIXME - } - else if (IsPrimitiveType(rightExprType)) - { - TypeMustMatch(leftType.type, rightExprType); - node.cachedExpressionType = leftExprType; - } - else if (IsVectorType(rightExprType)) - { - const VectorType& rightType = std::get(rightExprType); - TypeMustMatch(leftType.type, rightType.type); - - if (leftType.columnCount != rightType.componentCount) - throw AstError{ "incompatible types" }; - - node.cachedExpressionType = rightExprType; - } - else - throw AstError{ "incompatible types" }; - } - } - } - else if (IsVectorType(leftExprType)) - { - const VectorType& leftType = std::get(leftExprType); - switch (node.op) - { - case BinaryType::CompGe: - case BinaryType::CompGt: - case BinaryType::CompLe: - case BinaryType::CompLt: - case BinaryType::CompEq: - case BinaryType::CompNe: - TypeMustMatch(node.left, node.right); - node.cachedExpressionType = PrimitiveType::Boolean; - break; - - case BinaryType::Add: - case BinaryType::Subtract: - TypeMustMatch(node.left, node.right); - node.cachedExpressionType = leftExprType; - break; - - case BinaryType::Multiply: - case BinaryType::Divide: - { - if (IsPrimitiveType(rightExprType)) - { - TypeMustMatch(leftType.type, rightExprType); - node.cachedExpressionType = rightExprType; - } - else if (IsVectorType(rightExprType)) - { - TypeMustMatch(leftType, rightExprType); - node.cachedExpressionType = rightExprType; - } - else - throw AstError{ "incompatible types" }; - } - } - } - } - - void AstValidator::Visit(CastExpression& node) - { - AstScopedVisitor::Visit(node); - - auto GetComponentCount = [](const ExpressionType& exprType) -> std::size_t - { - if (IsPrimitiveType(exprType)) - return 1; - else if (IsVectorType(exprType)) - return std::get(exprType).componentCount; - else - throw AstError{ "wut" }; - }; - - std::size_t componentCount = 0; - std::size_t requiredComponents = GetComponentCount(node.targetType); - - for (auto& exprPtr : node.expressions) - { - if (!exprPtr) - break; - - const ExpressionType& exprType = GetExpressionType(*exprPtr); - if (!IsPrimitiveType(exprType) && !IsVectorType(exprType)) - throw AstError{ "incompatible type" }; - - componentCount += GetComponentCount(exprType); - } - - if (componentCount != requiredComponents) - throw AstError{ "component count doesn't match required component count" }; - - node.cachedExpressionType = node.targetType; - } - - void AstValidator::Visit(ConstantExpression& node) - { - node.cachedExpressionType = std::visit([&](auto&& arg) -> ShaderAst::ExpressionType - { - using T = std::decay_t; - - if constexpr (std::is_same_v) - return PrimitiveType::Boolean; - else if constexpr (std::is_same_v) - return PrimitiveType::Float32; - else if constexpr (std::is_same_v) - return PrimitiveType::Int32; - else if constexpr (std::is_same_v) - return PrimitiveType::UInt32; - else if constexpr (std::is_same_v) - return VectorType{ 2, PrimitiveType::Float32 }; - else if constexpr (std::is_same_v) - return VectorType{ 3, PrimitiveType::Float32 }; - else if constexpr (std::is_same_v) - return VectorType{ 4, PrimitiveType::Float32 }; - else if constexpr (std::is_same_v) - return VectorType{ 2, PrimitiveType::Int32 }; - else if constexpr (std::is_same_v) - return VectorType{ 3, PrimitiveType::Int32 }; - else if constexpr (std::is_same_v) - return VectorType{ 4, PrimitiveType::Int32 }; - else - static_assert(AlwaysFalse::value, "non-exhaustive visitor"); - }, node.value); - - } - - void AstValidator::Visit(ConditionalExpression& node) - { - MandatoryExpr(node.truePath); - MandatoryExpr(node.falsePath); - - AstScopedVisitor::Visit(node); - - ExpressionType leftExprType = GetExpressionType(*node.truePath); - if (leftExprType != GetExpressionType(*node.falsePath)) - throw AstError{ "true path type must match false path type" }; - - node.cachedExpressionType = leftExprType; - //if (m_shader.FindConditionByName(node.conditionName) == ShaderAst::InvalidCondition) - // throw AstError{ "condition not found" }; - } - - void AstValidator::Visit(IdentifierExpression& node) - { - assert(m_context); - - const Identifier* identifier = FindIdentifier(node.identifier); - if (!identifier) - throw AstError{ "Unknown identifier " + node.identifier }; - - node.cachedExpressionType = ResolveAlias(std::get(identifier->value).type); - } - - void AstValidator::Visit(IntrinsicExpression& node) - { - AstScopedVisitor::Visit(node); - - switch (node.intrinsic) - { - case IntrinsicType::CrossProduct: - case IntrinsicType::DotProduct: - { - if (node.parameters.size() != 2) - throw AstError { "Expected two parameters" }; - - for (auto& param : node.parameters) - MandatoryExpr(param); - - ExpressionType type = GetExpressionType(*node.parameters.front()); - - for (std::size_t i = 1; i < node.parameters.size(); ++i) - { - if (type != GetExpressionType(MandatoryExpr(node.parameters[i]))) - throw AstError{ "All type must match" }; - } - - break; - } - - case IntrinsicType::SampleTexture: - { - if (node.parameters.size() != 2) - throw AstError{ "Expected two parameters" }; - - for (auto& param : node.parameters) - MandatoryExpr(param); - - if (!IsSamplerType(GetExpressionType(*node.parameters[0]))) - throw AstError{ "First parameter must be a sampler" }; - - if (!IsVectorType(GetExpressionType(*node.parameters[1]))) - throw AstError{ "Second parameter must be a vector" }; - } - } - - switch (node.intrinsic) - { - case IntrinsicType::CrossProduct: - { - ExpressionType type = GetExpressionType(*node.parameters.front()); - if (type != ExpressionType{ VectorType{ 3, PrimitiveType::Float32 } }) - throw AstError{ "CrossProduct only works with vec3 expressions" }; - - node.cachedExpressionType = std::move(type); - break; - } - - case IntrinsicType::DotProduct: - { - ExpressionType type = GetExpressionType(*node.parameters.front()); - if (!IsVectorType(type)) - throw AstError{ "DotProduct expects vector types" }; - - node.cachedExpressionType = std::get(type).type; - break; - } - - case IntrinsicType::SampleTexture: - { - node.cachedExpressionType = VectorType{ 4, std::get(GetExpressionType(*node.parameters.front())).sampledType }; - break; - } - } - } - - void AstValidator::Visit(SwizzleExpression& node) - { - if (node.componentCount > 4) - throw AstError{ "Cannot swizzle more than four elements" }; - - MandatoryExpr(node.expression); - - AstScopedVisitor::Visit(node); - - ExpressionType exprType = GetExpressionType(*node.expression); - if (IsPrimitiveType(exprType) || IsVectorType(exprType)) - { - PrimitiveType baseType; - if (IsPrimitiveType(exprType)) - baseType = std::get(exprType); - else - baseType = std::get(exprType).type; - - if (node.componentCount > 1) - { - node.cachedExpressionType = VectorType{ - node.componentCount, - baseType - }; - } - else - node.cachedExpressionType = baseType; - } - else - throw AstError{ "Cannot swizzle this type" }; - } - - void AstValidator::Visit(BranchStatement& node) - { - for (auto& condStatement : node.condStatements) - { - ExpressionType condType = GetExpressionType(MandatoryExpr(condStatement.condition)); - if (!IsPrimitiveType(condType) || std::get(condType) != PrimitiveType::Boolean) - throw AstError{ "if expression must resolve to boolean type" }; - - MandatoryStatement(condStatement.statement); - } - - AstScopedVisitor::Visit(node); - } - - void AstValidator::Visit(ConditionalStatement& node) - { - MandatoryStatement(node.statement); - - AstScopedVisitor::Visit(node); - //if (m_shader.FindConditionByName(node.conditionName) == ShaderAst::InvalidCondition) - // throw AstError{ "condition not found" }; - } - - void AstValidator::Visit(DeclareExternalStatement& node) - { - for (const auto& extVar : node.externalVars) - { - if (extVar.bindingIndex) - { - unsigned int bindingIndex = extVar.bindingIndex.value(); - if (m_context->usedBindingIndexes.find(bindingIndex) != m_context->usedBindingIndexes.end()) - throw AstError{ "Binding #" + std::to_string(bindingIndex) + " is already in use" }; - - m_context->usedBindingIndexes.insert(bindingIndex); - } - - if (m_context->declaredExternalVar.find(extVar.name) != m_context->declaredExternalVar.end()) - throw AstError{ "External variable " + extVar.name + " is already declared" }; - - m_context->declaredExternalVar.insert(extVar.name); - } - - AstScopedVisitor::Visit(node); - } - - void AstValidator::Visit(DeclareFunctionStatement& node) - { - if (node.entryStage) - { - ShaderStageType stageType = *node.entryStage; - - if (m_context->entryFunctions[UnderlyingCast(stageType)]) - throw AstError{ "the same entry type has been defined multiple times" }; - - m_context->entryFunctions[UnderlyingCast(stageType)] = &node; - - if (node.parameters.size() > 1) - throw AstError{ "entry functions can either take one struct parameter or no parameter" }; - } - - for (auto& statement : node.statements) - MandatoryStatement(statement); - - AstScopedVisitor::Visit(node); - } - - void AstValidator::Visit(DeclareStructStatement& node) - { - assert(m_context); - - std::unordered_set declaredMembers; - - for (auto& member : node.description.members) - { - if (declaredMembers.find(member.name) != declaredMembers.end()) - throw AstError{ "struct member " + member.name + " found multiple time" }; - - declaredMembers.insert(member.name); - } - - AstScopedVisitor::Visit(node); - } - - void AstValidator::Visit(DeclareVariableStatement& node) - { - if (IsNoType(node.varType)) - { - if (!node.initialExpression) - throw AstError{ "variable must either have a type or an initial value" }; - - node.initialExpression->Visit(*this); - - node.varType = GetExpressionType(*node.initialExpression); - } - - AstScopedVisitor::Visit(node); - } - - void AstValidator::Visit(ExpressionStatement& node) - { - MandatoryExpr(node.expression); - - AstScopedVisitor::Visit(node); - } - - void AstValidator::Visit(MultiStatement& node) - { - assert(m_context); - - for (auto& statement : node.statements) - MandatoryStatement(statement); - - AstScopedVisitor::Visit(node); - } - - bool ValidateAst(StatementPtr& node, std::string* error) - { - AstValidator validator; - return validator.Validate(node, error); - } -} diff --git a/src/Nazara/Shader/SpirvWriter.cpp b/src/Nazara/Shader/SpirvWriter.cpp index af994659a..61e3be2f2 100644 --- a/src/Nazara/Shader/SpirvWriter.cpp +++ b/src/Nazara/Shader/SpirvWriter.cpp @@ -6,13 +6,13 @@ #include #include #include -#include +#include #include #include #include #include #include -#include +#include #include #include #include @@ -38,7 +38,7 @@ namespace Nz { ShaderAst::BuiltinEntry::VertexPosition, { "VertexPosition", ShaderStageType::Vertex, SpirvBuiltIn::Position } } }; - class PreVisitor : public ShaderAst::AstScopedVisitor + class PreVisitor : public ShaderAst::AstRecursiveVisitor { public: struct UniformVar @@ -107,7 +107,7 @@ namespace Nz m_constantCache.Register(*m_constantCache.BuildConstant(arg)); }, node.value); - AstScopedVisitor::Visit(node); + AstRecursiveVisitor::Visit(node); } void Visit(ShaderAst::DeclareExternalStatement& node) override @@ -233,13 +233,13 @@ namespace Nz } m_funcIndex = funcIndex; - AstScopedVisitor::Visit(node); + AstRecursiveVisitor::Visit(node); m_funcIndex.reset(); } void Visit(ShaderAst::DeclareStructStatement& node) override { - AstScopedVisitor::Visit(node); + AstRecursiveVisitor::Visit(node); assert(node.structIndex); std::size_t structIndex = *node.structIndex; @@ -253,7 +253,7 @@ namespace Nz void Visit(ShaderAst::DeclareVariableStatement& node) override { - AstScopedVisitor::Visit(node); + AstRecursiveVisitor::Visit(node); assert(m_funcIndex); auto& func = m_funcs[*m_funcIndex]; @@ -269,12 +269,12 @@ namespace Nz { m_constantCache.Register(*m_constantCache.BuildType(node.cachedExpressionType.value())); - AstScopedVisitor::Visit(node); + AstRecursiveVisitor::Visit(node); } void Visit(ShaderAst::IntrinsicExpression& node) override { - AstScopedVisitor::Visit(node); + AstRecursiveVisitor::Visit(node); switch (node.intrinsic) { @@ -285,6 +285,7 @@ namespace Nz // Part of SPIR-V core case ShaderAst::IntrinsicType::DotProduct: + case ShaderAst::IntrinsicType::SampleTexture: break; } @@ -293,7 +294,7 @@ namespace Nz void Visit(ShaderAst::SwizzleExpression& node) override { - AstScopedVisitor::Visit(node); + AstRecursiveVisitor::Visit(node); m_constantCache.Register(*m_constantCache.BuildType(node.cachedExpressionType.value())); } @@ -391,12 +392,7 @@ namespace Nz std::vector SpirvWriter::Generate(ShaderAst::StatementPtr& shader, const States& conditions) { - std::string error; - if (!ShaderAst::ValidateAst(shader, &error)) - throw std::runtime_error("Invalid shader AST: " + error); - - ShaderAst::TransformVisitor transformVisitor; - ShaderAst::StatementPtr transformedShader = transformVisitor.Transform(shader); + ShaderAst::StatementPtr sanitizedAst = ShaderAst::Sanitize(shader); m_context.states = &conditions; @@ -409,7 +405,7 @@ namespace Nz // Register all extended instruction sets PreVisitor preVisitor(conditions, state.constantTypeCache, state.funcs); - transformedShader->Visit(preVisitor); + sanitizedAst->Visit(preVisitor); m_currentState->preVisitor = &preVisitor; @@ -417,7 +413,7 @@ namespace Nz state.extensionInstructions[extInst] = AllocateResultId(); SpirvAstVisitor visitor(*this, state.instructions, state.funcs); - transformedShader->Visit(visitor); + sanitizedAst->Visit(visitor); AppendHeader(); From d335d44d6adccaa0966351a64709354bc5bf03e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 15 Apr 2021 13:38:14 +0200 Subject: [PATCH 110/278] Shader: Cleanup and rename AST files --- include/Nazara/Graphics/UberShader.hpp | 2 +- include/Nazara/Renderer/RenderDevice.hpp | 2 +- include/Nazara/Shader.hpp | 12 +---------- .../AstCloner.hpp} | 8 ++++---- .../AstCloner.inl} | 2 +- .../AstExpressionVisitor.hpp} | 10 +++++----- .../AstExpressionVisitorExcept.hpp} | 4 ++-- .../AstNodeList.hpp} | 0 .../AstOptimizer.hpp} | 4 ++-- .../AstOptimizer.inl} | 2 +- .../AstRecursiveVisitor.hpp} | 6 +++--- .../AstRecursiveVisitor.inl} | 2 +- .../AstSerializer.hpp} | 4 ++-- .../AstSerializer.inl} | 2 +- .../AstStatementVisitor.hpp} | 4 ++-- .../AstStatementVisitorExcept.hpp} | 4 ++-- .../{ShaderAstUtils.hpp => Ast/AstUtils.hpp} | 10 +++++----- .../{ShaderAstUtils.inl => Ast/AstUtils.inl} | 2 +- include/Nazara/Shader/Ast/Attribute.hpp | 2 +- .../Shader/{ShaderEnums.hpp => Ast/Enums.hpp} | 20 +++---------------- include/Nazara/Shader/Ast/ExpressionType.hpp | 2 +- .../Shader/{ShaderNodes.hpp => Ast/Nodes.hpp} | 8 ++++---- .../Shader/{ShaderNodes.inl => Ast/Nodes.inl} | 6 +++--- include/Nazara/Shader/Ast/SanitizeVisitor.hpp | 2 +- include/Nazara/Shader/GlslWriter.hpp | 4 ++-- include/Nazara/Shader/ShaderBuilder.hpp | 2 +- include/Nazara/Shader/ShaderEnums.inl | 12 ----------- include/Nazara/Shader/ShaderLangParser.hpp | 2 +- include/Nazara/Shader/SpirvAstVisitor.hpp | 6 +++--- include/Nazara/Shader/SpirvConstantCache.hpp | 2 +- include/Nazara/Shader/SpirvExpressionLoad.hpp | 2 +- .../Nazara/Shader/SpirvExpressionStore.hpp | 2 +- include/Nazara/Shader/SpirvSectionBase.hpp | 2 +- include/Nazara/Shader/SpirvWriter.hpp | 2 +- include/Nazara/VulkanRenderer.hpp | 2 +- .../VulkanRenderer/VulkanShaderModule.hpp | 2 +- .../OpenGLRenderer/OpenGLShaderModule.cpp | 4 ++-- .../AstCloner.cpp} | 4 ++-- .../AstExpressionVisitor.cpp} | 2 +- .../AstExpressionVisitorExcept.cpp} | 4 ++-- .../AstOptimizer.cpp} | 2 +- .../AstRecursiveVisitor.cpp} | 2 +- .../AstSerializer.cpp} | 12 +++++------ .../AstStatementVisitor.cpp} | 2 +- .../AstStatementVisitorExcept.cpp} | 4 ++-- .../{ShaderAstUtils.cpp => Ast/AstUtils.cpp} | 2 +- .../Shader/{ShaderNodes.cpp => Ast/Nodes.cpp} | 10 +++++----- src/Nazara/Shader/Ast/SanitizeVisitor.cpp | 2 +- src/Nazara/Shader/GlslWriter.cpp | 6 +++--- src/Nazara/Shader/SpirvWriter.cpp | 4 ++-- .../VulkanRenderer/VulkanShaderModule.cpp | 2 +- src/ShaderNode/DataModels/Mat4VecMul.cpp | 2 +- src/ShaderNode/DataModels/ShaderNode.hpp | 2 +- src/ShaderNode/DataModels/VecDot.cpp | 2 +- src/ShaderNode/DataModels/VecFloatMul.cpp | 2 +- src/ShaderNode/DataTypes/Matrix4Data.hpp | 2 +- src/ShaderNode/DataTypes/TextureData.hpp | 2 +- src/ShaderNode/DataTypes/VecData.hpp | 2 +- src/ShaderNode/ShaderGraph.cpp | 4 ++-- src/ShaderNode/ShaderGraph.hpp | 2 +- src/ShaderNode/Widgets/CodeOutputWidget.cpp | 2 +- src/ShaderNode/Widgets/MainWindow.cpp | 2 +- 62 files changed, 105 insertions(+), 141 deletions(-) rename include/Nazara/Shader/{ShaderAstCloner.hpp => Ast/AstCloner.hpp} (93%) rename include/Nazara/Shader/{ShaderAstCloner.inl => Ast/AstCloner.inl} (94%) rename include/Nazara/Shader/{ShaderAstExpressionVisitor.hpp => Ast/AstExpressionVisitor.hpp} (72%) rename include/Nazara/Shader/{ShaderAstExpressionVisitorExcept.hpp => Ast/AstExpressionVisitorExcept.hpp} (86%) rename include/Nazara/Shader/{ShaderAstNodes.hpp => Ast/AstNodeList.hpp} (100%) rename include/Nazara/Shader/{ShaderAstOptimizer.hpp => Ast/AstOptimizer.hpp} (93%) rename include/Nazara/Shader/{ShaderAstOptimizer.inl => Ast/AstOptimizer.inl} (85%) rename include/Nazara/Shader/{ShaderAstRecursiveVisitor.hpp => Ast/AstRecursiveVisitor.hpp} (91%) rename include/Nazara/Shader/{ShaderAstRecursiveVisitor.inl => Ast/AstRecursiveVisitor.inl} (83%) rename include/Nazara/Shader/{ShaderAstSerializer.hpp => Ast/AstSerializer.hpp} (98%) rename include/Nazara/Shader/{ShaderAstSerializer.inl => Ast/AstSerializer.inl} (97%) rename include/Nazara/Shader/{ShaderAstStatementVisitor.hpp => Ast/AstStatementVisitor.hpp} (91%) rename include/Nazara/Shader/{ShaderAstStatementVisitorExcept.hpp => Ast/AstStatementVisitorExcept.hpp} (86%) rename include/Nazara/Shader/{ShaderAstUtils.hpp => Ast/AstUtils.hpp} (88%) rename include/Nazara/Shader/{ShaderAstUtils.inl => Ast/AstUtils.inl} (90%) rename include/Nazara/Shader/{ShaderEnums.hpp => Ast/Enums.hpp} (83%) rename include/Nazara/Shader/{ShaderNodes.hpp => Ast/Nodes.hpp} (98%) rename include/Nazara/Shader/{ShaderNodes.inl => Ast/Nodes.inl} (86%) delete mode 100644 include/Nazara/Shader/ShaderEnums.inl rename src/Nazara/Shader/{ShaderAstCloner.cpp => Ast/AstCloner.cpp} (98%) rename src/Nazara/Shader/{ShaderAstExpressionVisitor.cpp => Ast/AstExpressionVisitor.cpp} (84%) rename src/Nazara/Shader/{ShaderAstExpressionVisitorExcept.cpp => Ast/AstExpressionVisitorExcept.cpp} (79%) rename src/Nazara/Shader/{ShaderAstOptimizer.cpp => Ast/AstOptimizer.cpp} (99%) rename src/Nazara/Shader/{ShaderAstRecursiveVisitor.cpp => Ast/AstRecursiveVisitor.cpp} (98%) rename src/Nazara/Shader/{ShaderAstSerializer.cpp => Ast/AstSerializer.cpp} (97%) rename src/Nazara/Shader/{ShaderAstStatementVisitor.cpp => Ast/AstStatementVisitor.cpp} (84%) rename src/Nazara/Shader/{ShaderAstStatementVisitorExcept.cpp => Ast/AstStatementVisitorExcept.cpp} (79%) rename src/Nazara/Shader/{ShaderAstUtils.cpp => Ast/AstUtils.cpp} (97%) rename src/Nazara/Shader/{ShaderNodes.cpp => Ast/Nodes.cpp} (73%) diff --git a/include/Nazara/Graphics/UberShader.hpp b/include/Nazara/Graphics/UberShader.hpp index d400ade68..78b39e232 100644 --- a/include/Nazara/Graphics/UberShader.hpp +++ b/include/Nazara/Graphics/UberShader.hpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include namespace Nz diff --git a/include/Nazara/Renderer/RenderDevice.hpp b/include/Nazara/Renderer/RenderDevice.hpp index 85cd03541..fd2531794 100644 --- a/include/Nazara/Renderer/RenderDevice.hpp +++ b/include/Nazara/Renderer/RenderDevice.hpp @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/Nazara/Shader.hpp b/include/Nazara/Shader.hpp index 122296819..e86610fb0 100644 --- a/include/Nazara/Shader.hpp +++ b/include/Nazara/Shader.hpp @@ -32,25 +32,15 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include #include #include -#include #include #include #include #include #include +#include #include #include #include diff --git a/include/Nazara/Shader/ShaderAstCloner.hpp b/include/Nazara/Shader/Ast/AstCloner.hpp similarity index 93% rename from include/Nazara/Shader/ShaderAstCloner.hpp rename to include/Nazara/Shader/Ast/AstCloner.hpp index 0d034cab9..6feedc689 100644 --- a/include/Nazara/Shader/ShaderAstCloner.hpp +++ b/include/Nazara/Shader/Ast/AstCloner.hpp @@ -9,8 +9,8 @@ #include #include -#include -#include +#include +#include #include namespace Nz::ShaderAst @@ -61,7 +61,7 @@ namespace Nz::ShaderAst virtual StatementPtr Clone(ReturnStatement& node); #define NAZARA_SHADERAST_NODE(NodeType) void Visit(NodeType& node) override; -#include +#include void PushExpression(ExpressionPtr expression); void PushStatement(StatementPtr statement); @@ -78,6 +78,6 @@ namespace Nz::ShaderAst inline StatementPtr Clone(StatementPtr& node); } -#include +#include #endif diff --git a/include/Nazara/Shader/ShaderAstCloner.inl b/include/Nazara/Shader/Ast/AstCloner.inl similarity index 94% rename from include/Nazara/Shader/ShaderAstCloner.inl rename to include/Nazara/Shader/Ast/AstCloner.inl index 9d099bf63..d00b7365b 100644 --- a/include/Nazara/Shader/ShaderAstCloner.inl +++ b/include/Nazara/Shader/Ast/AstCloner.inl @@ -2,7 +2,7 @@ // This file is part of the "Nazara Engine - Shader generator" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include namespace Nz::ShaderAst diff --git a/include/Nazara/Shader/ShaderAstExpressionVisitor.hpp b/include/Nazara/Shader/Ast/AstExpressionVisitor.hpp similarity index 72% rename from include/Nazara/Shader/ShaderAstExpressionVisitor.hpp rename to include/Nazara/Shader/Ast/AstExpressionVisitor.hpp index 83e8b0271..1c72f88b0 100644 --- a/include/Nazara/Shader/ShaderAstExpressionVisitor.hpp +++ b/include/Nazara/Shader/Ast/AstExpressionVisitor.hpp @@ -4,12 +4,12 @@ #pragma once -#ifndef NAZARA_SHADERASTEXPRESSIONVISITOR_HPP -#define NAZARA_SHADERASTEXPRESSIONVISITOR_HPP +#ifndef NAZARA_SHADER_AST_EXPRESSIONVISITOR_HPP +#define NAZARA_SHADER_AST_EXPRESSIONVISITOR_HPP #include #include -#include +#include namespace Nz::ShaderAst { @@ -21,8 +21,8 @@ namespace Nz::ShaderAst AstExpressionVisitor(AstExpressionVisitor&&) = delete; virtual ~AstExpressionVisitor(); -#define NAZARA_SHADERAST_EXPRESSION(NodeType) virtual void Visit(NodeType& node) = 0; -#include +#define NAZARA_SHADERAST_EXPRESSION(Node) virtual void Visit(Node& node) = 0; +#include AstExpressionVisitor& operator=(const AstExpressionVisitor&) = delete; AstExpressionVisitor& operator=(AstExpressionVisitor&&) = delete; diff --git a/include/Nazara/Shader/ShaderAstExpressionVisitorExcept.hpp b/include/Nazara/Shader/Ast/AstExpressionVisitorExcept.hpp similarity index 86% rename from include/Nazara/Shader/ShaderAstExpressionVisitorExcept.hpp rename to include/Nazara/Shader/Ast/AstExpressionVisitorExcept.hpp index f28e98c78..40af7e695 100644 --- a/include/Nazara/Shader/ShaderAstExpressionVisitorExcept.hpp +++ b/include/Nazara/Shader/Ast/AstExpressionVisitorExcept.hpp @@ -9,7 +9,7 @@ #include #include -#include +#include namespace Nz::ShaderAst { @@ -19,7 +19,7 @@ namespace Nz::ShaderAst using AstExpressionVisitor::Visit; #define NAZARA_SHADERAST_EXPRESSION(Node) void Visit(ShaderAst::Node& node) override; -#include +#include }; } diff --git a/include/Nazara/Shader/ShaderAstNodes.hpp b/include/Nazara/Shader/Ast/AstNodeList.hpp similarity index 100% rename from include/Nazara/Shader/ShaderAstNodes.hpp rename to include/Nazara/Shader/Ast/AstNodeList.hpp diff --git a/include/Nazara/Shader/ShaderAstOptimizer.hpp b/include/Nazara/Shader/Ast/AstOptimizer.hpp similarity index 93% rename from include/Nazara/Shader/ShaderAstOptimizer.hpp rename to include/Nazara/Shader/Ast/AstOptimizer.hpp index 83d5fa499..354fe86ba 100644 --- a/include/Nazara/Shader/ShaderAstOptimizer.hpp +++ b/include/Nazara/Shader/Ast/AstOptimizer.hpp @@ -9,7 +9,7 @@ #include #include -#include +#include #include namespace Nz::ShaderAst @@ -42,6 +42,6 @@ namespace Nz::ShaderAst }; } -#include +#include #endif diff --git a/include/Nazara/Shader/ShaderAstOptimizer.inl b/include/Nazara/Shader/Ast/AstOptimizer.inl similarity index 85% rename from include/Nazara/Shader/ShaderAstOptimizer.inl rename to include/Nazara/Shader/Ast/AstOptimizer.inl index 17cd14c12..9607f7af0 100644 --- a/include/Nazara/Shader/ShaderAstOptimizer.inl +++ b/include/Nazara/Shader/Ast/AstOptimizer.inl @@ -2,7 +2,7 @@ // This file is part of the "Nazara Engine - Shader generator" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include namespace Nz diff --git a/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp b/include/Nazara/Shader/Ast/AstRecursiveVisitor.hpp similarity index 91% rename from include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp rename to include/Nazara/Shader/Ast/AstRecursiveVisitor.hpp index f05a20d22..d131931d6 100644 --- a/include/Nazara/Shader/ShaderAstRecursiveVisitor.hpp +++ b/include/Nazara/Shader/Ast/AstRecursiveVisitor.hpp @@ -9,8 +9,8 @@ #include #include -#include -#include +#include +#include namespace Nz::ShaderAst { @@ -46,6 +46,6 @@ namespace Nz::ShaderAst }; } -#include +#include #endif diff --git a/include/Nazara/Shader/ShaderAstRecursiveVisitor.inl b/include/Nazara/Shader/Ast/AstRecursiveVisitor.inl similarity index 83% rename from include/Nazara/Shader/ShaderAstRecursiveVisitor.inl rename to include/Nazara/Shader/Ast/AstRecursiveVisitor.inl index 8de7f453c..1467b2ca2 100644 --- a/include/Nazara/Shader/ShaderAstRecursiveVisitor.inl +++ b/include/Nazara/Shader/Ast/AstRecursiveVisitor.inl @@ -2,7 +2,7 @@ // This file is part of the "Nazara Engine - Shader generator" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include namespace Nz diff --git a/include/Nazara/Shader/ShaderAstSerializer.hpp b/include/Nazara/Shader/Ast/AstSerializer.hpp similarity index 98% rename from include/Nazara/Shader/ShaderAstSerializer.hpp rename to include/Nazara/Shader/Ast/AstSerializer.hpp index bb7e5f28b..8b726d19d 100644 --- a/include/Nazara/Shader/ShaderAstSerializer.hpp +++ b/include/Nazara/Shader/Ast/AstSerializer.hpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include namespace Nz::ShaderAst { @@ -144,6 +144,6 @@ namespace Nz::ShaderAst NAZARA_SHADER_API StatementPtr UnserializeShader(ByteStream& stream); } -#include +#include #endif diff --git a/include/Nazara/Shader/ShaderAstSerializer.inl b/include/Nazara/Shader/Ast/AstSerializer.inl similarity index 97% rename from include/Nazara/Shader/ShaderAstSerializer.inl rename to include/Nazara/Shader/Ast/AstSerializer.inl index c1b2d41c6..025e869b9 100644 --- a/include/Nazara/Shader/ShaderAstSerializer.inl +++ b/include/Nazara/Shader/Ast/AstSerializer.inl @@ -2,7 +2,7 @@ // This file is part of the "Nazara Engine - Shader generator" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include namespace Nz::ShaderAst diff --git a/include/Nazara/Shader/ShaderAstStatementVisitor.hpp b/include/Nazara/Shader/Ast/AstStatementVisitor.hpp similarity index 91% rename from include/Nazara/Shader/ShaderAstStatementVisitor.hpp rename to include/Nazara/Shader/Ast/AstStatementVisitor.hpp index 2da7e28a1..d204e4e9f 100644 --- a/include/Nazara/Shader/ShaderAstStatementVisitor.hpp +++ b/include/Nazara/Shader/Ast/AstStatementVisitor.hpp @@ -9,7 +9,7 @@ #include #include -#include +#include namespace Nz::ShaderAst { @@ -22,7 +22,7 @@ namespace Nz::ShaderAst virtual ~AstStatementVisitor(); #define NAZARA_SHADERAST_STATEMENT(NodeType) virtual void Visit(ShaderAst::NodeType& node) = 0; -#include +#include AstStatementVisitor& operator=(const AstStatementVisitor&) = delete; AstStatementVisitor& operator=(AstStatementVisitor&&) = delete; diff --git a/include/Nazara/Shader/ShaderAstStatementVisitorExcept.hpp b/include/Nazara/Shader/Ast/AstStatementVisitorExcept.hpp similarity index 86% rename from include/Nazara/Shader/ShaderAstStatementVisitorExcept.hpp rename to include/Nazara/Shader/Ast/AstStatementVisitorExcept.hpp index d5a85416f..88199ddb2 100644 --- a/include/Nazara/Shader/ShaderAstStatementVisitorExcept.hpp +++ b/include/Nazara/Shader/Ast/AstStatementVisitorExcept.hpp @@ -9,7 +9,7 @@ #include #include -#include +#include namespace Nz::ShaderAst { @@ -19,7 +19,7 @@ namespace Nz::ShaderAst using AstStatementVisitor::Visit; #define NAZARA_SHADERAST_STATEMENT(Node) void Visit(ShaderAst::Node& node) override; -#include +#include }; } diff --git a/include/Nazara/Shader/ShaderAstUtils.hpp b/include/Nazara/Shader/Ast/AstUtils.hpp similarity index 88% rename from include/Nazara/Shader/ShaderAstUtils.hpp rename to include/Nazara/Shader/Ast/AstUtils.hpp index a560bb5b6..d27c41d49 100644 --- a/include/Nazara/Shader/ShaderAstUtils.hpp +++ b/include/Nazara/Shader/Ast/AstUtils.hpp @@ -4,13 +4,13 @@ #pragma once -#ifndef NAZARA_SHADERASTUTILS_HPP -#define NAZARA_SHADERASTUTILS_HPP +#ifndef NAZARA_SHADER_AST_UTILS_HPP +#define NAZARA_SHADER_AST_UTILS_HPP #include #include -#include -#include +#include +#include #include namespace Nz::ShaderAst @@ -49,6 +49,6 @@ namespace Nz::ShaderAst inline ExpressionCategory GetExpressionCategory(Expression& expression); } -#include +#include #endif diff --git a/include/Nazara/Shader/ShaderAstUtils.inl b/include/Nazara/Shader/Ast/AstUtils.inl similarity index 90% rename from include/Nazara/Shader/ShaderAstUtils.inl rename to include/Nazara/Shader/Ast/AstUtils.inl index dec5ed3a9..b988f6fef 100644 --- a/include/Nazara/Shader/ShaderAstUtils.inl +++ b/include/Nazara/Shader/Ast/AstUtils.inl @@ -2,7 +2,7 @@ // This file is part of the "Nazara Engine - Shader generator" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include namespace Nz::ShaderAst diff --git a/include/Nazara/Shader/Ast/Attribute.hpp b/include/Nazara/Shader/Ast/Attribute.hpp index 9c1e0dca5..fb7bc091d 100644 --- a/include/Nazara/Shader/Ast/Attribute.hpp +++ b/include/Nazara/Shader/Ast/Attribute.hpp @@ -8,7 +8,7 @@ #define NAZARA_SHADERAST_ATTRIBUTES_HPP #include -#include +#include namespace Nz::ShaderAst { diff --git a/include/Nazara/Shader/ShaderEnums.hpp b/include/Nazara/Shader/Ast/Enums.hpp similarity index 83% rename from include/Nazara/Shader/ShaderEnums.hpp rename to include/Nazara/Shader/Ast/Enums.hpp index a25ef4caa..21b1e91a0 100644 --- a/include/Nazara/Shader/ShaderEnums.hpp +++ b/include/Nazara/Shader/Ast/Enums.hpp @@ -4,8 +4,8 @@ #pragma once -#ifndef NAZARA_SHADER_ENUMS_HPP -#define NAZARA_SHADER_ENUMS_HPP +#ifndef NAZARA_SHADER_AST_ENUMS_HPP +#define NAZARA_SHADER_AST_ENUMS_HPP #include @@ -69,7 +69,7 @@ namespace Nz::ShaderAst #define NAZARA_SHADERAST_NODE(Node) Node, #define NAZARA_SHADERAST_STATEMENT_LAST(Node) Node, Max = Node -#include +#include }; enum class PrimitiveType @@ -87,20 +87,6 @@ namespace Nz::ShaderAst Third, Fourth }; - - enum class VariableType - { - None = -1, - - BuiltinVariable, - InputVariable, - LocalVariable, - OutputVariable, - ParameterVariable, - UniformVariable - }; } -#include - #endif // NAZARA_SHADER_ENUMS_HPP diff --git a/include/Nazara/Shader/Ast/ExpressionType.hpp b/include/Nazara/Shader/Ast/ExpressionType.hpp index 2b436c7aa..aa6cd809e 100644 --- a/include/Nazara/Shader/Ast/ExpressionType.hpp +++ b/include/Nazara/Shader/Ast/ExpressionType.hpp @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include #include diff --git a/include/Nazara/Shader/ShaderNodes.hpp b/include/Nazara/Shader/Ast/Nodes.hpp similarity index 98% rename from include/Nazara/Shader/ShaderNodes.hpp rename to include/Nazara/Shader/Ast/Nodes.hpp index 5a6a2bae7..0d9f67067 100644 --- a/include/Nazara/Shader/ShaderNodes.hpp +++ b/include/Nazara/Shader/Ast/Nodes.hpp @@ -4,8 +4,8 @@ #pragma once -#ifndef NAZARA_SHADER_NODES_HPP -#define NAZARA_SHADER_NODES_HPP +#ifndef NAZARA_SHADER_AST_NODES_HPP +#define NAZARA_SHADER_AST_NODES_HPP #include #include @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include @@ -304,6 +304,6 @@ namespace Nz::ShaderAst inline bool IsStatement(NodeType nodeType); } -#include +#include #endif diff --git a/include/Nazara/Shader/ShaderNodes.inl b/include/Nazara/Shader/Ast/Nodes.inl similarity index 86% rename from include/Nazara/Shader/ShaderNodes.inl rename to include/Nazara/Shader/Ast/Nodes.inl index c9c3b875b..7484f2ac4 100644 --- a/include/Nazara/Shader/ShaderNodes.inl +++ b/include/Nazara/Shader/Ast/Nodes.inl @@ -2,7 +2,7 @@ // This file is part of the "Nazara Engine - Shader generator" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include namespace Nz::ShaderAst @@ -18,7 +18,7 @@ namespace Nz::ShaderAst switch (nodeType) { #define NAZARA_SHADERAST_EXPRESSION(Node) case NodeType::Node: return true; -#include +#include default: return false; @@ -30,7 +30,7 @@ namespace Nz::ShaderAst switch (nodeType) { #define NAZARA_SHADERAST_STATEMENT(Node) case NodeType::Node: return true; -#include +#include default: return false; diff --git a/include/Nazara/Shader/Ast/SanitizeVisitor.hpp b/include/Nazara/Shader/Ast/SanitizeVisitor.hpp index 43167a7f8..e3e541ba5 100644 --- a/include/Nazara/Shader/Ast/SanitizeVisitor.hpp +++ b/include/Nazara/Shader/Ast/SanitizeVisitor.hpp @@ -9,7 +9,7 @@ #include #include -#include +#include #include namespace Nz::ShaderAst diff --git a/include/Nazara/Shader/GlslWriter.hpp b/include/Nazara/Shader/GlslWriter.hpp index faea46ef7..a0530230c 100644 --- a/include/Nazara/Shader/GlslWriter.hpp +++ b/include/Nazara/Shader/GlslWriter.hpp @@ -9,9 +9,9 @@ #include #include -#include -#include #include +#include +#include #include #include #include diff --git a/include/Nazara/Shader/ShaderBuilder.hpp b/include/Nazara/Shader/ShaderBuilder.hpp index 9394624b1..0d5e44021 100644 --- a/include/Nazara/Shader/ShaderBuilder.hpp +++ b/include/Nazara/Shader/ShaderBuilder.hpp @@ -8,7 +8,7 @@ #define NAZARA_SHADER_BUILDER_HPP #include -#include +#include #include #include diff --git a/include/Nazara/Shader/ShaderEnums.inl b/include/Nazara/Shader/ShaderEnums.inl deleted file mode 100644 index a24138a6e..000000000 --- a/include/Nazara/Shader/ShaderEnums.inl +++ /dev/null @@ -1,12 +0,0 @@ -// 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 -#include - -namespace Nz::ShaderAst -{ -} - -#include diff --git a/include/Nazara/Shader/ShaderLangParser.hpp b/include/Nazara/Shader/ShaderLangParser.hpp index 1fa385c9f..6cea99202 100644 --- a/include/Nazara/Shader/ShaderLangParser.hpp +++ b/include/Nazara/Shader/ShaderLangParser.hpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include namespace Nz::ShaderLang { diff --git a/include/Nazara/Shader/SpirvAstVisitor.hpp b/include/Nazara/Shader/SpirvAstVisitor.hpp index 0f2d06495..10eb271e2 100644 --- a/include/Nazara/Shader/SpirvAstVisitor.hpp +++ b/include/Nazara/Shader/SpirvAstVisitor.hpp @@ -9,10 +9,10 @@ #include #include -#include -#include -#include #include +#include +#include +#include #include #include diff --git a/include/Nazara/Shader/SpirvConstantCache.hpp b/include/Nazara/Shader/SpirvConstantCache.hpp index 3025c013d..44e8a1652 100644 --- a/include/Nazara/Shader/SpirvConstantCache.hpp +++ b/include/Nazara/Shader/SpirvConstantCache.hpp @@ -8,7 +8,7 @@ #define NAZARA_SPIRVCONSTANTCACHE_HPP #include -#include +#include #include #include #include diff --git a/include/Nazara/Shader/SpirvExpressionLoad.hpp b/include/Nazara/Shader/SpirvExpressionLoad.hpp index bff0047cf..b85ccc471 100644 --- a/include/Nazara/Shader/SpirvExpressionLoad.hpp +++ b/include/Nazara/Shader/SpirvExpressionLoad.hpp @@ -9,8 +9,8 @@ #include #include -#include #include +#include #include namespace Nz diff --git a/include/Nazara/Shader/SpirvExpressionStore.hpp b/include/Nazara/Shader/SpirvExpressionStore.hpp index e66d545d3..097c78560 100644 --- a/include/Nazara/Shader/SpirvExpressionStore.hpp +++ b/include/Nazara/Shader/SpirvExpressionStore.hpp @@ -9,8 +9,8 @@ #include #include -#include #include +#include namespace Nz { diff --git a/include/Nazara/Shader/SpirvSectionBase.hpp b/include/Nazara/Shader/SpirvSectionBase.hpp index 4783fd80b..8c16f773b 100644 --- a/include/Nazara/Shader/SpirvSectionBase.hpp +++ b/include/Nazara/Shader/SpirvSectionBase.hpp @@ -8,7 +8,7 @@ #define NAZARA_SPIRVSECTIONBASE_HPP #include -#include +#include #include #include #include diff --git a/include/Nazara/Shader/SpirvWriter.hpp b/include/Nazara/Shader/SpirvWriter.hpp index 2bab892ca..284e76a94 100644 --- a/include/Nazara/Shader/SpirvWriter.hpp +++ b/include/Nazara/Shader/SpirvWriter.hpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/Nazara/VulkanRenderer.hpp b/include/Nazara/VulkanRenderer.hpp index 7b52637fc..633e24ee4 100644 --- a/include/Nazara/VulkanRenderer.hpp +++ b/include/Nazara/VulkanRenderer.hpp @@ -47,7 +47,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/Nazara/VulkanRenderer/VulkanShaderModule.hpp b/include/Nazara/VulkanRenderer/VulkanShaderModule.hpp index 8813eac54..4017cbfe3 100644 --- a/include/Nazara/VulkanRenderer/VulkanShaderModule.hpp +++ b/include/Nazara/VulkanRenderer/VulkanShaderModule.hpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/Nazara/OpenGLRenderer/OpenGLShaderModule.cpp b/src/Nazara/OpenGLRenderer/OpenGLShaderModule.cpp index 86b043877..4486a07e6 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLShaderModule.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLShaderModule.cpp @@ -6,10 +6,10 @@ #include #include #include -#include -#include #include #include +#include +#include #include #include diff --git a/src/Nazara/Shader/ShaderAstCloner.cpp b/src/Nazara/Shader/Ast/AstCloner.cpp similarity index 98% rename from src/Nazara/Shader/ShaderAstCloner.cpp rename to src/Nazara/Shader/Ast/AstCloner.cpp index af1348c72..602ddcd94 100644 --- a/src/Nazara/Shader/ShaderAstCloner.cpp +++ b/src/Nazara/Shader/Ast/AstCloner.cpp @@ -2,7 +2,7 @@ // This file is part of the "Nazara Engine - Shader generator" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include #include @@ -287,7 +287,7 @@ namespace Nz::ShaderAst PushStatement(Clone(node)); \ } -#include +#include void AstCloner::PushExpression(ExpressionPtr expression) { diff --git a/src/Nazara/Shader/ShaderAstExpressionVisitor.cpp b/src/Nazara/Shader/Ast/AstExpressionVisitor.cpp similarity index 84% rename from src/Nazara/Shader/ShaderAstExpressionVisitor.cpp rename to src/Nazara/Shader/Ast/AstExpressionVisitor.cpp index 44beed045..671b0c306 100644 --- a/src/Nazara/Shader/ShaderAstExpressionVisitor.cpp +++ b/src/Nazara/Shader/Ast/AstExpressionVisitor.cpp @@ -2,7 +2,7 @@ // This file is part of the "Nazara Engine - Shader generator" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include namespace Nz::ShaderAst diff --git a/src/Nazara/Shader/ShaderAstExpressionVisitorExcept.cpp b/src/Nazara/Shader/Ast/AstExpressionVisitorExcept.cpp similarity index 79% rename from src/Nazara/Shader/ShaderAstExpressionVisitorExcept.cpp rename to src/Nazara/Shader/Ast/AstExpressionVisitorExcept.cpp index 1fddc0e78..954f8693f 100644 --- a/src/Nazara/Shader/ShaderAstExpressionVisitorExcept.cpp +++ b/src/Nazara/Shader/Ast/AstExpressionVisitorExcept.cpp @@ -2,7 +2,7 @@ // This file is part of the "Nazara Engine - Shader generator" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include namespace Nz::ShaderAst @@ -11,5 +11,5 @@ namespace Nz::ShaderAst { \ throw std::runtime_error("unexpected " #Node " node"); \ } -#include +#include } diff --git a/src/Nazara/Shader/ShaderAstOptimizer.cpp b/src/Nazara/Shader/Ast/AstOptimizer.cpp similarity index 99% rename from src/Nazara/Shader/ShaderAstOptimizer.cpp rename to src/Nazara/Shader/Ast/AstOptimizer.cpp index 3c67240a7..8f948778d 100644 --- a/src/Nazara/Shader/ShaderAstOptimizer.cpp +++ b/src/Nazara/Shader/Ast/AstOptimizer.cpp @@ -2,7 +2,7 @@ // This file is part of the "Nazara Engine - Shader generator" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include #include #include diff --git a/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp b/src/Nazara/Shader/Ast/AstRecursiveVisitor.cpp similarity index 98% rename from src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp rename to src/Nazara/Shader/Ast/AstRecursiveVisitor.cpp index 52e6dc3eb..7e33c9590 100644 --- a/src/Nazara/Shader/ShaderAstRecursiveVisitor.cpp +++ b/src/Nazara/Shader/Ast/AstRecursiveVisitor.cpp @@ -2,7 +2,7 @@ // This file is part of the "Nazara Engine - Shader generator" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include namespace Nz::ShaderAst diff --git a/src/Nazara/Shader/ShaderAstSerializer.cpp b/src/Nazara/Shader/Ast/AstSerializer.cpp similarity index 97% rename from src/Nazara/Shader/ShaderAstSerializer.cpp rename to src/Nazara/Shader/Ast/AstSerializer.cpp index 73ed6db60..1c79e7600 100644 --- a/src/Nazara/Shader/ShaderAstSerializer.cpp +++ b/src/Nazara/Shader/Ast/AstSerializer.cpp @@ -2,9 +2,9 @@ // This file is part of the "Nazara Engine - Shader generator" // For conditions of distribution and use, see copyright notice in Config.hpp -#include -#include -#include +#include +#include +#include #include namespace Nz::ShaderAst @@ -26,7 +26,7 @@ namespace Nz::ShaderAst { \ m_serializer.Serialize(node); \ } -#include +#include private: AstSerializerBase& m_serializer; @@ -444,7 +444,7 @@ namespace Nz::ShaderAst case NodeType::None: break; #define NAZARA_SHADERAST_EXPRESSION(Node) case NodeType:: Node : node = std::make_unique(); break; -#include +#include default: throw std::runtime_error("unexpected node type"); } @@ -470,7 +470,7 @@ namespace Nz::ShaderAst case NodeType::None: break; #define NAZARA_SHADERAST_STATEMENT(Node) case NodeType:: Node : node = std::make_unique(); break; -#include +#include default: throw std::runtime_error("unexpected node type"); } diff --git a/src/Nazara/Shader/ShaderAstStatementVisitor.cpp b/src/Nazara/Shader/Ast/AstStatementVisitor.cpp similarity index 84% rename from src/Nazara/Shader/ShaderAstStatementVisitor.cpp rename to src/Nazara/Shader/Ast/AstStatementVisitor.cpp index 6ee90504e..8d1cca01f 100644 --- a/src/Nazara/Shader/ShaderAstStatementVisitor.cpp +++ b/src/Nazara/Shader/Ast/AstStatementVisitor.cpp @@ -2,7 +2,7 @@ // This file is part of the "Nazara Engine - Shader generator" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include namespace Nz::ShaderAst diff --git a/src/Nazara/Shader/ShaderAstStatementVisitorExcept.cpp b/src/Nazara/Shader/Ast/AstStatementVisitorExcept.cpp similarity index 79% rename from src/Nazara/Shader/ShaderAstStatementVisitorExcept.cpp rename to src/Nazara/Shader/Ast/AstStatementVisitorExcept.cpp index ef4204ce6..9a4e36783 100644 --- a/src/Nazara/Shader/ShaderAstStatementVisitorExcept.cpp +++ b/src/Nazara/Shader/Ast/AstStatementVisitorExcept.cpp @@ -2,7 +2,7 @@ // This file is part of the "Nazara Engine - Shader generator" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include namespace Nz::ShaderAst @@ -11,5 +11,5 @@ namespace Nz::ShaderAst { \ throw std::runtime_error("unexpected " #Node " node"); \ } -#include +#include } diff --git a/src/Nazara/Shader/ShaderAstUtils.cpp b/src/Nazara/Shader/Ast/AstUtils.cpp similarity index 97% rename from src/Nazara/Shader/ShaderAstUtils.cpp rename to src/Nazara/Shader/Ast/AstUtils.cpp index 47f73cdeb..a6895177a 100644 --- a/src/Nazara/Shader/ShaderAstUtils.cpp +++ b/src/Nazara/Shader/Ast/AstUtils.cpp @@ -2,7 +2,7 @@ // This file is part of the "Nazara Engine - Shader generator" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include namespace Nz::ShaderAst diff --git a/src/Nazara/Shader/ShaderNodes.cpp b/src/Nazara/Shader/Ast/Nodes.cpp similarity index 73% rename from src/Nazara/Shader/ShaderNodes.cpp rename to src/Nazara/Shader/Ast/Nodes.cpp index d4510fcfc..aed845fc5 100644 --- a/src/Nazara/Shader/ShaderNodes.cpp +++ b/src/Nazara/Shader/Ast/Nodes.cpp @@ -2,10 +2,10 @@ // This file is part of the "Nazara Engine - Shader generator" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include -#include -#include +#include +#include #include namespace Nz::ShaderAst @@ -16,7 +16,7 @@ namespace Nz::ShaderAst { \ return NodeType:: Node; \ } -#include +#include #define NAZARA_SHADERAST_EXPRESSION(Node) void Node::Visit(AstExpressionVisitor& visitor) \ {\ @@ -28,5 +28,5 @@ namespace Nz::ShaderAst visitor.Visit(*this); \ } -#include +#include } diff --git a/src/Nazara/Shader/Ast/SanitizeVisitor.cpp b/src/Nazara/Shader/Ast/SanitizeVisitor.cpp index 6da7ef18a..57a3cd8cd 100644 --- a/src/Nazara/Shader/Ast/SanitizeVisitor.cpp +++ b/src/Nazara/Shader/Ast/SanitizeVisitor.cpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/Nazara/Shader/GlslWriter.cpp b/src/Nazara/Shader/GlslWriter.cpp index c354ffbd1..c6e4a983f 100644 --- a/src/Nazara/Shader/GlslWriter.cpp +++ b/src/Nazara/Shader/GlslWriter.cpp @@ -7,9 +7,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include #include #include diff --git a/src/Nazara/Shader/SpirvWriter.cpp b/src/Nazara/Shader/SpirvWriter.cpp index 61e3be2f2..5e2caca18 100644 --- a/src/Nazara/Shader/SpirvWriter.cpp +++ b/src/Nazara/Shader/SpirvWriter.cpp @@ -5,13 +5,13 @@ #include #include #include -#include -#include #include #include #include #include #include +#include +#include #include #include #include diff --git a/src/Nazara/VulkanRenderer/VulkanShaderModule.cpp b/src/Nazara/VulkanRenderer/VulkanShaderModule.cpp index a6e585123..acbb9f8bf 100644 --- a/src/Nazara/VulkanRenderer/VulkanShaderModule.cpp +++ b/src/Nazara/VulkanRenderer/VulkanShaderModule.cpp @@ -3,11 +3,11 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include #include #include #include #include +#include #include namespace Nz diff --git a/src/ShaderNode/DataModels/Mat4VecMul.cpp b/src/ShaderNode/DataModels/Mat4VecMul.cpp index f859166c1..0e723584d 100644 --- a/src/ShaderNode/DataModels/Mat4VecMul.cpp +++ b/src/ShaderNode/DataModels/Mat4VecMul.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include Mat4VecMul::Mat4VecMul(ShaderGraph& graph) : ShaderNode(graph) diff --git a/src/ShaderNode/DataModels/ShaderNode.hpp b/src/ShaderNode/DataModels/ShaderNode.hpp index eeb8d0b3e..c0aa8afcf 100644 --- a/src/ShaderNode/DataModels/ShaderNode.hpp +++ b/src/ShaderNode/DataModels/ShaderNode.hpp @@ -4,7 +4,7 @@ #define NAZARA_SHADERNODES_SHADERNODE_HPP #include -#include +#include #include #include #include diff --git a/src/ShaderNode/DataModels/VecDot.cpp b/src/ShaderNode/DataModels/VecDot.cpp index 0a6e7f0ce..21849ec03 100644 --- a/src/ShaderNode/DataModels/VecDot.cpp +++ b/src/ShaderNode/DataModels/VecDot.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include VecDot::VecDot(ShaderGraph& graph) : ShaderNode(graph) diff --git a/src/ShaderNode/DataModels/VecFloatMul.cpp b/src/ShaderNode/DataModels/VecFloatMul.cpp index 62abd27e8..9ddcb8bc0 100644 --- a/src/ShaderNode/DataModels/VecFloatMul.cpp +++ b/src/ShaderNode/DataModels/VecFloatMul.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include VecFloatMul::VecFloatMul(ShaderGraph& graph) : ShaderNode(graph) diff --git a/src/ShaderNode/DataTypes/Matrix4Data.hpp b/src/ShaderNode/DataTypes/Matrix4Data.hpp index 4eb63f136..bd2e9e978 100644 --- a/src/ShaderNode/DataTypes/Matrix4Data.hpp +++ b/src/ShaderNode/DataTypes/Matrix4Data.hpp @@ -3,7 +3,7 @@ #ifndef NAZARA_SHADERNODES_MATRIXDATA_HPP #define NAZARA_SHADERNODES_MATRIXDATA_HPP -#include +#include #include #include diff --git a/src/ShaderNode/DataTypes/TextureData.hpp b/src/ShaderNode/DataTypes/TextureData.hpp index 28b2b73d0..ab3bba1f2 100644 --- a/src/ShaderNode/DataTypes/TextureData.hpp +++ b/src/ShaderNode/DataTypes/TextureData.hpp @@ -4,7 +4,7 @@ #define NAZARA_SHADERNODES_TEXTUREDATA_HPP #include -#include +#include #include struct TextureData : public QtNodes::NodeData diff --git a/src/ShaderNode/DataTypes/VecData.hpp b/src/ShaderNode/DataTypes/VecData.hpp index 44ef84e67..1dcd265d5 100644 --- a/src/ShaderNode/DataTypes/VecData.hpp +++ b/src/ShaderNode/DataTypes/VecData.hpp @@ -3,7 +3,7 @@ #ifndef NAZARA_SHADERNODES_VECDATA_HPP #define NAZARA_SHADERNODES_VECDATA_HPP -#include +#include #include #include diff --git a/src/ShaderNode/ShaderGraph.cpp b/src/ShaderNode/ShaderGraph.cpp index 3e3fa273c..64abc3891 100644 --- a/src/ShaderNode/ShaderGraph.cpp +++ b/src/ShaderNode/ShaderGraph.cpp @@ -1,8 +1,8 @@ #include #include +#include +#include #include -#include -#include #include #include #include diff --git a/src/ShaderNode/ShaderGraph.hpp b/src/ShaderNode/ShaderGraph.hpp index 19dcb6813..b8187c5d1 100644 --- a/src/ShaderNode/ShaderGraph.hpp +++ b/src/ShaderNode/ShaderGraph.hpp @@ -5,7 +5,7 @@ #include #include -#include +#include #include #include #include diff --git a/src/ShaderNode/Widgets/CodeOutputWidget.cpp b/src/ShaderNode/Widgets/CodeOutputWidget.cpp index 9e20057e1..f92a23d2f 100644 --- a/src/ShaderNode/Widgets/CodeOutputWidget.cpp +++ b/src/ShaderNode/Widgets/CodeOutputWidget.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include #include diff --git a/src/ShaderNode/Widgets/MainWindow.cpp b/src/ShaderNode/Widgets/MainWindow.cpp index 5777964b2..54678eb23 100644 --- a/src/ShaderNode/Widgets/MainWindow.cpp +++ b/src/ShaderNode/Widgets/MainWindow.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include #include #include From fce336bfc96a4d4699ae39bf7d96cb61f2aebf7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 15 Apr 2021 14:01:14 +0200 Subject: [PATCH 111/278] Shader: Fix struct attributes handling --- src/Nazara/Shader/ShaderLangParser.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/Nazara/Shader/ShaderLangParser.cpp b/src/Nazara/Shader/ShaderLangParser.cpp index 1bc9316b5..8a28249ac 100644 --- a/src/Nazara/Shader/ShaderLangParser.cpp +++ b/src/Nazara/Shader/ShaderLangParser.cpp @@ -40,6 +40,10 @@ namespace Nz::ShaderLang { "position", ShaderAst::BuiltinEntry::VertexPosition } }; + std::unordered_map s_layoutMapping = { + { "std140", StructLayout_Std140 } + }; + template std::optional BoundCast(U val) { @@ -494,6 +498,28 @@ namespace Nz::ShaderLang ShaderAst::StructDescription description; description.name = ParseIdentifierAsName(); + + for (const auto& [attributeType, attributeParam] : attributes) + { + switch (attributeType) + { + case ShaderAst::AttributeType::Layout: + { + if (description.layout) + throw AttributeError{ "attribute layout must be present once" }; + + auto it = s_layoutMapping.find(std::get(attributeParam)); + if (it == s_layoutMapping.end()) + throw AttributeError{ "unknown layout" }; + + description.layout = it->second; + break; + } + + default: + throw AttributeError{ "unexpected attribute" }; + } + } Expect(Advance(), TokenType::OpenCurlyBracket); From 9fd4249a87ffe909a42116eb48ecb1a6ba5c7438 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 15 Apr 2021 14:01:36 +0200 Subject: [PATCH 112/278] Shader: compilation fixes --- include/Nazara/Shader/ShaderLangParser.hpp | 8 +++---- src/Nazara/Shader/Ast/AstOptimizer.cpp | 20 ++++++++-------- src/Nazara/Shader/ShaderLangLexer.cpp | 2 +- src/Nazara/Shader/ShaderLangParser.cpp | 27 ++++++++++++---------- 4 files changed, 30 insertions(+), 27 deletions(-) diff --git a/include/Nazara/Shader/ShaderLangParser.hpp b/include/Nazara/Shader/ShaderLangParser.hpp index 6cea99202..4780a022c 100644 --- a/include/Nazara/Shader/ShaderLangParser.hpp +++ b/include/Nazara/Shader/ShaderLangParser.hpp @@ -14,10 +14,10 @@ namespace Nz::ShaderLang { - class AttributeError : public std::exception + class AttributeError : public std::runtime_error { public: - using exception::exception; + using runtime_error::runtime_error; }; class ExpectedToken : public std::exception @@ -26,10 +26,10 @@ namespace Nz::ShaderLang using exception::exception; }; - class DuplicateIdentifier : public std::exception + class DuplicateIdentifier : public std::runtime_error { public: - using exception::exception; + using runtime_error::runtime_error; }; class ReservedKeyword : public std::exception diff --git a/src/Nazara/Shader/Ast/AstOptimizer.cpp b/src/Nazara/Shader/Ast/AstOptimizer.cpp index 8f948778d..3c00fbd2b 100644 --- a/src/Nazara/Shader/Ast/AstOptimizer.cpp +++ b/src/Nazara/Shader/Ast/AstOptimizer.cpp @@ -53,7 +53,7 @@ namespace Nz::ShaderAst template struct PropagateConstantType { - using Op = typename CompEq; + using Op = CompEq; }; // CompGe @@ -72,7 +72,7 @@ namespace Nz::ShaderAst template struct PropagateConstantType { - using Op = typename CompGe; + using Op = CompGe; }; // CompGt @@ -91,7 +91,7 @@ namespace Nz::ShaderAst template struct PropagateConstantType { - using Op = typename CompGt; + using Op = CompGt; }; // CompLe @@ -110,7 +110,7 @@ namespace Nz::ShaderAst template struct PropagateConstantType { - using Op = typename CompLe; + using Op = CompLe; }; // CompLt @@ -129,7 +129,7 @@ namespace Nz::ShaderAst template struct PropagateConstantType { - using Op = typename CompLe; + using Op = CompLe; }; // CompNe @@ -148,7 +148,7 @@ namespace Nz::ShaderAst template struct PropagateConstantType { - using Op = typename CompNe; + using Op = CompNe; }; // Addition @@ -167,7 +167,7 @@ namespace Nz::ShaderAst template struct PropagateConstantType { - using Op = typename Addition; + using Op = Addition; }; // Division @@ -186,7 +186,7 @@ namespace Nz::ShaderAst template struct PropagateConstantType { - using Op = typename Division; + using Op = Division; }; // Multiplication @@ -205,7 +205,7 @@ namespace Nz::ShaderAst template struct PropagateConstantType { - using Op = typename Multiplication; + using Op = Multiplication; }; // Subtraction @@ -224,7 +224,7 @@ namespace Nz::ShaderAst template struct PropagateConstantType { - using Op = typename Subtraction; + using Op = Subtraction; }; #define EnableOptimisation(Op, T1, T2) template<> struct Op : Op##Base {} diff --git a/src/Nazara/Shader/ShaderLangLexer.cpp b/src/Nazara/Shader/ShaderLangLexer.cpp index 0b084a014..b25c56877 100644 --- a/src/Nazara/Shader/ShaderLangLexer.cpp +++ b/src/Nazara/Shader/ShaderLangLexer.cpp @@ -73,7 +73,7 @@ namespace Nz::ShaderLang char c = Peek(0); Token token; - token.column = currentPos - lastLineFeed; + token.column = static_cast(currentPos - lastLineFeed); token.line = lineNumber; if (c == -1) diff --git a/src/Nazara/Shader/ShaderLangParser.cpp b/src/Nazara/Shader/ShaderLangParser.cpp index 8a28249ac..74d5aefd7 100644 --- a/src/Nazara/Shader/ShaderLangParser.cpp +++ b/src/Nazara/Shader/ShaderLangParser.cpp @@ -11,19 +11,19 @@ namespace Nz::ShaderLang { namespace { - std::unordered_map identifierToBasicType = { + std::unordered_map s_identifierToBasicType = { { "bool", ShaderAst::PrimitiveType::Boolean }, { "i32", ShaderAst::PrimitiveType::Int32 }, { "f32", ShaderAst::PrimitiveType::Float32 }, { "u32", ShaderAst::PrimitiveType::UInt32 } }; - std::unordered_map identifierToIntrinsic = { + std::unordered_map s_identifierToIntrinsic = { { "cross", ShaderAst::IntrinsicType::CrossProduct }, { "dot", ShaderAst::IntrinsicType::DotProduct }, }; - std::unordered_map identifierToAttributeType = { + std::unordered_map s_identifierToAttributeType = { { "binding", ShaderAst::AttributeType::Binding }, { "builtin", ShaderAst::AttributeType::Builtin }, { "entry", ShaderAst::AttributeType::Entry }, @@ -127,7 +127,7 @@ namespace Nz::ShaderLang ShaderAst::ExpressionType Parser::DecodeType(const std::string& identifier) { - if (auto it = identifierToBasicType.find(identifier); it != identifierToBasicType.end()) + if (auto it = s_identifierToBasicType.find(identifier); it != s_identifierToBasicType.end()) return it->second; //FIXME: Handle this better @@ -576,7 +576,10 @@ namespace Nz::ShaderLang throw AttributeError{ "invalid location index" }; break; - } + } + + default: + throw AttributeError{ "unexpected attribute" }; } } @@ -809,7 +812,7 @@ namespace Nz::ShaderLang { const std::string& identifier = std::get(token.data); - if (auto it = identifierToIntrinsic.find(identifier); it != identifierToIntrinsic.end()) + if (auto it = s_identifierToIntrinsic.find(identifier); it != s_identifierToIntrinsic.end()) { if (Peek(1).type == TokenType::OpenParenthesis) { @@ -879,8 +882,8 @@ namespace Nz::ShaderLang const Token& identifierToken = Expect(Advance(), TokenType::Identifier); const std::string& identifier = std::get(identifierToken.data); - auto it = identifierToAttributeType.find(identifier); - if (it == identifierToAttributeType.end()) + auto it = s_identifierToAttributeType.find(identifier); + if (it == s_identifierToAttributeType.end()) throw UnknownAttribute{}; return it->second; @@ -891,8 +894,8 @@ namespace Nz::ShaderLang const Token& identifierToken = Expect(Advance(), TokenType::Identifier); const std::string& identifier = std::get(identifierToken.data); - auto it = identifierToBasicType.find(identifier); - if (it != identifierToBasicType.end()) + auto it = s_identifierToBasicType.find(identifier); + if (it != s_identifierToBasicType.end()) throw ReservedKeyword{}; return identifier; @@ -903,8 +906,8 @@ namespace Nz::ShaderLang const Token& identifierToken = Expect(Advance(), TokenType::Identifier); const std::string& identifier = std::get(identifierToken.data); - auto it = identifierToBasicType.find(identifier); - if (it == identifierToBasicType.end()) + auto it = s_identifierToBasicType.find(identifier); + if (it == s_identifierToBasicType.end()) throw UnknownType{}; return it->second; From 7da02c8708c53768777d8a0db64a393dea4b156e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 15 Apr 2021 15:01:58 +0200 Subject: [PATCH 113/278] Fix RenderTest shader code --- examples/RenderTest/main.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/RenderTest/main.cpp b/examples/RenderTest/main.cpp index 5dcde7161..b3b19ebcc 100644 --- a/examples/RenderTest/main.cpp +++ b/examples/RenderTest/main.cpp @@ -9,7 +9,7 @@ #include const char shaderSource[] = R"( -[[layout(std140)]] +[layout(std140)] struct Data { projectionMatrix: mat4, @@ -19,30 +19,30 @@ struct Data external { - [[binding(0)]] viewerData: uniform, - [[binding(1)]] tex: sampler2D + [binding(0)] viewerData: uniform, + [binding(1)] tex: sampler2D } struct VertIn { - [[location(0)]] position: vec3, - [[location(1)]] normal: vec3, - [[location(2)]] uv: vec2 + [location(0)] position: vec3, + [location(1)] normal: vec3, + [location(2)] uv: vec2 } struct VertOut { - [[builtin(position)]] position: vec4, - [[location(0)]] normal: vec3, - [[location(1)]] uv: vec2 + [builtin(position)] position: vec4, + [location(0)] normal: vec3, + [location(1)] uv: vec2 } struct FragOut { - [[location(0)]] color: vec4 + [location(0)] color: vec4 } -[[entry(frag)]] +[entry(frag)] fn main(fragIn: VertOut) -> FragOut { let lightDir = vec3(0.0, -0.707, 0.707); @@ -54,7 +54,7 @@ fn main(fragIn: VertOut) -> FragOut return fragOut; } -[[entry(vert)]] +[entry(vert)] fn main(vertIn: VertIn) -> VertOut { let vertOut: VertOut; From 87ce2edc6ebad67217eb7cd77d8c3a6788244123 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sat, 17 Apr 2021 14:43:00 +0200 Subject: [PATCH 114/278] Shader: Add initial support for options (WIP) --- examples/RenderTest/main.cpp | 10 +- .../Nazara/OpenGLRenderer/OpenGLDevice.hpp | 2 +- .../OpenGLRenderer/OpenGLShaderModule.hpp | 2 +- include/Nazara/Renderer/RenderDevice.hpp | 4 +- include/Nazara/Shader/Ast/AstCloner.hpp | 2 + include/Nazara/Shader/Ast/AstNodeList.hpp | 2 + include/Nazara/Shader/Ast/AstOptimizer.hpp | 14 +-- .../Nazara/Shader/Ast/AstRecursiveVisitor.hpp | 2 + include/Nazara/Shader/Ast/AstSerializer.hpp | 2 + include/Nazara/Shader/Ast/AstUtils.hpp | 1 + include/Nazara/Shader/Ast/Enums.hpp | 3 +- include/Nazara/Shader/Ast/Nodes.hpp | 26 +++- include/Nazara/Shader/Ast/SanitizeVisitor.hpp | 22 +++- include/Nazara/Shader/Ast/SanitizeVisitor.inl | 28 ++++- include/Nazara/Shader/GlslWriter.hpp | 5 +- include/Nazara/Shader/GlslWriter.inl | 4 +- include/Nazara/Shader/LangWriter.hpp | 111 ++++++++++++++++++ include/Nazara/Shader/LangWriter.inl | 16 +++ include/Nazara/Shader/ShaderBuilder.hpp | 16 ++- include/Nazara/Shader/ShaderBuilder.inl | 28 ++++- include/Nazara/Shader/ShaderLangParser.hpp | 2 + include/Nazara/Shader/ShaderLangTokenList.hpp | 2 + include/Nazara/Shader/ShaderWriter.hpp | 2 +- include/Nazara/Shader/SpirvWriter.hpp | 4 +- include/Nazara/Shader/SpirvWriter.inl | 8 -- .../Nazara/VulkanRenderer/VulkanDevice.hpp | 2 +- .../VulkanRenderer/VulkanShaderModule.hpp | 2 +- src/Nazara/OpenGLRenderer/OpenGLDevice.cpp | 4 +- .../OpenGLRenderer/OpenGLShaderModule.cpp | 4 +- src/Nazara/Renderer/RenderDevice.cpp | 4 +- src/Nazara/Shader/Ast/AstCloner.cpp | 28 ++++- src/Nazara/Shader/Ast/AstRecursiveVisitor.cpp | 12 ++ src/Nazara/Shader/Ast/AstSerializer.cpp | 36 ++++-- src/Nazara/Shader/Ast/AstUtils.cpp | 14 +++ src/Nazara/Shader/Ast/Nodes.cpp | 31 +++++ src/Nazara/Shader/Ast/SanitizeVisitor.cpp | 71 ++++++++++- src/Nazara/Shader/GlslWriter.cpp | 27 +++-- src/Nazara/Shader/ShaderLangLexer.cpp | 16 +-- src/Nazara/Shader/ShaderLangParser.cpp | 79 ++++++++++++- src/Nazara/Shader/SpirvAstVisitor.cpp | 4 +- src/Nazara/Shader/SpirvWriter.cpp | 31 +++-- src/Nazara/VulkanRenderer/VulkanDevice.cpp | 4 +- .../VulkanRenderer/VulkanShaderModule.cpp | 6 +- .../DataModels/ConditionalExpression.cpp | 2 +- src/ShaderNode/ShaderGraph.cpp | 4 + 45 files changed, 586 insertions(+), 113 deletions(-) create mode 100644 include/Nazara/Shader/LangWriter.hpp create mode 100644 include/Nazara/Shader/LangWriter.inl diff --git a/examples/RenderTest/main.cpp b/examples/RenderTest/main.cpp index b3b19ebcc..c076d8c3f 100644 --- a/examples/RenderTest/main.cpp +++ b/examples/RenderTest/main.cpp @@ -9,6 +9,9 @@ #include const char shaderSource[] = R"( + +option red: bool; + [layout(std140)] struct Data { @@ -49,7 +52,7 @@ fn main(fragIn: VertOut) -> FragOut let lightFactor = dot(fragIn.normal, lightDir); let fragOut: FragOut; - fragOut.color = lightFactor * tex.Sample(fragIn.uv); + fragOut.color = lightFactor * tex.Sample(fragIn.uv) * select_opt(red, vec4(1.0, 0.0, 0.0, 1.0), vec4(1.0, 1.0, 1.0, 1.0)); return fragOut; } @@ -92,7 +95,10 @@ int main() std::shared_ptr device = window.GetRenderDevice(); - auto fragVertShader = device->InstantiateShaderModule(Nz::ShaderStageType::Fragment | Nz::ShaderStageType::Vertex, Nz::ShaderLanguage::NazaraShader, shaderSource, sizeof(shaderSource)); + Nz::ShaderWriter::States states; + states.enabledOptions = 0; + + auto fragVertShader = device->InstantiateShaderModule(Nz::ShaderStageType::Fragment | Nz::ShaderStageType::Vertex, Nz::ShaderLanguage::NazaraShader, shaderSource, sizeof(shaderSource), states); if (!fragVertShader) { std::cout << "Failed to instantiate shader" << std::endl; diff --git a/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp b/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp index 2597b3f91..b897ef728 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp @@ -39,7 +39,7 @@ namespace Nz std::shared_ptr InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override; std::shared_ptr InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) override; std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states) override; - std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize) override; + std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const ShaderWriter::States& states) override; std::shared_ptr InstantiateTexture(const TextureInfo& params) override; std::shared_ptr InstantiateTextureSampler(const TextureSamplerInfo& params) override; diff --git a/include/Nazara/OpenGLRenderer/OpenGLShaderModule.hpp b/include/Nazara/OpenGLRenderer/OpenGLShaderModule.hpp index 6e0426702..c93f2e277 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLShaderModule.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLShaderModule.hpp @@ -21,7 +21,7 @@ namespace Nz { public: OpenGLShaderModule(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states); - OpenGLShaderModule(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize); + OpenGLShaderModule(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const ShaderWriter::States& states); OpenGLShaderModule(const OpenGLShaderModule&) = delete; OpenGLShaderModule(OpenGLShaderModule&&) noexcept = default; ~OpenGLShaderModule() = default; diff --git a/include/Nazara/Renderer/RenderDevice.hpp b/include/Nazara/Renderer/RenderDevice.hpp index fd2531794..8132eb118 100644 --- a/include/Nazara/Renderer/RenderDevice.hpp +++ b/include/Nazara/Renderer/RenderDevice.hpp @@ -40,8 +40,8 @@ namespace Nz virtual std::shared_ptr InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) = 0; virtual std::shared_ptr InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) = 0; virtual std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states) = 0; - virtual std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize) = 0; - std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const std::filesystem::path& sourcePath); + virtual std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const ShaderWriter::States& states) = 0; + std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const std::filesystem::path& sourcePath, const ShaderWriter::States& states); virtual std::shared_ptr InstantiateTexture(const TextureInfo& params) = 0; virtual std::shared_ptr InstantiateTextureSampler(const TextureSamplerInfo& params) = 0; }; diff --git a/include/Nazara/Shader/Ast/AstCloner.hpp b/include/Nazara/Shader/Ast/AstCloner.hpp index 6feedc689..35bd3b6ed 100644 --- a/include/Nazara/Shader/Ast/AstCloner.hpp +++ b/include/Nazara/Shader/Ast/AstCloner.hpp @@ -45,6 +45,7 @@ namespace Nz::ShaderAst virtual ExpressionPtr Clone(ConstantExpression& node); virtual ExpressionPtr Clone(IdentifierExpression& node); virtual ExpressionPtr Clone(IntrinsicExpression& node); + virtual ExpressionPtr Clone(SelectOptionExpression& node); virtual ExpressionPtr Clone(SwizzleExpression& node); virtual ExpressionPtr Clone(VariableExpression& node); @@ -52,6 +53,7 @@ namespace Nz::ShaderAst virtual StatementPtr Clone(ConditionalStatement& node); virtual StatementPtr Clone(DeclareExternalStatement& node); virtual StatementPtr Clone(DeclareFunctionStatement& node); + virtual StatementPtr Clone(DeclareOptionStatement& node); virtual StatementPtr Clone(DeclareStructStatement& node); virtual StatementPtr Clone(DeclareVariableStatement& node); virtual StatementPtr Clone(DiscardStatement& node); diff --git a/include/Nazara/Shader/Ast/AstNodeList.hpp b/include/Nazara/Shader/Ast/AstNodeList.hpp index 0bd48175c..f16cdd9b5 100644 --- a/include/Nazara/Shader/Ast/AstNodeList.hpp +++ b/include/Nazara/Shader/Ast/AstNodeList.hpp @@ -35,12 +35,14 @@ NAZARA_SHADERAST_EXPRESSION(ConditionalExpression) NAZARA_SHADERAST_EXPRESSION(ConstantExpression) NAZARA_SHADERAST_EXPRESSION(IdentifierExpression) NAZARA_SHADERAST_EXPRESSION(IntrinsicExpression) +NAZARA_SHADERAST_EXPRESSION(SelectOptionExpression) NAZARA_SHADERAST_EXPRESSION(SwizzleExpression) NAZARA_SHADERAST_EXPRESSION(VariableExpression) NAZARA_SHADERAST_STATEMENT(BranchStatement) NAZARA_SHADERAST_STATEMENT(ConditionalStatement) NAZARA_SHADERAST_STATEMENT(DeclareExternalStatement) NAZARA_SHADERAST_STATEMENT(DeclareFunctionStatement) +NAZARA_SHADERAST_STATEMENT(DeclareOptionStatement) NAZARA_SHADERAST_STATEMENT(DeclareStructStatement) NAZARA_SHADERAST_STATEMENT(DeclareVariableStatement) NAZARA_SHADERAST_STATEMENT(DiscardStatement) diff --git a/include/Nazara/Shader/Ast/AstOptimizer.hpp b/include/Nazara/Shader/Ast/AstOptimizer.hpp index 354fe86ba..c52e41ad9 100644 --- a/include/Nazara/Shader/Ast/AstOptimizer.hpp +++ b/include/Nazara/Shader/Ast/AstOptimizer.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include namespace Nz::ShaderAst @@ -29,16 +30,15 @@ namespace Nz::ShaderAst AstOptimizer& operator=(AstOptimizer&&) = delete; protected: - using AstCloner::Visit; - void Visit(BinaryExpression& node) override; - void Visit(ConditionalExpression& node) override; - void Visit(BranchStatement& node) override; - void Visit(ConditionalStatement& node) override; + ExpressionPtr Clone(BinaryExpression& node) override; + ExpressionPtr Clone(ConditionalExpression& node) override; + StatementPtr Clone(BranchStatement& node) override; + StatementPtr Clone(ConditionalStatement& node) override; - template void PropagateConstant(std::unique_ptr&& lhs, std::unique_ptr&& rhs); + template ExpressionPtr PropagateConstant(std::unique_ptr&& lhs, std::unique_ptr&& rhs); private: - UInt64 m_enabledConditions; + std::optional m_enabledOptions; }; } diff --git a/include/Nazara/Shader/Ast/AstRecursiveVisitor.hpp b/include/Nazara/Shader/Ast/AstRecursiveVisitor.hpp index d131931d6..ea605ff6a 100644 --- a/include/Nazara/Shader/Ast/AstRecursiveVisitor.hpp +++ b/include/Nazara/Shader/Ast/AstRecursiveVisitor.hpp @@ -29,6 +29,7 @@ namespace Nz::ShaderAst void Visit(ConstantExpression& node) override; void Visit(IdentifierExpression& node) override; void Visit(IntrinsicExpression& node) override; + void Visit(SelectOptionExpression& node) override; void Visit(SwizzleExpression& node) override; void Visit(VariableExpression& node) override; @@ -36,6 +37,7 @@ namespace Nz::ShaderAst void Visit(ConditionalStatement& node) override; void Visit(DeclareExternalStatement& node) override; void Visit(DeclareFunctionStatement& node) override; + void Visit(DeclareOptionStatement& node) override; void Visit(DeclareStructStatement& node) override; void Visit(DeclareVariableStatement& node) override; void Visit(DiscardStatement& node) override; diff --git a/include/Nazara/Shader/Ast/AstSerializer.hpp b/include/Nazara/Shader/Ast/AstSerializer.hpp index 8b726d19d..193f2f971 100644 --- a/include/Nazara/Shader/Ast/AstSerializer.hpp +++ b/include/Nazara/Shader/Ast/AstSerializer.hpp @@ -32,6 +32,7 @@ namespace Nz::ShaderAst void Serialize(ConstantExpression& node); void Serialize(IdentifierExpression& node); void Serialize(IntrinsicExpression& node); + void Serialize(SelectOptionExpression& node); void Serialize(SwizzleExpression& node); void Serialize(VariableExpression& node); @@ -39,6 +40,7 @@ namespace Nz::ShaderAst void Serialize(ConditionalStatement& node); void Serialize(DeclareExternalStatement& node); void Serialize(DeclareFunctionStatement& node); + void Serialize(DeclareOptionStatement& node); void Serialize(DeclareStructStatement& node); void Serialize(DeclareVariableStatement& node); void Serialize(DiscardStatement& node); diff --git a/include/Nazara/Shader/Ast/AstUtils.hpp b/include/Nazara/Shader/Ast/AstUtils.hpp index d27c41d49..42d7254ab 100644 --- a/include/Nazara/Shader/Ast/AstUtils.hpp +++ b/include/Nazara/Shader/Ast/AstUtils.hpp @@ -40,6 +40,7 @@ namespace Nz::ShaderAst void Visit(ConstantExpression& node) override; void Visit(IdentifierExpression& node) override; void Visit(IntrinsicExpression& node) override; + void Visit(SelectOptionExpression& node) override; void Visit(SwizzleExpression& node) override; void Visit(VariableExpression& node) override; diff --git a/include/Nazara/Shader/Ast/Enums.hpp b/include/Nazara/Shader/Ast/Enums.hpp index 21b1e91a0..90d229000 100644 --- a/include/Nazara/Shader/Ast/Enums.hpp +++ b/include/Nazara/Shader/Ast/Enums.hpp @@ -22,7 +22,8 @@ namespace Nz::ShaderAst Builtin, //< Builtin (struct member only) - has argument type Entry, //< Entry point (function only) - has argument type Layout, //< Struct layout (struct only) - has argument style - Location //< Location (struct member only) - has argument index + Location, //< Location (struct member only) - has argument index + Option, //< Conditional compilation option - has argument expr }; enum class BinaryType diff --git a/include/Nazara/Shader/Ast/Nodes.hpp b/include/Nazara/Shader/Ast/Nodes.hpp index 0d9f67067..8ac4942b3 100644 --- a/include/Nazara/Shader/Ast/Nodes.hpp +++ b/include/Nazara/Shader/Ast/Nodes.hpp @@ -116,7 +116,7 @@ namespace Nz::ShaderAst NodeType GetType() const override; void Visit(AstExpressionVisitor& visitor) override; - std::string conditionName; + std::size_t optionIndex; ExpressionPtr falsePath; ExpressionPtr truePath; }; @@ -146,6 +146,16 @@ namespace Nz::ShaderAst std::vector parameters; }; + struct NAZARA_SHADER_API SelectOptionExpression : public Expression + { + NodeType GetType() const override; + void Visit(AstExpressionVisitor& visitor) override; + + std::string optionName; + ExpressionPtr falsePath; + ExpressionPtr truePath; + }; + struct NAZARA_SHADER_API SwizzleExpression : public Expression { NodeType GetType() const override; @@ -203,7 +213,7 @@ namespace Nz::ShaderAst NodeType GetType() const override; void Visit(AstStatementVisitor& visitor) override; - std::string conditionName; + std::size_t optionIndex; StatementPtr statement; }; @@ -237,12 +247,24 @@ namespace Nz::ShaderAst std::optional entryStage; std::optional funcIndex; std::optional varIndex; + std::string optionName; std::string name; std::vector parameters; std::vector statements; ExpressionType returnType; }; + struct NAZARA_SHADER_API DeclareOptionStatement : Statement + { + NodeType GetType() const override; + void Visit(AstStatementVisitor& visitor) override; + + std::optional optIndex; + std::string optName; + ExpressionPtr initialValue; + ExpressionType optType; + }; + struct NAZARA_SHADER_API DeclareStructStatement : Statement { NodeType GetType() const override; diff --git a/include/Nazara/Shader/Ast/SanitizeVisitor.hpp b/include/Nazara/Shader/Ast/SanitizeVisitor.hpp index e3e541ba5..8016e13d7 100644 --- a/include/Nazara/Shader/Ast/SanitizeVisitor.hpp +++ b/include/Nazara/Shader/Ast/SanitizeVisitor.hpp @@ -17,16 +17,24 @@ namespace Nz::ShaderAst class NAZARA_SHADER_API SanitizeVisitor final : AstCloner { public: + struct Options; + inline SanitizeVisitor(); SanitizeVisitor(const SanitizeVisitor&) = delete; SanitizeVisitor(SanitizeVisitor&&) = delete; ~SanitizeVisitor() = default; - StatementPtr Sanitize(StatementPtr& statement, std::string* error = nullptr); + inline StatementPtr Sanitize(StatementPtr& statement, std::string* error = nullptr); + StatementPtr Sanitize(StatementPtr& statement, const Options& options, std::string* error = nullptr); SanitizeVisitor& operator=(const SanitizeVisitor&) = delete; SanitizeVisitor& operator=(SanitizeVisitor&&) = delete; + struct Options + { + bool removeOptionDeclaration = true; + }; + private: struct Identifier; @@ -42,12 +50,14 @@ namespace Nz::ShaderAst ExpressionPtr Clone(ConstantExpression& node) override; ExpressionPtr Clone(IdentifierExpression& node) override; ExpressionPtr Clone(IntrinsicExpression& node) override; + ExpressionPtr Clone(SelectOptionExpression& node) override; ExpressionPtr Clone(SwizzleExpression& node) override; StatementPtr Clone(BranchStatement& node) override; StatementPtr Clone(ConditionalStatement& node) override; StatementPtr Clone(DeclareExternalStatement& node) override; StatementPtr Clone(DeclareFunctionStatement& node) override; + StatementPtr Clone(DeclareOptionStatement& node) override; StatementPtr Clone(DeclareStructStatement& node) override; StatementPtr Clone(DeclareVariableStatement& node) override; StatementPtr Clone(ExpressionStatement& node) override; @@ -64,6 +74,7 @@ namespace Nz::ShaderAst void PopScope(); inline std::size_t RegisterFunction(std::string name); + inline std::size_t RegisterOption(std::string name, ExpressionType type); inline std::size_t RegisterStruct(std::string name, StructDescription description); inline std::size_t RegisterVariable(std::string name, ExpressionType type); @@ -78,6 +89,11 @@ namespace Nz::ShaderAst std::variant value; }; + struct Option + { + std::size_t optionIndex; + }; + struct Struct { std::size_t structIndex; @@ -91,11 +107,12 @@ namespace Nz::ShaderAst struct Identifier { std::string name; - std::variant value; + std::variant value; }; std::size_t m_nextFuncIndex; std::vector m_identifiersInScope; + std::vector m_options; std::vector m_structs; std::vector m_variables; std::vector m_scopeSizes; @@ -105,6 +122,7 @@ namespace Nz::ShaderAst }; inline StatementPtr Sanitize(StatementPtr& ast, std::string* error = nullptr); + inline StatementPtr Sanitize(StatementPtr& ast, const SanitizeVisitor::Options& options, std::string* error = nullptr); } #include diff --git a/include/Nazara/Shader/Ast/SanitizeVisitor.inl b/include/Nazara/Shader/Ast/SanitizeVisitor.inl index 29a902b8a..5c1c32f93 100644 --- a/include/Nazara/Shader/Ast/SanitizeVisitor.inl +++ b/include/Nazara/Shader/Ast/SanitizeVisitor.inl @@ -12,6 +12,11 @@ namespace Nz::ShaderAst { } + inline StatementPtr SanitizeVisitor::Sanitize(StatementPtr& statement, std::string* error) + { + return Sanitize(statement, {}, error); + } + inline auto SanitizeVisitor::FindIdentifier(const std::string_view& identifierName) const -> const Identifier* { auto it = std::find_if(m_identifiersInScope.rbegin(), m_identifiersInScope.rend(), [&](const Identifier& identifier) { return identifier.name == identifierName; }); @@ -23,10 +28,23 @@ namespace Nz::ShaderAst inline std::size_t SanitizeVisitor::RegisterFunction(std::string name) { - std::size_t funcIndex = m_nextFuncIndex++; - return funcIndex; + return m_nextFuncIndex++; } + inline std::size_t SanitizeVisitor::RegisterOption(std::string name, ExpressionType type) + { + std::size_t optionIndex = m_options.size(); + m_options.emplace_back(std::move(type)); + + m_identifiersInScope.push_back({ + std::move(name), + Option { + optionIndex + } + }); + + return optionIndex; + } inline std::size_t SanitizeVisitor::RegisterStruct(std::string name, StructDescription description) { @@ -63,6 +81,12 @@ namespace Nz::ShaderAst SanitizeVisitor sanitizer; return sanitizer.Sanitize(ast, error); } + + StatementPtr Sanitize(StatementPtr& ast, const SanitizeVisitor::Options& options, std::string* error) + { + SanitizeVisitor sanitizer; + return sanitizer.Sanitize(ast, options, error); + } } #include diff --git a/include/Nazara/Shader/GlslWriter.hpp b/include/Nazara/Shader/GlslWriter.hpp index a0530230c..582af602a 100644 --- a/include/Nazara/Shader/GlslWriter.hpp +++ b/include/Nazara/Shader/GlslWriter.hpp @@ -29,8 +29,8 @@ namespace Nz GlslWriter(GlslWriter&&) = delete; ~GlslWriter() = default; - inline std::string Generate(ShaderAst::StatementPtr& shader, const States& conditions = {}); - std::string Generate(std::optional shaderStage, ShaderAst::StatementPtr& shader, const States& conditions = {}); + inline std::string Generate(ShaderAst::StatementPtr& shader, const States& states = {}); + std::string Generate(std::optional shaderStage, ShaderAst::StatementPtr& shader, const States& states = {}); void SetEnv(Environment environment); @@ -60,7 +60,6 @@ namespace Nz template void Append(const T& param); template void Append(const T1& firstParam, const T2& secondParam, Args&&... params); void AppendCommentSection(const std::string& section); - void AppendEntryPoint(ShaderStageType shaderStage, ShaderAst::StatementPtr& shader); void AppendField(std::size_t structIndex, const std::size_t* memberIndices, std::size_t remainingMembers); void AppendHeader(); void AppendLine(const std::string& txt = {}); diff --git a/include/Nazara/Shader/GlslWriter.inl b/include/Nazara/Shader/GlslWriter.inl index e8c4d052c..dc736e182 100644 --- a/include/Nazara/Shader/GlslWriter.inl +++ b/include/Nazara/Shader/GlslWriter.inl @@ -12,9 +12,9 @@ namespace Nz { } - inline std::string GlslWriter::Generate(ShaderAst::StatementPtr& shader, const States& conditions) + inline std::string GlslWriter::Generate(ShaderAst::StatementPtr& shader, const States& states) { - return Generate(std::nullopt, shader, conditions); + return Generate(std::nullopt, shader, states); } } diff --git a/include/Nazara/Shader/LangWriter.hpp b/include/Nazara/Shader/LangWriter.hpp new file mode 100644 index 000000000..2a111f47b --- /dev/null +++ b/include/Nazara/Shader/LangWriter.hpp @@ -0,0 +1,111 @@ +// Copyright (C) 2020 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_LANGWRITER_HPP +#define NAZARA_LANGWRITER_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + class NAZARA_SHADER_API LangWriter : public ShaderWriter, public ShaderAst::ExpressionVisitorExcept, public ShaderAst::StatementVisitorExcept + { + public: + struct Environment; + + inline LangWriter(); + LangWriter(const LangWriter&) = delete; + LangWriter(LangWriter&&) = delete; + ~LangWriter() = default; + + std::string Generate(ShaderAst::StatementPtr& shader, const States& conditions = {}); + + void SetEnv(Environment environment); + + struct Environment + { + }; + + private: + struct BindingAttribute; + struct BuiltinAttribute; + struct EntryAttribute; + struct LayoutAttribute; + struct LocationAttribute; + + void Append(const ShaderAst::ExpressionType& type); + void Append(const ShaderAst::IdentifierType& identifierType); + void Append(const ShaderAst::MatrixType& matrixType); + void Append(ShaderAst::NoType); + void Append(ShaderAst::PrimitiveType type); + void Append(const ShaderAst::SamplerType& samplerType); + void Append(const ShaderAst::StructType& structType); + void Append(const ShaderAst::UniformType& uniformType); + void Append(const ShaderAst::VectorType& vecType); + template void Append(const T& param); + template void Append(const T1& firstParam, const T2& secondParam, Args&&... params); + template void AppendAttributes(bool appendLine, Args&&... params); + void AppendAttribute(BindingAttribute builtin); + void AppendAttribute(BuiltinAttribute builtin); + void AppendAttribute(EntryAttribute entry); + void AppendAttribute(LayoutAttribute layout); + void AppendAttribute(LocationAttribute location); + void AppendCommentSection(const std::string& section); + void AppendField(std::size_t structIndex, const std::size_t* memberIndices, std::size_t remainingMembers); + void AppendHeader(); + void AppendLine(const std::string& txt = {}); + template void AppendLine(Args&&... params); + void AppendStatementList(std::vector& statements); + + void EnterScope(); + void LeaveScope(bool skipLine = true); + + void RegisterOption(std::size_t optionIndex, std::string optionName); + void RegisterStruct(std::size_t structIndex, ShaderAst::StructDescription desc); + void RegisterVariable(std::size_t varIndex, std::string varName); + + void Visit(ShaderAst::ExpressionPtr& expr, bool encloseIfRequired = false); + + void Visit(ShaderAst::AccessMemberIndexExpression& node) override; + void Visit(ShaderAst::AssignExpression& node) override; + void Visit(ShaderAst::BinaryExpression& node) override; + void Visit(ShaderAst::CastExpression& node) override; + void Visit(ShaderAst::ConditionalExpression& node) override; + void Visit(ShaderAst::ConstantExpression& node) override; + void Visit(ShaderAst::IntrinsicExpression& node) override; + void Visit(ShaderAst::SwizzleExpression& node) override; + void Visit(ShaderAst::VariableExpression& node) override; + + void Visit(ShaderAst::BranchStatement& node) override; + void Visit(ShaderAst::ConditionalStatement& node) override; + void Visit(ShaderAst::DeclareExternalStatement& node) override; + void Visit(ShaderAst::DeclareFunctionStatement& node) override; + void Visit(ShaderAst::DeclareOptionStatement& node) override; + void Visit(ShaderAst::DeclareStructStatement& node) override; + void Visit(ShaderAst::DeclareVariableStatement& node) override; + void Visit(ShaderAst::DiscardStatement& node) override; + void Visit(ShaderAst::ExpressionStatement& node) override; + void Visit(ShaderAst::MultiStatement& node) override; + void Visit(ShaderAst::NoOpStatement& node) override; + void Visit(ShaderAst::ReturnStatement& node) override; + + struct State; + + Environment m_environment; + State* m_currentState; + }; +} + +#include + +#endif diff --git a/include/Nazara/Shader/LangWriter.inl b/include/Nazara/Shader/LangWriter.inl new file mode 100644 index 000000000..adc74afe4 --- /dev/null +++ b/include/Nazara/Shader/LangWriter.inl @@ -0,0 +1,16 @@ +// 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 +#include + +namespace Nz +{ + inline LangWriter::LangWriter() : + m_currentState(nullptr) + { + } +} + +#include diff --git a/include/Nazara/Shader/ShaderBuilder.hpp b/include/Nazara/Shader/ShaderBuilder.hpp index 0d5e44021..434e05cfe 100644 --- a/include/Nazara/Shader/ShaderBuilder.hpp +++ b/include/Nazara/Shader/ShaderBuilder.hpp @@ -44,12 +44,12 @@ namespace Nz::ShaderBuilder struct ConditionalExpression { - inline std::unique_ptr operator()(std::string conditionName, ShaderAst::ExpressionPtr truePath, ShaderAst::ExpressionPtr falsePath) const; + inline std::unique_ptr operator()(std::size_t optionIndex, ShaderAst::ExpressionPtr truePath, ShaderAst::ExpressionPtr falsePath) const; }; struct ConditionalStatement { - inline std::unique_ptr operator()(std::string conditionName, ShaderAst::StatementPtr statement) const; + inline std::unique_ptr operator()(std::size_t optionIndex, ShaderAst::StatementPtr statement) const; }; struct Constant @@ -64,6 +64,11 @@ namespace Nz::ShaderBuilder inline std::unique_ptr operator()(std::optional entryStage, std::string name, std::vector parameters, std::vector statements, ShaderAst::ExpressionType returnType = ShaderAst::NoType{}) const; }; + struct DeclareOption + { + inline std::unique_ptr operator()(std::string name, ShaderAst::ExpressionType type, ShaderAst::ExpressionPtr initialValue = nullptr) const; + }; + struct DeclareStruct { inline std::unique_ptr operator()(ShaderAst::StructDescription description) const; @@ -106,6 +111,11 @@ namespace Nz::ShaderBuilder inline std::unique_ptr operator()(ShaderAst::ExpressionPtr expr = nullptr) const; }; + struct SelectOption + { + inline std::unique_ptr operator()(std::string optionName, ShaderAst::ExpressionPtr truePath, ShaderAst::ExpressionPtr falsePath) const; + }; + struct Swizzle { inline std::unique_ptr operator()(ShaderAst::ExpressionPtr expression, std::vector swizzleComponents) const; @@ -121,6 +131,7 @@ namespace Nz::ShaderBuilder constexpr Impl::ConditionalStatement ConditionalStatement; constexpr Impl::Constant Constant; constexpr Impl::DeclareFunction DeclareFunction; + constexpr Impl::DeclareOption DeclareOption; constexpr Impl::DeclareStruct DeclareStruct; constexpr Impl::DeclareVariable DeclareVariable; constexpr Impl::ExpressionStatement ExpressionStatement; @@ -130,6 +141,7 @@ namespace Nz::ShaderBuilder constexpr Impl::Multi MultiStatement; constexpr Impl::NoParam NoOp; constexpr Impl::Return Return; + constexpr Impl::SelectOption SelectOption; constexpr Impl::Swizzle Swizzle; } diff --git a/include/Nazara/Shader/ShaderBuilder.inl b/include/Nazara/Shader/ShaderBuilder.inl index d48263e01..93287e2b6 100644 --- a/include/Nazara/Shader/ShaderBuilder.inl +++ b/include/Nazara/Shader/ShaderBuilder.inl @@ -70,20 +70,20 @@ namespace Nz::ShaderBuilder return castNode; } - inline std::unique_ptr Impl::ConditionalExpression::operator()(std::string conditionName, ShaderAst::ExpressionPtr truePath, ShaderAst::ExpressionPtr falsePath) const + inline std::unique_ptr Impl::ConditionalExpression::operator()(std::size_t optionIndex, ShaderAst::ExpressionPtr truePath, ShaderAst::ExpressionPtr falsePath) const { auto condExprNode = std::make_unique(); - condExprNode->conditionName = std::move(conditionName); + condExprNode->optionIndex = optionIndex; condExprNode->falsePath = std::move(falsePath); condExprNode->truePath = std::move(truePath); return condExprNode; } - inline std::unique_ptr Impl::ConditionalStatement::operator()(std::string conditionName, ShaderAst::StatementPtr statement) const + inline std::unique_ptr Impl::ConditionalStatement::operator()(std::size_t optionIndex, ShaderAst::StatementPtr statement) const { auto condStatementNode = std::make_unique(); - condStatementNode->conditionName = std::move(conditionName); + condStatementNode->optionIndex = optionIndex; condStatementNode->statement = std::move(statement); return condStatementNode; @@ -129,6 +129,16 @@ namespace Nz::ShaderBuilder return declareFunctionNode; } + inline std::unique_ptr Nz::ShaderBuilder::Impl::DeclareOption::operator()(std::string name, ShaderAst::ExpressionType type, ShaderAst::ExpressionPtr initialValue) const + { + auto declareOptionNode = std::make_unique(); + declareOptionNode->optName = std::move(name); + declareOptionNode->optType = std::move(type); + declareOptionNode->initialValue = std::move(initialValue); + + return declareOptionNode; + } + inline std::unique_ptr Impl::DeclareStruct::operator()(ShaderAst::StructDescription description) const { auto declareStructNode = std::make_unique(); @@ -203,6 +213,16 @@ namespace Nz::ShaderBuilder return returnNode; } + inline std::unique_ptr Impl::SelectOption::operator()(std::string optionName, ShaderAst::ExpressionPtr truePath, ShaderAst::ExpressionPtr falsePath) const + { + auto selectOptNode = std::make_unique(); + selectOptNode->optionName = std::move(optionName); + selectOptNode->falsePath = std::move(falsePath); + selectOptNode->truePath = std::move(truePath); + + return selectOptNode; + } + inline std::unique_ptr Impl::Swizzle::operator()(ShaderAst::ExpressionPtr expression, std::vector swizzleComponents) const { auto swizzleNode = std::make_unique(); diff --git a/include/Nazara/Shader/ShaderLangParser.hpp b/include/Nazara/Shader/ShaderLangParser.hpp index 4780a022c..24f6ca085 100644 --- a/include/Nazara/Shader/ShaderLangParser.hpp +++ b/include/Nazara/Shader/ShaderLangParser.hpp @@ -85,6 +85,7 @@ namespace Nz::ShaderLang std::vector ParseFunctionBody(); ShaderAst::StatementPtr ParseFunctionDeclaration(std::vector attributes = {}); ShaderAst::DeclareFunctionStatement::Parameter ParseFunctionParameter(); + ShaderAst::StatementPtr ParseOptionDeclaration(); ShaderAst::StatementPtr ParseStructDeclaration(std::vector attributes = {}); ShaderAst::StatementPtr ParseReturnStatement(); ShaderAst::StatementPtr ParseStatement(); @@ -100,6 +101,7 @@ namespace Nz::ShaderLang std::vector ParseParameters(); ShaderAst::ExpressionPtr ParseParenthesisExpression(); ShaderAst::ExpressionPtr ParsePrimaryExpression(); + ShaderAst::ExpressionPtr ParseSelectOptExpression(); ShaderAst::ExpressionPtr ParseVariableAssignation(); ShaderAst::AttributeType ParseIdentifierAsAttributeType(); diff --git a/include/Nazara/Shader/ShaderLangTokenList.hpp b/include/Nazara/Shader/ShaderLangTokenList.hpp index 183a16062..a7b8c50f7 100644 --- a/include/Nazara/Shader/ShaderLangTokenList.hpp +++ b/include/Nazara/Shader/ShaderLangTokenList.hpp @@ -40,8 +40,10 @@ NAZARA_SHADERLANG_TOKEN(Plus) NAZARA_SHADERLANG_TOKEN(OpenCurlyBracket) NAZARA_SHADERLANG_TOKEN(OpenSquareBracket) NAZARA_SHADERLANG_TOKEN(OpenParenthesis) +NAZARA_SHADERLANG_TOKEN(Option) NAZARA_SHADERLANG_TOKEN(Semicolon) NAZARA_SHADERLANG_TOKEN(Return) +NAZARA_SHADERLANG_TOKEN(SelectOpt) NAZARA_SHADERLANG_TOKEN(Struct) #undef NAZARA_SHADERLANG_TOKEN diff --git a/include/Nazara/Shader/ShaderWriter.hpp b/include/Nazara/Shader/ShaderWriter.hpp index 47fb04a6f..e955c8535 100644 --- a/include/Nazara/Shader/ShaderWriter.hpp +++ b/include/Nazara/Shader/ShaderWriter.hpp @@ -26,7 +26,7 @@ namespace Nz struct States { - Nz::UInt64 enabledConditions = 0; + Nz::UInt64 enabledOptions = 0; }; }; } diff --git a/include/Nazara/Shader/SpirvWriter.hpp b/include/Nazara/Shader/SpirvWriter.hpp index 284e76a94..52695d2c2 100644 --- a/include/Nazara/Shader/SpirvWriter.hpp +++ b/include/Nazara/Shader/SpirvWriter.hpp @@ -36,7 +36,7 @@ namespace Nz SpirvWriter(SpirvWriter&&) = delete; ~SpirvWriter() = default; - std::vector Generate(ShaderAst::StatementPtr& shader, const States& conditions = {}); + std::vector Generate(ShaderAst::StatementPtr& shader, const States& states = {}); void SetEnv(Environment environment); @@ -62,7 +62,7 @@ namespace Nz UInt32 GetPointerTypeId(const ShaderAst::ExpressionType& type, SpirvStorageClass storageClass) const; UInt32 GetTypeId(const ShaderAst::ExpressionType& type) const; - inline bool IsConditionEnabled(const std::string& condition) const; + bool IsOptionEnabled(std::size_t optionIndex) const; UInt32 RegisterConstant(const ShaderAst::ConstantValue& value); UInt32 RegisterFunctionType(const ShaderAst::DeclareFunctionStatement& functionNode); diff --git a/include/Nazara/Shader/SpirvWriter.inl b/include/Nazara/Shader/SpirvWriter.inl index 903d6265b..0be50bead 100644 --- a/include/Nazara/Shader/SpirvWriter.inl +++ b/include/Nazara/Shader/SpirvWriter.inl @@ -8,14 +8,6 @@ namespace Nz { - inline bool SpirvWriter::IsConditionEnabled(const std::string& condition) const - { - /*std::size_t conditionIndex = m_context.shader->FindConditionByName(condition); - assert(conditionIndex != ShaderAst::InvalidCondition); - - return TestBit(m_context.states->enabledConditions, conditionIndex);*/ - return false; - } } #include diff --git a/include/Nazara/VulkanRenderer/VulkanDevice.hpp b/include/Nazara/VulkanRenderer/VulkanDevice.hpp index d8dc546b6..603532e18 100644 --- a/include/Nazara/VulkanRenderer/VulkanDevice.hpp +++ b/include/Nazara/VulkanRenderer/VulkanDevice.hpp @@ -30,7 +30,7 @@ namespace Nz std::shared_ptr InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override; std::shared_ptr InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) override; std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags stages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states) override; - std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags stages, ShaderLanguage lang, const void* source, std::size_t sourceSize) override; + std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags stages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const ShaderWriter::States& states) override; std::shared_ptr InstantiateTexture(const TextureInfo& params) override; std::shared_ptr InstantiateTextureSampler(const TextureSamplerInfo& params) override; diff --git a/include/Nazara/VulkanRenderer/VulkanShaderModule.hpp b/include/Nazara/VulkanRenderer/VulkanShaderModule.hpp index 4017cbfe3..c3bc405f0 100644 --- a/include/Nazara/VulkanRenderer/VulkanShaderModule.hpp +++ b/include/Nazara/VulkanRenderer/VulkanShaderModule.hpp @@ -28,7 +28,7 @@ namespace Nz ~VulkanShaderModule() = default; bool Create(Vk::Device& device, ShaderStageTypeFlags shaderStages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states); - bool Create(Vk::Device& device, ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize); + bool Create(Vk::Device& device, ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const ShaderWriter::States& states); inline const Vk::ShaderModule& GetHandle() const; inline const std::vector& GetStages() const; diff --git a/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp b/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp index a6425aa9f..902bfda5f 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp @@ -85,9 +85,9 @@ namespace Nz return std::make_shared(*this, shaderStages, shaderAst, states); } - std::shared_ptr OpenGLDevice::InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize) + std::shared_ptr OpenGLDevice::InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const ShaderWriter::States& states) { - return std::make_shared(*this, shaderStages, lang, source, sourceSize); + return std::make_shared(*this, shaderStages, lang, source, sourceSize, states); } std::shared_ptr OpenGLDevice::InstantiateTexture(const TextureInfo& params) diff --git a/src/Nazara/OpenGLRenderer/OpenGLShaderModule.cpp b/src/Nazara/OpenGLRenderer/OpenGLShaderModule.cpp index 4486a07e6..4eb1154f2 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLShaderModule.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLShaderModule.cpp @@ -21,7 +21,7 @@ namespace Nz Create(device, shaderStages, shaderAst, states); } - OpenGLShaderModule::OpenGLShaderModule(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize) + OpenGLShaderModule::OpenGLShaderModule(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const ShaderWriter::States& states) { NazaraAssert(shaderStages != 0, "at least one shader stage must be specified"); @@ -65,7 +65,7 @@ namespace Nz Nz::ShaderLang::Parser parser; Nz::ShaderAst::StatementPtr shaderAst = parser.Parse(tokens); - Create(device, shaderStages, shaderAst, {}); + Create(device, shaderStages, shaderAst, states); break; } diff --git a/src/Nazara/Renderer/RenderDevice.cpp b/src/Nazara/Renderer/RenderDevice.cpp index 0d71e5e66..19582f718 100644 --- a/src/Nazara/Renderer/RenderDevice.cpp +++ b/src/Nazara/Renderer/RenderDevice.cpp @@ -11,7 +11,7 @@ namespace Nz { RenderDevice::~RenderDevice() = default; - std::shared_ptr RenderDevice::InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const std::filesystem::path& sourcePath) + std::shared_ptr RenderDevice::InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const std::filesystem::path& sourcePath, const ShaderWriter::States& states) { File file(sourcePath); if (!file.Open(OpenMode_ReadOnly | OpenMode_Text)) @@ -29,6 +29,6 @@ namespace Nz return {}; } - return InstantiateShaderModule(shaderStages, lang, source.data(), source.size()); + return InstantiateShaderModule(shaderStages, lang, source.data(), source.size(), states); } } diff --git a/src/Nazara/Shader/Ast/AstCloner.cpp b/src/Nazara/Shader/Ast/AstCloner.cpp index 602ddcd94..2571b86e5 100644 --- a/src/Nazara/Shader/Ast/AstCloner.cpp +++ b/src/Nazara/Shader/Ast/AstCloner.cpp @@ -56,7 +56,7 @@ namespace Nz::ShaderAst StatementPtr AstCloner::Clone(ConditionalStatement& node) { auto clone = std::make_unique(); - clone->conditionName = node.conditionName; + clone->optionIndex = node.optionIndex; clone->statement = CloneStatement(node.statement); return clone; @@ -77,6 +77,7 @@ namespace Nz::ShaderAst clone->entryStage = node.entryStage; clone->funcIndex = node.funcIndex; clone->name = node.name; + clone->optionName = node.optionName; clone->parameters = node.parameters; clone->returnType = node.returnType; clone->varIndex = node.varIndex; @@ -88,6 +89,17 @@ namespace Nz::ShaderAst return clone; } + StatementPtr AstCloner::Clone(DeclareOptionStatement& node) + { + auto clone = std::make_unique(); + clone->initialValue = CloneExpression(node.initialValue); + clone->optIndex = node.optIndex; + clone->optName = node.optName; + clone->optType = node.optType; + + return clone; + } + StatementPtr AstCloner::Clone(DeclareStructStatement& node) { auto clone = std::make_unique(); @@ -212,7 +224,7 @@ namespace Nz::ShaderAst ExpressionPtr AstCloner::Clone(ConditionalExpression& node) { auto clone = std::make_unique(); - clone->conditionName = node.conditionName; + clone->optionIndex = node.optionIndex; clone->falsePath = CloneExpression(node.falsePath); clone->truePath = CloneExpression(node.truePath); @@ -255,6 +267,18 @@ namespace Nz::ShaderAst return clone; } + ExpressionPtr AstCloner::Clone(SelectOptionExpression& node) + { + auto clone = std::make_unique(); + clone->optionName = node.optionName; + clone->falsePath = CloneExpression(node.falsePath); + clone->truePath = CloneExpression(node.truePath); + + clone->cachedExpressionType = node.cachedExpressionType; + + return clone; + } + ExpressionPtr AstCloner::Clone(SwizzleExpression& node) { auto clone = std::make_unique(); diff --git a/src/Nazara/Shader/Ast/AstRecursiveVisitor.cpp b/src/Nazara/Shader/Ast/AstRecursiveVisitor.cpp index 7e33c9590..85e8b2507 100644 --- a/src/Nazara/Shader/Ast/AstRecursiveVisitor.cpp +++ b/src/Nazara/Shader/Ast/AstRecursiveVisitor.cpp @@ -62,6 +62,12 @@ namespace Nz::ShaderAst param->Visit(*this); } + void AstRecursiveVisitor::Visit(SelectOptionExpression& node) + { + node.truePath->Visit(*this); + node.falsePath->Visit(*this); + } + void AstRecursiveVisitor::Visit(SwizzleExpression& node) { node.expression->Visit(*this); @@ -100,6 +106,12 @@ namespace Nz::ShaderAst statement->Visit(*this); } + void AstRecursiveVisitor::Visit(DeclareOptionStatement& node) + { + if (node.initialValue) + node.initialValue->Visit(*this); + } + void AstRecursiveVisitor::Visit(DeclareStructStatement& /*node*/) { /* Nothing to do */ diff --git a/src/Nazara/Shader/Ast/AstSerializer.cpp b/src/Nazara/Shader/Ast/AstSerializer.cpp index 1c79e7600..fee7d53fd 100644 --- a/src/Nazara/Shader/Ast/AstSerializer.cpp +++ b/src/Nazara/Shader/Ast/AstSerializer.cpp @@ -74,7 +74,7 @@ namespace Nz::ShaderAst void AstSerializerBase::Serialize(ConditionalExpression& node) { - Value(node.conditionName); + SizeT(node.optionIndex); Node(node.truePath); Node(node.falsePath); } @@ -113,14 +113,6 @@ namespace Nz::ShaderAst } } - void AstSerializerBase::Serialize(DeclareVariableStatement& node) - { - OptVal(node.varIndex); - Value(node.varName); - Type(node.varType); - Node(node.initialExpression); - } - void AstSerializerBase::Serialize(IdentifierExpression& node) { Value(node.identifier); @@ -134,6 +126,13 @@ namespace Nz::ShaderAst Node(param); } + void AstSerializerBase::Serialize(SelectOptionExpression& node) + { + Value(node.optionName); + Node(node.truePath); + Node(node.falsePath); + } + void AstSerializerBase::Serialize(SwizzleExpression& node) { SizeT(node.componentCount); @@ -163,7 +162,7 @@ namespace Nz::ShaderAst void AstSerializerBase::Serialize(ConditionalStatement& node) { - Value(node.conditionName); + SizeT(node.optionIndex); Node(node.statement); } @@ -186,6 +185,7 @@ namespace Nz::ShaderAst Type(node.returnType); OptEnum(node.entryStage); OptVal(node.funcIndex); + Value(node.optionName); OptVal(node.varIndex); Container(node.parameters); @@ -200,6 +200,14 @@ namespace Nz::ShaderAst Node(statement); } + void AstSerializerBase::Serialize(DeclareOptionStatement& node) + { + OptVal(node.optIndex); + Value(node.optName); + Type(node.optType); + Node(node.initialValue); + } + void AstSerializerBase::Serialize(DeclareStructStatement& node) { OptVal(node.structIndex); @@ -216,6 +224,14 @@ namespace Nz::ShaderAst OptVal(member.locationIndex); } } + + void AstSerializerBase::Serialize(DeclareVariableStatement& node) + { + OptVal(node.varIndex); + Value(node.varName); + Type(node.varType); + Node(node.initialExpression); + } void AstSerializerBase::Serialize(DiscardStatement& /*node*/) { diff --git a/src/Nazara/Shader/Ast/AstUtils.cpp b/src/Nazara/Shader/Ast/AstUtils.cpp index a6895177a..76496ddf0 100644 --- a/src/Nazara/Shader/Ast/AstUtils.cpp +++ b/src/Nazara/Shader/Ast/AstUtils.cpp @@ -67,6 +67,20 @@ namespace Nz::ShaderAst m_expressionCategory = ExpressionCategory::RValue; } + void ShaderAstValueCategory::Visit(SelectOptionExpression& node) + { + node.truePath->Visit(*this); + ExpressionCategory trueExprCategory = m_expressionCategory; + + node.falsePath->Visit(*this); + ExpressionCategory falseExprCategory = m_expressionCategory; + + if (trueExprCategory == ExpressionCategory::RValue || falseExprCategory == ExpressionCategory::RValue) + m_expressionCategory = ExpressionCategory::RValue; + else + m_expressionCategory = ExpressionCategory::LValue; + } + void ShaderAstValueCategory::Visit(SwizzleExpression& node) { node.expression->Visit(*this); diff --git a/src/Nazara/Shader/Ast/Nodes.cpp b/src/Nazara/Shader/Ast/Nodes.cpp index aed845fc5..b334d76ec 100644 --- a/src/Nazara/Shader/Ast/Nodes.cpp +++ b/src/Nazara/Shader/Ast/Nodes.cpp @@ -29,4 +29,35 @@ namespace Nz::ShaderAst } #include + + ExpressionType ConstantExpression::GetExpressionType() const + { + return std::visit([&](auto&& arg) -> ShaderAst::ExpressionType + { + using T = std::decay_t; + + if constexpr (std::is_same_v) + return PrimitiveType::Boolean; + else if constexpr (std::is_same_v) + return PrimitiveType::Float32; + else if constexpr (std::is_same_v) + return PrimitiveType::Int32; + else if constexpr (std::is_same_v) + return PrimitiveType::UInt32; + else if constexpr (std::is_same_v) + return VectorType{ 2, PrimitiveType::Float32 }; + else if constexpr (std::is_same_v) + return VectorType{ 3, PrimitiveType::Float32 }; + else if constexpr (std::is_same_v) + return VectorType{ 4, PrimitiveType::Float32 }; + else if constexpr (std::is_same_v) + return VectorType{ 2, PrimitiveType::Int32 }; + else if constexpr (std::is_same_v) + return VectorType{ 3, PrimitiveType::Int32 }; + else if constexpr (std::is_same_v) + return VectorType{ 4, PrimitiveType::Int32 }; + else + static_assert(AlwaysFalse::value, "non-exhaustive visitor"); + }, value); + } } diff --git a/src/Nazara/Shader/Ast/SanitizeVisitor.cpp b/src/Nazara/Shader/Ast/SanitizeVisitor.cpp index 57a3cd8cd..b05194a82 100644 --- a/src/Nazara/Shader/Ast/SanitizeVisitor.cpp +++ b/src/Nazara/Shader/Ast/SanitizeVisitor.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -28,16 +29,18 @@ namespace Nz::ShaderAst struct SanitizeVisitor::Context { + Options options; std::array entryFunctions = {}; std::unordered_set declaredExternalVar; std::unordered_set usedBindingIndexes; }; - StatementPtr SanitizeVisitor::Sanitize(StatementPtr& nodePtr, std::string* error) + StatementPtr SanitizeVisitor::Sanitize(StatementPtr& nodePtr, const Options& options, std::string* error) { StatementPtr clone; Context currentContext; + currentContext.options = options; m_context = ¤tContext; CallOnExit resetContext([&] { m_context = nullptr; }); @@ -483,6 +486,33 @@ namespace Nz::ShaderAst return clone; } + ExpressionPtr SanitizeVisitor::Clone(SelectOptionExpression& node) + { + MandatoryExpr(node.truePath); + MandatoryExpr(node.falsePath); + + auto condExpr = std::make_unique(); + condExpr->truePath = CloneExpression(node.truePath); + condExpr->falsePath = CloneExpression(node.falsePath); + + const Identifier* identifier = FindIdentifier(node.optionName); + if (!identifier) + throw AstError{ "unknown option " + node.optionName }; + + if (!std::holds_alternative