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] 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)