Sparkle 0.0.1
Loading...
Searching...
No Matches
spk_shader_storage_buffer_object.hpp
1#pragma once
2
3#include "structure/container/spk_buffer_layout.hpp"
4#include "structure/opengl/spk_buffer_object.hpp"
5#include "structure/opengl/spk_opengl_includes.hpp"
6#include "utils/spk_opengl_utils.hpp"
7#include <cstddef>
8#include <cstring>
9#include <optional>
10#include <stdexcept>
11#include <string>
12#include <type_traits>
13#include <vector>
14
15namespace spk
16{
17 namespace OpenGL
18 {
25 {
26 private:
27 GLuint _bindingPoint = 0;
28 std::size_t _fixedSectionSize = 0;
29 std::size_t _paddingBetweenFixedAndDynamicPart = 0;
30 BufferLayout _layout;
31 std::wstring _dynamicArrayName;
32 std::optional<BufferLayout::Element> _dynamicArrayPrototype;
33 bool _dynamicArrayPresent = false;
34
35 BufferLayout _initializeLayout(size_t p_size);
36 void _registerCallbacks();
37
38 public:
46
53 ShaderStorageBufferObject(GLuint p_bindingPoint, BufferObject::Usage p_usage, const size_t &p_size);
65
75 const BufferLayout &layout() const;
76
82 void setDynamicElement(const std::wstring &p_name, const BufferLayout::Element &p_elementPrototype);
87 void setDynamicPadding(std::size_t p_padding);
92 void resizeDynamicArray(std::size_t p_newCount);
93
94 template <typename TType>
100 TType pullFixed() const
101 {
102 static_assert(std::is_trivially_copyable_v<TType>, "ShaderStorageBufferObject::pullFixed requires a trivially copyable type");
103
104 if (sizeof(TType) > _fixedSectionSize)
105 {
106 throw std::runtime_error("ShaderStorageBufferObject::pullFixed: requested type is larger than the fixed section");
107 }
108
109 const auto rawData = spk::OpenGLUtils::readBuffer(static_cast<GLenum>(_type), static_cast<GLuint>(_id));
110 if (rawData.size() < _fixedSectionSize)
111 {
112 throw std::runtime_error("ShaderStorageBufferObject::pullFixed: GPU buffer is smaller than the fixed section");
113 }
114
115 TType value{};
116 std::memcpy(&value, rawData.data(), sizeof(TType));
117 return value;
118 }
119
120 template <typename TElement>
126 std::vector<TElement> pullDynamic() const
127 {
128 static_assert(std::is_trivially_copyable_v<TElement>, "ShaderStorageBufferObject::pullDynamic requires a trivially copyable type");
129
130 if (_dynamicArrayPrototype.has_value() == false)
131 {
132 throw std::runtime_error("ShaderStorageBufferObject::pullDynamic: dynamic array is not configured");
133 }
134
135 const auto rawData = spk::OpenGLUtils::readBuffer(static_cast<GLenum>(_type), static_cast<GLuint>(_id));
136 const std::size_t offset = _fixedSectionSize + _paddingBetweenFixedAndDynamicPart;
137
138 if (rawData.size() < offset)
139 {
140 throw std::runtime_error("ShaderStorageBufferObject::pullDynamic: GPU buffer is smaller than the dynamic section offset");
141 }
142
143 const std::size_t dynamicByteSize = rawData.size() - offset;
144 if (dynamicByteSize == 0)
145 {
146 return {};
147 }
148
149 if (dynamicByteSize % sizeof(TElement) != 0)
150 {
151 throw std::runtime_error("ShaderStorageBufferObject::pullDynamic: dynamic section is not a multiple of the element size");
152 }
153
154 std::vector<TElement> values(dynamicByteSize / sizeof(TElement));
155 std::memcpy(values.data(), rawData.data() + offset, dynamicByteSize);
156 return values;
157 }
158 };
159
160 using SSBO = ShaderStorageBufferObject;
161 }
162}
void deactivate()
Sets the state to Deactivated.
Definition spk_activable_object.hpp:61
void activate()
Sets the state to Activated.
Definition spk_activable_object.hpp:54
bool isActive() const
Checks whether the object is currently activated.
Definition spk_activable_object.hpp:77
Node within a BufferLayout representing an object, array or leaf segment.
Definition spk_buffer_layout.hpp:65
Describes and writes typed data into a raw buffer with object/array hierarchy.
Definition spk_buffer_layout.hpp:26
spk::CachedData< GLuint > _id
Lazily created GPU buffer identifier.
Definition spk_buffer_object.hpp:91
Buffer::value_type * data()
Mutable pointer to underlying bytes.
Definition spk_buffer_object.cpp:183
Usage
Usage hints forwarded to the OpenGL driver.
Definition spk_buffer_object.hpp:61
BufferObject(const Type &p_type, const Usage &p_usage)
Constructs a buffer with target type and usage hint.
Definition spk_buffer_object.cpp:45
size_t size() const
Returns the current CPU buffer size.
Definition spk_buffer_object.cpp:168
Type _type
Buffer target selected at construction.
Definition spk_buffer_object.hpp:83
void _registerCallbacks()
Registers GPU lifecycle callbacks with the cached buffer id.
Definition spk_buffer_object.cpp:33
void resizeDynamicArray(std::size_t p_newCount)
Resizes the dynamic array section.
Definition spk_shader_storage_buffer_object.cpp:121
ShaderStorageBufferObject(GLuint p_bindingPoint, BufferObject::Usage p_usage, const size_t &p_size)
Creates an SSBO bound to a binding point.
Definition spk_shader_storage_buffer_object.cpp:23
void setDynamicElement(const std::wstring &p_name, const BufferLayout::Element &p_elementPrototype)
Defines the prototype for the dynamic array section.
Definition spk_shader_storage_buffer_object.cpp:98
ShaderStorageBufferObject & operator=(const ShaderStorageBufferObject &p_other)
Copies buffer binding and layout configuration from another SSBO.
Definition spk_shader_storage_buffer_object.cpp:51
BufferLayout & layout()
Accesses the layout describing the buffer.
Definition spk_shader_storage_buffer_object.cpp:88
TType pullFixed() const
Reads the fixed section of the SSBO into a trivially copyable type.
Definition spk_shader_storage_buffer_object.hpp:100
void setDynamicPadding(std::size_t p_padding)
Sets padding between fixed and dynamic sections.
Definition spk_shader_storage_buffer_object.cpp:111
std::vector< TElement > pullDynamic() const
Reads the dynamic array section into a vector of elements.
Definition spk_shader_storage_buffer_object.hpp:126
bool needsSynchronization() const noexcept
Checks if synchronization is pending.
Definition spk_synchronizable_object.hpp:32
void requestSynchronization() noexcept
Marks the object as needing synchronization.
Definition spk_synchronizable_object.hpp:23