Add initial support for shader binding sets (WIP)
This commit is contained in:
@@ -39,7 +39,7 @@ namespace Nz
|
||||
|
||||
inline void BindIndexBuffer(GLuint indexBuffer, UInt64 offset = 0);
|
||||
inline void BindPipeline(const OpenGLRenderPipeline* pipeline);
|
||||
inline void BindShaderBinding(const OpenGLShaderBinding* binding);
|
||||
inline void BindShaderBinding(const OpenGLRenderPipelineLayout& pipelineLayout, UInt32 set, const OpenGLShaderBinding* binding);
|
||||
inline void BindVertexBuffer(UInt32 binding, GLuint vertexBuffer, UInt64 offset = 0);
|
||||
|
||||
inline void CopyBuffer(GLuint source, GLuint target, UInt64 size, UInt64 sourceOffset = 0, UInt64 targetOffset = 0);
|
||||
@@ -102,10 +102,10 @@ namespace Nz
|
||||
|
||||
GLuint indexBuffer = 0;
|
||||
const OpenGLRenderPipeline* pipeline = nullptr;
|
||||
const OpenGLShaderBinding* shaderBindings = nullptr;
|
||||
UInt64 indexBufferOffset;
|
||||
std::optional<Recti> scissorRegion;
|
||||
std::optional<Recti> viewportRegion;
|
||||
std::vector<std::pair<const OpenGLRenderPipelineLayout*, const OpenGLShaderBinding*>> shaderBindings;
|
||||
std::vector<VertexBuffer> vertexBuffers;
|
||||
bool shouldFlipY = false;
|
||||
};
|
||||
|
||||
@@ -44,9 +44,12 @@ namespace Nz
|
||||
m_currentStates.pipeline = pipeline;
|
||||
}
|
||||
|
||||
inline void OpenGLCommandBuffer::BindShaderBinding(const OpenGLShaderBinding* binding)
|
||||
inline void OpenGLCommandBuffer::BindShaderBinding(const OpenGLRenderPipelineLayout& pipelineLayout, UInt32 set, const OpenGLShaderBinding* binding)
|
||||
{
|
||||
m_currentStates.shaderBindings = binding;
|
||||
if (set >= m_currentStates.shaderBindings.size())
|
||||
m_currentStates.shaderBindings.resize(set + 1);
|
||||
|
||||
m_currentStates.shaderBindings[set] = std::make_pair(&pipelineLayout, binding);
|
||||
}
|
||||
|
||||
inline void OpenGLCommandBuffer::BindVertexBuffer(UInt32 binding, GLuint vertexBuffer, UInt64 offset)
|
||||
|
||||
@@ -28,7 +28,8 @@ namespace Nz
|
||||
|
||||
void BindIndexBuffer(AbstractBuffer* indexBuffer, UInt64 offset = 0) override;
|
||||
void BindPipeline(const RenderPipeline& pipeline) override;
|
||||
void BindShaderBinding(const ShaderBinding& binding) override;
|
||||
void BindShaderBinding(UInt32 set, const ShaderBinding& binding) override;
|
||||
void BindShaderBinding(const RenderPipelineLayout& pipelineLayout, UInt32 set, const ShaderBinding& binding) override;
|
||||
void BindVertexBuffer(UInt32 binding, Nz::AbstractBuffer* vertexBuffer, UInt64 offset = 0) override;
|
||||
|
||||
void CopyBuffer(const RenderBufferView& source, const RenderBufferView& target, UInt64 size, UInt64 sourceOffset = 0, UInt64 targetOffset = 0) override;
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace Nz
|
||||
std::shared_ptr<RenderPass> InstantiateRenderPass(std::vector<RenderPass::Attachment> attachments, std::vector<RenderPass::SubpassDescription> subpassDescriptions, std::vector<RenderPass::SubpassDependency> subpassDependencies) override;
|
||||
std::shared_ptr<RenderPipeline> InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override;
|
||||
std::shared_ptr<RenderPipelineLayout> InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) override;
|
||||
std::shared_ptr<ShaderModule> InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states) override;
|
||||
std::shared_ptr<ShaderModule> InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderAst::Statement& shaderAst, const ShaderWriter::States& states) override;
|
||||
std::shared_ptr<ShaderModule> InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const ShaderWriter::States& states) override;
|
||||
std::shared_ptr<Texture> InstantiateTexture(const TextureInfo& params) override;
|
||||
std::shared_ptr<TextureSampler> InstantiateTextureSampler(const TextureSamplerInfo& params) override;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <Nazara/OpenGLRenderer/OpenGLShaderBinding.hpp>
|
||||
#include <Nazara/OpenGLRenderer/Wrapper/Context.hpp>
|
||||
#include <Nazara/OpenGLRenderer/Wrapper/CoreFunctions.hpp>
|
||||
#include <Nazara/Shader/GlslWriter.hpp>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
@@ -30,13 +31,11 @@ namespace Nz
|
||||
OpenGLRenderPipelineLayout(OpenGLRenderPipelineLayout&&) = delete;
|
||||
~OpenGLRenderPipelineLayout();
|
||||
|
||||
ShaderBindingPtr AllocateShaderBinding() override;
|
||||
ShaderBindingPtr AllocateShaderBinding(UInt32 setIndex) override;
|
||||
|
||||
inline const GlslWriter::BindingMapping& GetBindingMapping() const;
|
||||
inline const RenderPipelineLayoutInfo& GetLayoutInfo() const;
|
||||
|
||||
inline std::size_t GetTextureDescriptorCount() const;
|
||||
inline std::size_t GetUniformBufferDescriptorCount() const;
|
||||
|
||||
OpenGLRenderPipelineLayout& operator=(const OpenGLRenderPipelineLayout&) = delete;
|
||||
OpenGLRenderPipelineLayout& operator=(OpenGLRenderPipelineLayout&&) = delete;
|
||||
|
||||
@@ -46,17 +45,15 @@ namespace Nz
|
||||
struct UniformBufferDescriptor;
|
||||
|
||||
DescriptorPool& AllocatePool();
|
||||
ShaderBindingPtr AllocateFromPool(std::size_t poolIndex);
|
||||
TextureDescriptor& GetTextureDescriptor(std::size_t poolIndex, std::size_t bindingIndex, std::size_t textureIndex);
|
||||
UniformBufferDescriptor& GetUniformBufferDescriptor(std::size_t poolIndex, std::size_t bindingIndex, std::size_t uniformBufferIndex);
|
||||
ShaderBindingPtr AllocateFromPool(std::size_t poolIndex, UInt32 setIndex);
|
||||
template<typename F> void ForEachDescriptor(std::size_t poolIndex, std::size_t bindingIndex, F&& functor);
|
||||
TextureDescriptor& GetTextureDescriptor(std::size_t poolIndex, std::size_t bindingIndex, std::size_t descriptorIndex);
|
||||
UniformBufferDescriptor& GetUniformBufferDescriptor(std::size_t poolIndex, std::size_t bindingIndex, std::size_t descriptorIndex);
|
||||
void Release(ShaderBinding& binding);
|
||||
inline void TryToShrink();
|
||||
|
||||
static constexpr UInt32 InvalidIndex = 0xFFFFFFFF;
|
||||
|
||||
struct TextureDescriptor
|
||||
{
|
||||
UInt32 bindingIndex = InvalidIndex;
|
||||
GLuint texture;
|
||||
GLuint sampler;
|
||||
GL::TextureTarget textureTarget;
|
||||
@@ -64,25 +61,25 @@ namespace Nz
|
||||
|
||||
struct UniformBufferDescriptor
|
||||
{
|
||||
UInt32 bindingIndex = InvalidIndex;
|
||||
GLuint buffer;
|
||||
GLintptr offset;
|
||||
GLsizeiptr size;
|
||||
};
|
||||
|
||||
using Descriptor = std::variant<std::monostate, TextureDescriptor, UniformBufferDescriptor>;
|
||||
|
||||
struct DescriptorPool
|
||||
{
|
||||
using BindingStorage = std::aligned_storage_t<sizeof(OpenGLShaderBinding), alignof(OpenGLShaderBinding)>;
|
||||
|
||||
Bitset<UInt64> freeBindings;
|
||||
std::vector<TextureDescriptor> textureDescriptor;
|
||||
std::vector<UniformBufferDescriptor> uniformBufferDescriptor;
|
||||
std::vector<Descriptor> descriptors;
|
||||
std::unique_ptr<BindingStorage[]> storage;
|
||||
};
|
||||
|
||||
std::size_t m_textureDescriptorCount;
|
||||
std::size_t m_uniformBufferDescriptorCount;
|
||||
std::size_t m_maxDescriptorCount;
|
||||
std::vector<DescriptorPool> m_descriptorPools;
|
||||
GlslWriter::BindingMapping m_bindingMapping;
|
||||
RenderPipelineLayoutInfo m_layoutInfo;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7,19 +7,32 @@
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline const GlslWriter::BindingMapping& OpenGLRenderPipelineLayout::GetBindingMapping() const
|
||||
{
|
||||
return m_bindingMapping;
|
||||
}
|
||||
|
||||
inline const RenderPipelineLayoutInfo& OpenGLRenderPipelineLayout::GetLayoutInfo() const
|
||||
{
|
||||
return m_layoutInfo;
|
||||
}
|
||||
|
||||
inline std::size_t OpenGLRenderPipelineLayout::GetTextureDescriptorCount() const
|
||||
template<typename F>
|
||||
void OpenGLRenderPipelineLayout::ForEachDescriptor(std::size_t poolIndex, std::size_t bindingIndex, F&& functor)
|
||||
{
|
||||
return m_textureDescriptorCount;
|
||||
}
|
||||
assert(poolIndex < m_descriptorPools.size());
|
||||
auto& pool = m_descriptorPools[poolIndex];
|
||||
assert(!pool.freeBindings.Test(bindingIndex));
|
||||
|
||||
inline std::size_t OpenGLRenderPipelineLayout::GetUniformBufferDescriptorCount() const
|
||||
{
|
||||
return m_uniformBufferDescriptorCount;
|
||||
for (std::size_t descriptorIndex = 0; descriptorIndex < m_maxDescriptorCount; ++descriptorIndex)
|
||||
{
|
||||
std::visit([&](auto&& arg)
|
||||
{
|
||||
if constexpr (!std::is_same_v<std::decay_t<decltype(arg)>, std::monostate>)
|
||||
functor(UInt32(descriptorIndex), arg);
|
||||
},
|
||||
pool.descriptors[bindingIndex * m_maxDescriptorCount + descriptorIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
inline void OpenGLRenderPipelineLayout::TryToShrink()
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Nz
|
||||
OpenGLShaderBinding(OpenGLShaderBinding&&) = delete;
|
||||
~OpenGLShaderBinding() = default;
|
||||
|
||||
void Apply(const GL::Context& context) const;
|
||||
void Apply(const OpenGLRenderPipelineLayout& pipelineLayout, UInt32 setIndex, const GL::Context& context) const;
|
||||
|
||||
inline std::size_t GetBindingIndex() const;
|
||||
inline std::size_t GetPoolIndex() const;
|
||||
|
||||
@@ -11,8 +11,10 @@
|
||||
#include <Nazara/Renderer/Enums.hpp>
|
||||
#include <Nazara/Renderer/ShaderModule.hpp>
|
||||
#include <Nazara/OpenGLRenderer/Wrapper/Context.hpp>
|
||||
#include <Nazara/OpenGLRenderer/Wrapper/Program.hpp>
|
||||
#include <Nazara/OpenGLRenderer/Wrapper/Shader.hpp>
|
||||
#include <Nazara/Shader/ShaderWriter.hpp>
|
||||
#include <Nazara/Shader/GlslWriter.hpp>
|
||||
#include <Nazara/Shader/Ast/Nodes.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace Nz
|
||||
@@ -20,30 +22,40 @@ namespace Nz
|
||||
class NAZARA_OPENGLRENDERER_API OpenGLShaderModule : public ShaderModule
|
||||
{
|
||||
public:
|
||||
struct Shader;
|
||||
|
||||
OpenGLShaderModule(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states = {});
|
||||
OpenGLShaderModule(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderAst::Statement& 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(OpenGLShaderModule&&) noexcept = default;
|
||||
~OpenGLShaderModule() = default;
|
||||
|
||||
inline const std::vector<Shader>& GetShaders() const;
|
||||
ShaderStageTypeFlags Attach(GL::Program& program, const GlslWriter::BindingMapping& bindingMapping) const;
|
||||
|
||||
OpenGLShaderModule& operator=(const OpenGLShaderModule&) = delete;
|
||||
OpenGLShaderModule& operator=(OpenGLShaderModule&&) noexcept = default;
|
||||
|
||||
struct Shader
|
||||
{
|
||||
ShaderStageType stage;
|
||||
GL::Shader shader;
|
||||
};
|
||||
|
||||
private:
|
||||
void Create(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states);
|
||||
void Create(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderAst::Statement& shaderAst, const ShaderWriter::States& states);
|
||||
|
||||
static void CheckCompilationStatus(GL::Shader& shader);
|
||||
|
||||
struct GlslShader
|
||||
{
|
||||
std::string sourceCode;
|
||||
};
|
||||
|
||||
struct ShaderStatement
|
||||
{
|
||||
std::shared_ptr<ShaderAst::Statement> ast;
|
||||
};
|
||||
|
||||
struct Shader
|
||||
{
|
||||
ShaderStageType stage;
|
||||
std::variant<GlslShader, ShaderStatement> shader;
|
||||
};
|
||||
|
||||
OpenGLDevice& m_device;
|
||||
ShaderWriter::States m_states;
|
||||
std::vector<Shader> m_shaders;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7,10 +7,6 @@
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline auto OpenGLShaderModule::GetShaders() const -> const std::vector<Shader>&
|
||||
{
|
||||
return m_shaders;
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/OpenGLRenderer/DebugOff.hpp>
|
||||
|
||||
Reference in New Issue
Block a user