OpenGLRenderer: Allow RenderPipeline without a fragment shader on OpenGL ES

This commit is contained in:
Jérôme Leclercq 2021-05-29 00:32:00 +02:00
parent 336e70f72e
commit 109b2a156e
7 changed files with 60 additions and 11 deletions

View File

@ -374,7 +374,7 @@ int main()
stencilPipelineInfo.stencilBack.compare = Nz::RendererComparison::Always; stencilPipelineInfo.stencilBack.compare = Nz::RendererComparison::Always;
stencilPipelineInfo.stencilBack.depthFail = Nz::StencilOperation::Invert; stencilPipelineInfo.stencilBack.depthFail = Nz::StencilOperation::Invert;
stencilPipelineInfo.shaderModules.push_back(device->InstantiateShaderModule(Nz::ShaderStageType::Fragment | Nz::ShaderStageType::Vertex, Nz::ShaderLanguage::NazaraShader, resourceDir / "lighting.nzsl", {})); stencilPipelineInfo.shaderModules.push_back(device->InstantiateShaderModule(Nz::ShaderStageType::Vertex, Nz::ShaderLanguage::NazaraShader, resourceDir / "lighting.nzsl", {}));
std::shared_ptr<Nz::RenderPipeline> stencilPipeline = device->InstantiateRenderPipeline(stencilPipelineInfo); std::shared_ptr<Nz::RenderPipeline> stencilPipeline = device->InstantiateRenderPipeline(stencilPipelineInfo);

View File

@ -20,23 +20,31 @@ namespace Nz
class NAZARA_OPENGLRENDERER_API OpenGLShaderModule : public ShaderModule class NAZARA_OPENGLRENDERER_API OpenGLShaderModule : public ShaderModule
{ {
public: public:
OpenGLShaderModule(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states); struct Shader;
OpenGLShaderModule(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const ShaderWriter::States& states);
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, const ShaderWriter::States& states = {});
OpenGLShaderModule(const OpenGLShaderModule&) = delete; OpenGLShaderModule(const OpenGLShaderModule&) = delete;
OpenGLShaderModule(OpenGLShaderModule&&) noexcept = default; OpenGLShaderModule(OpenGLShaderModule&&) noexcept = default;
~OpenGLShaderModule() = default; ~OpenGLShaderModule() = default;
inline const std::vector<GL::Shader>& GetShaders() const; inline const std::vector<Shader>& GetShaders() const;
OpenGLShaderModule& operator=(const OpenGLShaderModule&) = delete; OpenGLShaderModule& operator=(const OpenGLShaderModule&) = delete;
OpenGLShaderModule& operator=(OpenGLShaderModule&&) noexcept = default; OpenGLShaderModule& operator=(OpenGLShaderModule&&) noexcept = default;
struct Shader
{
ShaderStageType stage;
GL::Shader shader;
};
private: private:
void Create(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states); void Create(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states);
static void CheckCompilationStatus(GL::Shader& shader); static void CheckCompilationStatus(GL::Shader& shader);
std::vector<GL::Shader> m_shaders; std::vector<Shader> m_shaders;
}; };
} }

View File

