OpenGLRenderer: Allow RenderPipeline without a fragment shader on OpenGL ES
This commit is contained in:
parent
336e70f72e
commit
109b2a156e
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>();
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue