Renderer: Working compute implementation

This commit is contained in:
SirLynix
2022-12-25 16:08:35 +01:00
committed by Jérôme Leclercq
parent 4605eed0da
commit fe8715f1fb
31 changed files with 615 additions and 167 deletions

View File

@@ -40,9 +40,10 @@ namespace Nz
inline void BeginDebugRegion(const 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 BindShaderBinding(const OpenGLRenderPipelineLayout& pipelineLayout, UInt32 set, const OpenGLShaderBinding* binding);
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);
@@ -63,6 +64,8 @@ namespace Nz
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);
@@ -74,7 +77,9 @@ namespace Nz
private:
struct DrawStates;
struct ShaderBindings;
void ApplyBindings(const GL::Context& context, const ShaderBindings& bindings);
void ApplyStates(const GL::Context& context, const DrawStates& states);
void Release() override;
@@ -123,9 +128,15 @@ namespace Nz
UInt64 targetOffset;
};
struct ShaderBindings
{
std::vector<std::pair<const OpenGLRenderPipelineLayout*, const OpenGLShaderBinding*>> shaderBindings;
};
struct DispatchData
{
ComputeStates states;
ShaderBindings bindings;
UInt32 numGroupsX;
UInt32 numGroupsY;
UInt32 numGroupsZ;
@@ -145,7 +156,6 @@ namespace Nz
IndexType indexBufferType;
std::optional<Recti> scissorRegion;
std::optional<Recti> viewportRegion;
std::vector<std::pair<const OpenGLRenderPipelineLayout*, const OpenGLShaderBinding*>> shaderBindings;
std::vector<VertexBuffer> vertexBuffers;
bool shouldFlipY = false;
};
@@ -153,6 +163,7 @@ namespace Nz
struct DrawData
{
DrawStates states;
ShaderBindings bindings;
UInt32 firstInstance;
UInt32 firstVertex;
UInt32 instanceCount;
@@ -162,6 +173,7 @@ namespace Nz
struct DrawIndexedData
{
DrawStates states;
ShaderBindings bindings;
UInt32 firstIndex;
UInt32 firstInstance;
UInt32 indexCount;
@@ -172,6 +184,11 @@ namespace Nz
{
};
struct MemoryBarrier
{
GLbitfield barriers;
};
struct SetFrameBufferData
{
std::array<CommandBufferBuilder::ClearValues, 16> clearValues; //< TODO: Remove hard limit?
@@ -189,11 +206,15 @@ namespace Nz
DrawData,
DrawIndexedData,
EndDebugRegionData,
MemoryBarrier,
SetFrameBufferData
>;
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;

View File

@@ -38,6 +38,14 @@ namespace Nz
m_currentComputeStates.pipeline = pipeline;
}
inline void OpenGLCommandBuffer::BindComputeShaderBinding(const OpenGLRenderPipelineLayout& pipelineLayout, UInt32 set, const OpenGLShaderBinding* binding)
{
if (set >= m_currentComputeShaderBindings.shaderBindings.size())
m_currentComputeShaderBindings.shaderBindings.resize(set + 1);
m_currentComputeShaderBindings.shaderBindings[set] = std::make_pair(&pipelineLayout, binding);
}
inline void OpenGLCommandBuffer::BindIndexBuffer(GLuint indexBuffer, IndexType indexType, UInt64 offset)
{
m_currentDrawStates.indexBuffer = indexBuffer;
@@ -50,12 +58,12 @@ namespace Nz
m_currentDrawStates.pipeline = pipeline;
}
inline void OpenGLCommandBuffer::BindShaderBinding(const OpenGLRenderPipelineLayout& pipelineLayout, UInt32 set, const OpenGLShaderBinding* binding)
inline void OpenGLCommandBuffer::BindRenderShaderBinding(const OpenGLRenderPipelineLayout& pipelineLayout, UInt32 set, const OpenGLShaderBinding* binding)
{
if (set >= m_currentDrawStates.shaderBindings.size())
m_currentDrawStates.shaderBindings.resize(set + 1);
if (set >= m_currentGraphicsShaderBindings.shaderBindings.size())
m_currentGraphicsShaderBindings.shaderBindings.resize(set + 1);
m_currentDrawStates.shaderBindings[set] = std::make_pair(&pipelineLayout, binding);
m_currentGraphicsShaderBindings.shaderBindings[set] = std::make_pair(&pipelineLayout, binding);
}
inline void OpenGLCommandBuffer::BindVertexBuffer(UInt32 binding, GLuint vertexBuffer, UInt64 offset)
@@ -124,6 +132,7 @@ namespace Nz
throw std::runtime_error("no pipeline bound");
DispatchData dispatch;
dispatch.bindings = m_currentComputeShaderBindings;
dispatch.states = m_currentComputeStates;
dispatch.numGroupsX = numGroupsX;
dispatch.numGroupsY = numGroupsY;
@@ -138,6 +147,7 @@ namespace Nz
throw std::runtime_error("no pipeline bound");
DrawData draw;
draw.bindings = m_currentGraphicsShaderBindings;
draw.states = m_currentDrawStates;
draw.firstInstance = firstInstance;
draw.firstVertex = firstVertex;
@@ -153,6 +163,7 @@ namespace Nz
throw std::runtime_error("no pipeline bound");
DrawIndexedData draw;
draw.bindings = m_currentGraphicsShaderBindings;
draw.states = m_currentDrawStates;
draw.firstIndex = firstIndex;
draw.firstInstance = firstInstance;
@@ -183,6 +194,23 @@ namespace Nz
return *m_owner;
}
inline void OpenGLCommandBuffer::InsertMemoryBarrier(GLbitfield barriers)
{
// Merge with previous barrier, if any (may happen because memory barriers are not relative to a texture with OpenGL)
if (!m_commands.empty() && std::holds_alternative<MemoryBarrier>(m_commands.back()))
{
MemoryBarrier& memBarrier = std::get<MemoryBarrier>(m_commands.back());
memBarrier.barriers |= barriers;
}
else
{
MemoryBarrier memBarrier;
memBarrier.barriers = barriers;
m_commands.emplace_back(std::move(memBarrier));
}
}
inline void OpenGLCommandBuffer::SetFramebuffer(const OpenGLFramebuffer& framebuffer, const OpenGLRenderPass& renderPass, const CommandBufferBuilder::ClearValues* clearValues, std::size_t clearValueCount)
{
m_maxColorBufferCount = std::max(m_maxColorBufferCount, framebuffer.GetColorBufferCount());

View File

@@ -28,10 +28,12 @@ namespace Nz
void BeginRenderPass(const Framebuffer& framebuffer, const RenderPass& renderPass, const Recti& renderRect, const ClearValues* clearValues, std::size_t clearValueCount) override;
void BindComputePipeline(const ComputePipeline& pipeline) override;
void BindComputeShaderBinding(UInt32 set, const ShaderBinding& binding) override;
void BindComputeShaderBinding(const RenderPipelineLayout& pipelineLayout, UInt32 set, const ShaderBinding& binding) override;
void BindIndexBuffer(const RenderBuffer& indexBuffer, IndexType indexType, UInt64 offset = 0) override;
void BindRenderPipeline(const RenderPipeline& pipeline) override;
void BindShaderBinding(UInt32 set, const ShaderBinding& binding) override;
void BindShaderBinding(const RenderPipelineLayout& pipelineLayout, UInt32 set, const ShaderBinding& binding) override;
void BindRenderShaderBinding(UInt32 set, const ShaderBinding& binding) override;
void BindRenderShaderBinding(const RenderPipelineLayout& pipelineLayout, UInt32 set, const ShaderBinding& binding) override;
void BindVertexBuffer(UInt32 binding, const RenderBuffer& vertexBuffer, UInt64 offset = 0) override;
void BlitTexture(const Texture& fromTexture, const Boxui& fromBox, TextureLayout fromLayout, const Texture& toTexture, const Boxui& toBox, TextureLayout toLayout, SamplerFilter filter) override;

View File

@@ -16,7 +16,7 @@
namespace Nz
{
class NAZARA_OPENGLRENDERER_API OpenGLTexture : public Texture
class NAZARA_OPENGLRENDERER_API OpenGLTexture final : public Texture
{
public:
OpenGLTexture(OpenGLDevice& device, const TextureInfo& textureInfo);
@@ -28,13 +28,14 @@ namespace Nz
bool Copy(const Texture& source, const Boxui& srcBox, const Vector3ui& dstPos) override;
std::shared_ptr<Texture> CreateView(const TextureViewInfo& viewInfo) override;
PixelFormat GetFormat() const override;
UInt8 GetLevelCount() const override;
OpenGLTexture* GetParentTexture() const override;
Vector3ui GetSize(UInt8 level = 0) const override;
inline PixelFormat GetFormat() const override;
inline UInt8 GetLevelCount() const override;
inline OpenGLTexture* GetParentTexture() const override;
inline Vector3ui GetSize(UInt8 level = 0) const override;
inline const GL::Texture& GetTexture() const;
inline const TextureInfo& GetTextureInfo() const override;
inline const TextureViewInfo& GetTextureViewInfo() const;
ImageType GetType() const override;
inline ImageType GetType() const override;
inline bool RequiresTextureViewEmulation() const;

View File

@@ -8,17 +8,47 @@
namespace Nz
{
inline PixelFormat OpenGLTexture::GetFormat() const
{
return m_textureInfo.pixelFormat;
}
inline UInt8 OpenGLTexture::GetLevelCount() const
{
return m_textureInfo.levelCount;
}
inline OpenGLTexture* OpenGLTexture::GetParentTexture() const
{
return m_parentTexture.get();
}
inline Vector3ui OpenGLTexture::GetSize(UInt8 level) const
{
return Vector3ui(GetLevelSize(m_textureInfo.width, level), GetLevelSize(m_textureInfo.height, level), GetLevelSize(m_textureInfo.depth, level));
}
inline const GL::Texture& OpenGLTexture::GetTexture() const
{
return m_texture;
}
inline const TextureInfo& OpenGLTexture::GetTextureInfo() const
{
return m_textureInfo;
}
inline const TextureViewInfo& OpenGLTexture::GetTextureViewInfo() const
{
assert(m_viewInfo);
return *m_viewInfo;
}
inline ImageType OpenGLTexture::GetType() const
{
return m_textureInfo.type;
}
inline bool OpenGLTexture::RequiresTextureViewEmulation() const
{
return m_viewInfo.has_value() && !m_texture.IsValid();

View File

@@ -44,10 +44,12 @@ namespace Nz
inline void BeginRenderPass(const Framebuffer& framebuffer, const RenderPass& renderPass, const Recti& renderRect, std::initializer_list<ClearValues> clearValues);
virtual void BindComputePipeline(const ComputePipeline& pipeline) = 0;
virtual void BindComputeShaderBinding(UInt32 set, const ShaderBinding& binding) = 0;
virtual void BindComputeShaderBinding(const RenderPipelineLayout& pipelineLayout, UInt32 set, const ShaderBinding& binding) = 0;
virtual void BindIndexBuffer(const RenderBuffer& indexBuffer, IndexType indexType, UInt64 offset = 0) = 0;
virtual void BindRenderPipeline(const RenderPipeline& pipeline) = 0;
virtual void BindShaderBinding(UInt32 set, const ShaderBinding& binding) = 0;
virtual void BindShaderBinding(const RenderPipelineLayout& pipelineLayout, UInt32 set, const ShaderBinding& binding) = 0;
virtual void BindRenderShaderBinding(UInt32 set, const ShaderBinding& binding) = 0;
virtual void BindRenderShaderBinding(const RenderPipelineLayout& pipelineLayout, UInt32 set, const ShaderBinding& binding) = 0;
virtual void BindVertexBuffer(UInt32 binding, const RenderBuffer& vertexBuffer, UInt64 offset = 0) = 0;
virtual void BlitTexture(const Texture& fromTexture, const Boxui& fromBox, TextureLayout fromLayout, const Texture& toTexture, const Boxui& toBox, TextureLayout toLayout, SamplerFilter filter) = 0;

View File

@@ -83,6 +83,7 @@ namespace Nz
TopOfPipe,
ColorOutput,
ComputeShader,
DrawIndirect,
FragmentShader,
FragmentTestsEarly,
@@ -196,6 +197,7 @@ namespace Nz
ColorOutput,
DepthStencilReadOnly,
DepthStencilReadWrite,
General,
Present,
TransferSource,
TransferDestination,

View File

@@ -21,9 +21,8 @@ namespace Nz
bool depthClamping = false;
bool nonSolidFaceFilling = false;
bool storageBuffers = false;
bool textureRead = false;
bool textureReadWithoutFormat = false;
bool textureWrite = false;
bool textureReadWrite = false;
bool textureWriteWithoutFormat = false;
bool unrestrictedTextureViews = false;
};

View File

@@ -68,11 +68,8 @@ namespace Nz
virtual bool Copy(const Texture& source, const Boxui& srcBox, const Vector3ui& dstPos = Vector3ui::Zero()) = 0;
virtual std::shared_ptr<Texture> CreateView(const TextureViewInfo& viewInfo) = 0;
virtual PixelFormat GetFormat() const = 0;
virtual UInt8 GetLevelCount() const = 0;
virtual Texture* GetParentTexture() const = 0;
virtual Vector3ui GetSize(UInt8 level = 0) const = 0;
virtual ImageType GetType() const = 0;
virtual const TextureInfo& GetTextureInfo() const = 0;
virtual void UpdateDebugName(std::string_view name) = 0;

View File

@@ -227,6 +227,7 @@ namespace Nz
{
case PipelineStage::TopOfPipe: return VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
case PipelineStage::ColorOutput: return VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
case PipelineStage::ComputeShader: return VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
case PipelineStage::DrawIndirect: return VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
case PipelineStage::FragmentShader: return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
case PipelineStage::FragmentTestsEarly: return VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
@@ -444,6 +445,7 @@ namespace Nz
case TextureLayout::ColorOutput: return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
case TextureLayout::DepthStencilReadOnly: return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
case TextureLayout::DepthStencilReadWrite: return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
case TextureLayout::General: return VK_IMAGE_LAYOUT_GENERAL;
case TextureLayout::Present: return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
case TextureLayout::TransferSource: return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
case TextureLayout::TransferDestination: return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;

View File

@@ -28,10 +28,12 @@ namespace Nz
void BeginRenderPass(const Framebuffer& framebuffer, const RenderPass& renderPass, const Recti& renderRect, const ClearValues* clearValues, std::size_t clearValueCount) override;
void BindComputePipeline(const ComputePipeline& pipeline) override;
void BindComputeShaderBinding(UInt32 set, const ShaderBinding& binding) override;
void BindComputeShaderBinding(const RenderPipelineLayout& pipelineLayout, UInt32 set, const ShaderBinding& binding) override;
void BindIndexBuffer(const RenderBuffer& indexBuffer, IndexType indexType, UInt64 offset = 0) override;
void BindRenderPipeline(const RenderPipeline& pipeline) override;
void BindShaderBinding(UInt32 set, const ShaderBinding& binding) override;
void BindShaderBinding(const RenderPipelineLayout& pipelineLayout, UInt32 set, const ShaderBinding& binding) override;
void BindRenderShaderBinding(UInt32 set, const ShaderBinding& binding) override;
void BindRenderShaderBinding(const RenderPipelineLayout& pipelineLayout, UInt32 set, const ShaderBinding& binding) override;
void BindVertexBuffer(UInt32 binding, const RenderBuffer& vertexBuffer, UInt64 offset = 0) override;
void BlitTexture(const Texture& fromTexture, const Boxui& fromBox, TextureLayout fromLayout, const Texture& toTexture, const Boxui& toBox, TextureLayout toLayout, SamplerFilter filter) override;

View File

@@ -16,7 +16,7 @@
namespace Nz
{
class NAZARA_VULKANRENDERER_API VulkanTexture : public Texture
class NAZARA_VULKANRENDERER_API VulkanTexture final : public Texture
{
public:
VulkanTexture(Vk::Device& device, const TextureInfo& textureInfo);
@@ -28,14 +28,15 @@ namespace Nz
bool Copy(const Texture& source, const Boxui& srcBox, const Vector3ui& dstPos) override;
std::shared_ptr<Texture> CreateView(const TextureViewInfo& viewInfo) override;
PixelFormat GetFormat() const override;
inline PixelFormat GetFormat() const override;
inline VkImage GetImage() const;
inline VkImageView GetImageView() const;
UInt8 GetLevelCount() const override;
VulkanTexture* GetParentTexture() const override;
Vector3ui GetSize(UInt8 level = 0) const override;
inline UInt8 GetLevelCount() const override;
inline VulkanTexture* GetParentTexture() const override;
inline Vector3ui GetSize(UInt8 level = 0) const override;
inline const VkImageSubresourceRange& GetSubresourceRange() const;
ImageType GetType() const override;
inline const TextureInfo& GetTextureInfo() const override;
inline ImageType GetType() const override;
using Texture::Update;
bool Update(const void* ptr, const Boxui& box, unsigned int srcWidth, unsigned int srcHeight, UInt8 level) override;

View File

@@ -7,6 +7,11 @@
namespace Nz
{
inline PixelFormat VulkanTexture::GetFormat() const
{
return m_textureInfo.pixelFormat;
}
inline VkImage VulkanTexture::GetImage() const
{
return m_image;
@@ -17,10 +22,35 @@ namespace Nz
return m_imageView;
}
inline UInt8 VulkanTexture::GetLevelCount() const
{
return m_textureInfo.levelCount;
}
inline VulkanTexture* VulkanTexture::GetParentTexture() const
{
return m_parentTexture.get();
}
inline Vector3ui VulkanTexture::GetSize(UInt8 level) const
{
return Vector3ui(GetLevelSize(m_textureInfo.width, level), GetLevelSize(m_textureInfo.height, level), GetLevelSize(m_textureInfo.depth, level));
}
inline const VkImageSubresourceRange& VulkanTexture::GetSubresourceRange() const
{
return m_imageRange;
}
inline const TextureInfo& VulkanTexture::GetTextureInfo() const
{
return m_textureInfo;
}
inline ImageType VulkanTexture::GetType() const
{
return m_textureInfo.type;
}
}
#include <Nazara/VulkanRenderer/DebugOff.hpp>