@ -7,7 +7,7 @@
namespace Nz namespace Nz
{ {
inline const std::vector<GL::Shader>& OpenGLShaderModule::GetShaders() const inline auto OpenGLShaderModule::GetShaders() const -> const std::vector<Shader>&
{ {
return m_shaders; return m_shaders;
} }

View File

@ -20,6 +20,7 @@ namespace Nz::ShaderBuilder
struct AccessMember struct AccessMember
{ {
inline std::unique_ptr<ShaderAst::AccessMemberIdentifierExpression> operator()(ShaderAst::ExpressionPtr structExpr, std::vector<std::string> memberIdentifiers) const; inline std::unique_ptr<ShaderAst::AccessMemberIdentifierExpression> operator()(ShaderAst::ExpressionPtr structExpr, std::vector<std::string> memberIdentifiers) const;
inline std::unique_ptr<ShaderAst::AccessMemberIndexExpression> operator()(ShaderAst::ExpressionPtr structExpr, std::vector<std::size_t> memberIndices) const;
}; };
struct Assign struct Assign
@ -104,7 +105,7 @@ namespace Nz::ShaderBuilder
struct Multi struct Multi
{ {
inline std::unique_ptr<ShaderAst::MultiStatement> operator()(std::vector<ShaderAst::StatementPtr> statements) const; inline std::unique_ptr<ShaderAst::MultiStatement> operator()(std::vector<ShaderAst::StatementPtr> statements = {}) const;
}; };
template<typename T> template<typename T>

View File

@ -16,6 +16,15 @@ namespace Nz::ShaderBuilder
return accessMemberNode; return accessMemberNode;
} }
inline std::unique_ptr<ShaderAst::AccessMemberIndexExpression> Impl::AccessMember::operator()(ShaderAst::ExpressionPtr structExpr, std::vector<std::size_t> memberIndices) const
{
auto accessMemberNode = std::make_unique<ShaderAst::AccessMemberIndexExpression>();
accessMemberNode->structExpr = std::move(structExpr);
accessMemberNode->memberIndices = std::move(memberIndices);
return accessMemberNode;
}
inline std::unique_ptr<ShaderAst::AssignExpression> Impl::Assign::operator()(ShaderAst::AssignType op, ShaderAst::ExpressionPtr left, ShaderAst::ExpressionPtr right) const inline std::unique_ptr<ShaderAst::AssignExpression> Impl::Assign::operator()(ShaderAst::AssignType op, ShaderAst::ExpressionPtr left, ShaderAst::ExpressionPtr right) const
{ {
auto assignNode = std::make_unique<ShaderAst::AssignExpression>(); auto assignNode = std::make_unique<ShaderAst::AssignExpression>();

View File

@ -8,6 +8,7 @@
#include <Nazara/OpenGLRenderer/OpenGLRenderPipelineLayout.hpp> #include <Nazara/OpenGLRenderer/OpenGLRenderPipelineLayout.hpp>
#include <Nazara/OpenGLRenderer/OpenGLShaderModule.hpp> #include <Nazara/OpenGLRenderer/OpenGLShaderModule.hpp>
#include <Nazara/Shader/GlslWriter.hpp> #include <Nazara/Shader/GlslWriter.hpp>
#include <Nazara/Shader/ShaderBuilder.hpp>
#include <cassert> #include <cassert>
#include <stdexcept> #include <stdexcept>
#include <Nazara/OpenGLRenderer/Debug.hpp> #include <Nazara/OpenGLRenderer/Debug.hpp>
@ -21,11 +22,37 @@ namespace Nz
if (!m_program.Create(device)) if (!m_program.Create(device))
throw std::runtime_error("failed to create program"); throw std::runtime_error("failed to create program");
ShaderStageTypeFlags stageFlags;
for (const auto& shaderModulePtr : m_pipelineInfo.shaderModules) for (const auto& shaderModulePtr : m_pipelineInfo.shaderModules)
{ {
OpenGLShaderModule& shaderModule = static_cast<OpenGLShaderModule&>(*shaderModulePtr); OpenGLShaderModule& shaderModule = static_cast<OpenGLShaderModule&>(*shaderModulePtr);
for (const GL::Shader& shader : shaderModule.GetShaders()) for (const auto& shaderEntry : shaderModule.GetShaders())
m_program.AttachShader(shader.GetObjectId()); {
m_program.AttachShader(shaderEntry.shader.GetObjectId());
stageFlags |= shaderEntry.stage;
}
}
// OpenGL ES programs must have both vertex and fragment shaders or a compute shader or a mesh and fragment shader.
if (device.GetReferenceContext().GetParams().type == GL::ContextType::OpenGL_ES)
{
auto GenerateIfMissing = [&](ShaderStageType stage)
{
if (!stageFlags.Test(stage))
{
ShaderAst::StatementPtr dummyAst = ShaderBuilder::DeclareFunction(stage, "main", {}, {});
OpenGLShaderModule shaderModule(device, stage, dummyAst);
for (const auto& shaderEntry : shaderModule.GetShaders())
{
m_program.AttachShader(shaderEntry.shader.GetObjectId());
stageFlags |= shaderEntry.stage;
}
}
};
GenerateIfMissing(ShaderStageType::Fragment);
GenerateIfMissing(ShaderStageType::Vertex);
} }
m_program.Link(); m_program.Link();

View File

@ -44,7 +44,9 @@ namespace Nz
shader.Compile(); shader.Compile();
CheckCompilationStatus(shader); CheckCompilationStatus(shader);
m_shaders.emplace_back(std::move(shader)); auto& entry = m_shaders.emplace_back();
entry.shader = std::move(shader);
entry.stage = shaderStage;
break; break;
} }
} }
@ -130,7 +132,9 @@ namespace Nz
CheckCompilationStatus(shader); CheckCompilationStatus(shader);
m_shaders.emplace_back(std::move(shader)); auto& entry = m_shaders.emplace_back();
entry.shader = std::move(shader);
entry.stage = shaderStage;
} }
} }
} }