NazaraEngine/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp

291 lines
9.5 KiB
C++

// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - OpenGL renderer"
// For conditions of distribution and use, see copyright notice in Export.hpp
#pragma once
#ifndef NAZARA_OPENGLRENDERER_OPENGLCOMMANDBUFFER_HPP
#define NAZARA_OPENGLRENDERER_OPENGLCOMMANDBUFFER_HPP
#include <NazaraUtils/Prerequisites.hpp>
#include <Nazara/Core/Color.hpp>
#include <Nazara/Math/Rect.hpp>
#include <Nazara/OpenGLRenderer/Export.hpp>
#include <Nazara/OpenGLRenderer/OpenGLBuffer.hpp>
#include <Nazara/OpenGLRenderer/OpenGLRenderPipeline.hpp>
#include <Nazara/OpenGLRenderer/OpenGLShaderBinding.hpp>
#include <Nazara/Renderer/CommandBuffer.hpp>
#include <Nazara/Renderer/CommandBufferBuilder.hpp>
#include <NazaraUtils/TypeList.hpp>
#include <optional>
#include <variant>
#include <vector>
namespace Nz
{
class OpenGLCommandPool;
class OpenGLComputePipeline;
class OpenGLFramebuffer;
class OpenGLRenderPass;
class OpenGLTexture;
class NAZARA_OPENGLRENDERER_API OpenGLCommandBuffer final : public CommandBuffer
{
public:
inline OpenGLCommandBuffer();
inline OpenGLCommandBuffer(OpenGLCommandPool& owner, std::size_t poolIndex, std::size_t bindingIndex);
OpenGLCommandBuffer(const OpenGLCommandBuffer&) = delete;
OpenGLCommandBuffer(OpenGLCommandBuffer&&) = delete;
~OpenGLCommandBuffer() = default;
inline void BeginDebugRegion(std::string_view regionName, const Color& color);
inline void BindComputePipeline(const OpenGLComputePipeline* pipeline);
inline void BindComputeShaderBinding(const OpenGLRenderPipelineLayout& pipelineLayout, UInt32 set, const OpenGLShaderBinding* binding);
inline void BindIndexBuffer(GLuint indexBuffer, IndexType indexType, UInt64 offset = 0);
inline void BindRenderPipeline(const OpenGLRenderPipeline* pipeline);
inline void BindRenderShaderBinding(const OpenGLRenderPipelineLayout& pipelineLayout, UInt32 set, const OpenGLShaderBinding* binding);
inline void BindVertexBuffer(UInt32 binding, GLuint vertexBuffer, UInt64 offset = 0);
inline void BlitTexture(const OpenGLTexture& source, const Boxui& sourceBox, const OpenGLTexture& target, const Boxui& targetBox, SamplerFilter filter = SamplerFilter::Nearest);
inline void BlitTextureToWindow(const OpenGLTexture& source, const Boxui& sourceBox, const Boxui& targetBox, SamplerFilter filter = SamplerFilter::Nearest);
inline void BuildMipmaps(OpenGLTexture& texture, UInt8 baseLevel, UInt8 levelCount);
inline void CopyBuffer(GLuint source, GLuint target, UInt64 size, UInt64 sourceOffset = 0, UInt64 targetOffset = 0);
inline void CopyBuffer(const UploadPool::Allocation& allocation, GLuint target, UInt64 size, UInt64 sourceOffset = 0, UInt64 targetOffset = 0);
inline void CopyTexture(const OpenGLTexture& source, const Boxui& sourceBox, const OpenGLTexture& target, const Vector3ui& targetPoint);
inline void Dispatch(UInt32 numGroupsX, UInt32 numGroupsY, UInt32 numGroupsZ);
inline void Draw(UInt32 vertexCount, UInt32 instanceCount = 1, UInt32 firstVertex = 0, UInt32 firstInstance = 0);
inline void DrawIndexed(UInt32 indexCount, UInt32 instanceCount = 1, UInt32 firstIndex = 0, UInt32 firstInstance = 0);
inline void EndDebugRegion();
void Execute();
inline void InsertDebugLabel(std::string_view label, const Color& color);
inline std::size_t GetBindingIndex() const;
inline std::size_t GetPoolIndex() const;
inline const OpenGLCommandPool& GetOwner() const;
inline void InsertMemoryBarrier(GLbitfield barriers);
inline void SetFramebuffer(const OpenGLFramebuffer& framebuffer, const OpenGLRenderPass& renderPass, const CommandBufferBuilder::ClearValues* clearValues, std::size_t clearValueCount);
inline void SetScissor(const Recti& scissorRegion);
inline void SetViewport(const Recti& viewportRegion);
void UpdateDebugName(std::string_view name) override;
OpenGLCommandBuffer& operator=(const OpenGLCommandBuffer&) = delete;
OpenGLCommandBuffer& operator=(OpenGLCommandBuffer&&) = delete;
private:
struct DrawStates;
struct ShaderBindings;
#define NAZARA_OPENGL_FOREACH_COMMANDS(cb, lastCb) \
cb(BeginDebugRegionCommand) \
cb(BlitTextureCommand) \
cb(BlitTextureToWindowCommand) \
cb(BuildTextureMipmapsCommand) \
cb(CopyBufferCommand) \
cb(CopyBufferFromMemoryCommand) \
cb(CopyTextureCommand) \
cb(DispatchCommand) \
cb(DrawCommand) \
cb(DrawIndexedCommand) \
cb(EndDebugRegionCommand) \
cb(InsertDebugLabelCommand) \
cb(MemoryBarrier) \
lastCb(SetFrameBufferCommand) \
#define NAZARA_OPENGL_COMMAND_CALLBACK(Command) struct Command;
NAZARA_OPENGL_FOREACH_COMMANDS(NAZARA_OPENGL_COMMAND_CALLBACK, NAZARA_OPENGL_COMMAND_CALLBACK)
#undef NAZARA_OPENGL_COMMAND_CALLBACK
using CommandList = TypeList<
#define NAZARA_OPENGL_COMMAND_CALLBACK(Command) Command,
#define NAZARA_OPENGL_COMMAND_CALLBACK_LAST(Command) Command
NAZARA_OPENGL_FOREACH_COMMANDS(NAZARA_OPENGL_COMMAND_CALLBACK, NAZARA_OPENGL_COMMAND_CALLBACK_LAST)
#undef NAZARA_OPENGL_COMMAND_CALLBACK_LAST
#undef NAZARA_OPENGL_COMMAND_CALLBACK
>;
void ApplyBindings(const GL::Context& context, const ShaderBindings& bindings);
void ApplyStates(const GL::Context& context, const DrawStates& states);
inline void Execute(const GL::Context* context, const BeginDebugRegionCommand& command);
inline void Execute(const GL::Context* context, const BlitTextureCommand& command);
inline void Execute(const GL::Context* context, const BlitTextureToWindowCommand& command);
inline void Execute(const GL::Context* context, const BuildTextureMipmapsCommand& command);
inline void Execute(const GL::Context* context, const CopyBufferCommand& command);
inline void Execute(const GL::Context* context, const CopyBufferFromMemoryCommand& command);
inline void Execute(const GL::Context* context, const CopyTextureCommand& command);
inline void Execute(const GL::Context* context, const DispatchCommand& command);
inline void Execute(const GL::Context* context, const DrawCommand& command);
inline void Execute(const GL::Context* context, const DrawIndexedCommand& command);
inline void Execute(const GL::Context* context, const EndDebugRegionCommand& command);
inline void Execute(const GL::Context* context, const InsertDebugLabelCommand& command);
inline void Execute(const GL::Context* context, const MemoryBarrier& command);
inline void Execute(const GL::Context*& context, const SetFrameBufferCommand& command);
void Release() override;
struct BeginDebugRegionCommand
{
std::string regionName;
Color color;
};
struct BlitTextureCommand
{
const OpenGLTexture* source;
const OpenGLTexture* target;
Boxui sourceBox;
Boxui targetBox;
SamplerFilter filter;
};
struct BlitTextureToWindowCommand
{
const OpenGLTexture* source;
Boxui sourceBox;
Boxui targetBox;
SamplerFilter filter;
};
struct BuildTextureMipmapsCommand
{
OpenGLTexture* texture;
UInt8 baseLevel;
UInt8 levelCount;
};
struct ComputeStates
{
const OpenGLComputePipeline* pipeline = nullptr;
};
struct CopyBufferCommand
{
GLuint source;
GLuint target;
UInt64 size;
UInt64 sourceOffset;
UInt64 targetOffset;
};
struct CopyTextureCommand
{
const OpenGLTexture* source;
const OpenGLTexture* target;
Boxui sourceBox;
Vector3ui targetPoint;
};
struct CopyBufferFromMemoryCommand
{
const void* memory;
GLuint target;
UInt64 size;
UInt64 targetOffset;
};
struct ShaderBindings
{
std::vector<std::pair<const OpenGLRenderPipelineLayout*, const OpenGLShaderBinding*>> shaderBindings;
};
struct DispatchCommand
{
ComputeStates states;
ShaderBindings bindings;
UInt32 numGroupsX;
UInt32 numGroupsY;
UInt32 numGroupsZ;
};
struct DrawStates
{
struct VertexBuffer
{
GLuint vertexBuffer = 0;
UInt64 offset;
};
GLuint indexBuffer = 0;
const OpenGLRenderPipeline* pipeline = nullptr;
UInt64 indexBufferOffset;
IndexType indexBufferType;
std::optional<Recti> scissorRegion;
std::optional<Recti> viewportRegion;
std::vector<VertexBuffer> vertexBuffers;
bool shouldFlipY = false;
};
struct DrawCommand
{
DrawStates states;
ShaderBindings bindings;
UInt32 firstInstance;
UInt32 firstVertex;
UInt32 instanceCount;
UInt32 vertexCount;
};
struct DrawIndexedCommand
{
DrawStates states;
ShaderBindings bindings;
UInt32 firstIndex;
UInt32 firstInstance;
UInt32 indexCount;
UInt32 instanceCount;
};
struct EndDebugRegionCommand
{
};
struct InsertDebugLabelCommand
{
std::string label;
Color color;
};
struct MemoryBarrier
{
GLbitfield barriers;
};
struct SetFrameBufferCommand
{
std::array<CommandBufferBuilder::ClearValues, 16> clearValues; //< TODO: Remove hard limit?
const OpenGLFramebuffer* framebuffer;
const OpenGLRenderPass* renderpass;
};
using CommandData = TypeListInstantiate<CommandList, std::variant>;
ComputeStates m_currentComputeStates;
DrawStates m_currentDrawStates;
ShaderBindings m_currentComputeShaderBindings;
ShaderBindings m_currentGraphicsShaderBindings;
std::optional<MemoryBarrier> m_pendingBarrier;
std::size_t m_bindingIndex;
std::size_t m_maxColorBufferCount;
std::size_t m_poolIndex;
std::vector<CommandData> m_commands;
OpenGLCommandPool* m_owner;
};
}
#include <Nazara/OpenGLRenderer/OpenGLCommandBuffer.inl>
#endif // NAZARA_OPENGLRENDERER_OPENGLCOMMANDBUFFER_HPP