Sparkle 0.0.1
Loading...
Searching...
No Matches
spk_pipeline.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_buffer_set_object.hpp"
6#include "structure/opengl/spk_frame_buffer_object.hpp"
7#include "structure/opengl/spk_program.hpp"
8#include "structure/opengl/spk_sampler_object.hpp"
9#include "structure/opengl/spk_shader_storage_buffer_object.hpp"
10#include "structure/opengl/spk_uniform_buffer_object.hpp"
11#include "structure/opengl/spk_vertex_buffer_object.hpp"
12#include "utils/spk_string_utils.hpp"
13
14#include <cstddef>
15#include <filesystem>
16#include <memory>
17#include <stdexcept>
18#include <string>
19#include <type_traits>
20#include <unordered_map>
21#include <variant>
22#include <vector>
23
24namespace spk::Lumina
25{
37 class Pipeline
38 {
39 public:
45 {
46 public:
51 enum class Kind
52 {
53 None,
54 UBO,
55 SSBO,
56 Sampler
57 };
58
59 private:
60 Kind _kind = Kind::None;
61 GLuint _bindingPoint = 0;
62 std::size_t _size = 0;
63 std::variant<std::monostate, spk::OpenGL::UBO, spk::OpenGL::SSBO, spk::OpenGL::SamplerObject> _data;
64
65 template <typename TCallable>
66 void _withResource(TCallable &&p_callable)
67 {
68 std::visit(
69 [&](auto &p_resource) {
70 using ResourceType = std::decay_t<decltype(p_resource)>;
71 if constexpr (std::is_same_v<ResourceType, std::monostate>)
72 {
73 throw std::runtime_error("Pipeline constant not initialized");
74 }
75 else
76 {
77 p_callable(p_resource);
78 }
79 },
80 _data);
81 }
82
83 template <typename TResource>
84 TResource &_get()
85 {
86 if (auto ptr = std::get_if<TResource>(&_data))
87 {
88 return *ptr;
89 }
90 throw std::runtime_error("Pipeline constant does not hold requested resource type");
91 }
92
93 template <typename TResource>
94 const TResource &_get() const
95 {
96 if (auto ptr = std::get_if<TResource>(&_data))
97 {
98 return *ptr;
99 }
100 throw std::runtime_error("Pipeline constant does not hold requested resource type");
101 }
102
103 public:
107 Constant() = default;
111 Constant(Constant &&) = default;
117
118 Constant(const Constant &) = delete;
119 Constant &operator=(const Constant &) = delete;
120
125 Kind kind() const noexcept
126 {
127 return _kind;
128 }
129
133 GLuint bindingPoint() const noexcept
134 {
135 return _bindingPoint;
136 }
137
141 std::size_t size() const noexcept
142 {
143 return _size;
144 }
145
152 void setUBO(GLuint p_bindingPoint, std::size_t p_size, spk::OpenGL::BufferObject::Usage p_usage)
153 {
154 _kind = Kind::UBO;
155 _bindingPoint = p_bindingPoint;
156 _size = p_size;
157 _data.emplace<spk::OpenGL::UBO>(p_bindingPoint, p_usage, p_size);
158 }
159
166 void setSSBO(GLuint p_bindingPoint, std::size_t p_size, spk::OpenGL::BufferObject::Usage p_usage)
167 {
168 _kind = Kind::SSBO;
169 _bindingPoint = p_bindingPoint;
170 _size = p_size;
171 _data.emplace<spk::OpenGL::SSBO>(p_bindingPoint, p_usage, p_size);
172 }
173
179 void setSampler(GLint p_uniformLocation, GLuint p_textureUnitIndex)
180 {
181 _kind = Kind::Sampler;
182 _bindingPoint = p_textureUnitIndex;
183 _size = 0;
184 _data.emplace<spk::OpenGL::SamplerObject>(p_uniformLocation, p_textureUnitIndex);
185 }
186
190 void activate()
191 {
192 _withResource([](auto &p_resource) {
193 p_resource.activate();
194 });
195 }
196
201 {
202 _withResource([](auto &p_resource) {
203 p_resource.deactivate();
204 });
205 }
206
211 spk::OpenGL::UBO &ubo()
212 {
213 return _get<spk::OpenGL::UBO>();
214 }
215
219 const spk::OpenGL::UBO &ubo() const
220 {
221 return _get<spk::OpenGL::UBO>();
222 }
223
228 spk::OpenGL::SSBO &ssbo()
229 {
230 return _get<spk::OpenGL::SSBO>();
231 }
232
236 const spk::OpenGL::SSBO &ssbo() const
237 {
238 return _get<spk::OpenGL::SSBO>();
239 }
240
246 {
247 return _get<spk::OpenGL::SamplerObject>();
248 }
249
254 {
255 return _get<spk::OpenGL::SamplerObject>();
256 }
257
262 operator spk::OpenGL::UBO &()
263 {
264 return _get<spk::OpenGL::UBO>();
265 }
266
271 operator const spk::OpenGL::UBO &() const
272 {
273 return _get<spk::OpenGL::UBO>();
274 }
275
280 operator spk::OpenGL::SSBO &()
281 {
282 return _get<spk::OpenGL::SSBO>();
283 }
284
289 operator const spk::OpenGL::SSBO &() const
290 {
291 return _get<spk::OpenGL::SSBO>();
292 }
293
299 {
300 return _get<spk::OpenGL::SamplerObject>();
301 }
302
307 operator const spk::OpenGL::SamplerObject &() const
308 {
309 return _get<spk::OpenGL::SamplerObject>();
310 }
311 };
312
323 class Object
324 {
325 friend class Pipeline;
326
327 public:
332 {
333 public:
338 enum class Kind
339 {
340 None,
341 UBO,
342 SSBO,
343 Sampler
344 };
345
346 private:
347 Kind _kind = Kind::None;
348 GLuint _bindingPoint = 0;
349 std::size_t _size = 0;
350 GLint _uniformLocation = -1;
351 std::variant<std::monostate, spk::OpenGL::UBO, spk::OpenGL::SSBO, spk::OpenGL::SamplerObject> _resource;
352
353 template <typename TResource>
354 TResource &_getResource()
355 {
356 if (auto ptr = std::get_if<TResource>(&_resource))
357 {
358 return *ptr;
359 }
360 throw std::runtime_error("Pipeline attribute does not hold requested resource type");
361 }
362
363 template <typename TResource>
364 const TResource &_getResource() const
365 {
366 if (auto ptr = std::get_if<TResource>(&_resource))
367 {
368 return *ptr;
369 }
370 throw std::runtime_error("Pipeline attribute does not hold requested resource type");
371 }
372
373 public:
377 Attribute() = default;
382 Attribute(const Attribute &p_other) = default;
387 Attribute(Attribute &&p_other) noexcept = default;
393 Attribute &operator=(const Attribute &p_other) = default;
399 Attribute &operator=(Attribute &&p_other) noexcept = default;
400
405 Kind kind() const noexcept
406 {
407 return _kind;
408 }
409
414 GLuint bindingPoint() const noexcept
415 {
416 return _bindingPoint;
417 }
418
423 std::size_t size() const noexcept
424 {
425 return _size;
426 }
427
432 GLint uniformLocation() const noexcept
433 {
434 return _uniformLocation;
435 }
436
443 void setUBO(GLuint p_bindingPoint, std::size_t p_size, spk::OpenGL::BufferObject::Usage p_usage)
444 {
445 _kind = Kind::UBO;
446 _bindingPoint = p_bindingPoint;
447 _size = p_size;
448 _resource.emplace<spk::OpenGL::UBO>(p_bindingPoint, p_usage, p_size);
449 }
450
457 void setSSBO(GLuint p_bindingPoint, std::size_t p_size, spk::OpenGL::BufferObject::Usage p_usage)
458 {
459 _kind = Kind::SSBO;
460 _bindingPoint = p_bindingPoint;
461 _size = p_size;
462 _resource.emplace<spk::OpenGL::SSBO>(p_bindingPoint, p_usage, p_size);
463 }
464
470 void setSampler(GLint p_uniformLocation, GLuint p_textureUnitIndex)
471 {
472 _kind = Kind::Sampler;
473 _bindingPoint = p_textureUnitIndex;
474 _size = 0;
475 _uniformLocation = p_uniformLocation;
476 _resource.emplace<spk::OpenGL::SamplerObject>(p_uniformLocation, p_textureUnitIndex);
477 }
478
482 void activate()
483 {
484 std::visit(
485 [](auto &p_resource) {
486 using ResourceType = std::decay_t<decltype(p_resource)>;
487 if constexpr (std::is_same_v<ResourceType, std::monostate>)
488 {
489 return;
490 }
491 else
492 {
493 p_resource.activate();
494 }
495 },
496 _resource);
497 }
498
503 {
504 std::visit(
505 [](auto &p_resource) {
506 using ResourceType = std::decay_t<decltype(p_resource)>;
507 if constexpr (std::is_same_v<ResourceType, std::monostate>)
508 {
509 return;
510 }
511 else
512 {
513 p_resource.deactivate();
514 }
515 },
516 _resource);
517 }
518
523 spk::OpenGL::UBO &ubo()
524 {
525 return _getResource<spk::OpenGL::UBO>();
526 }
527
532 const spk::OpenGL::UBO &ubo() const
533 {
534 return _getResource<spk::OpenGL::UBO>();
535 }
536
541 spk::OpenGL::SSBO &ssbo()
542 {
543 return _getResource<spk::OpenGL::SSBO>();
544 }
545
550 const spk::OpenGL::SSBO &ssbo() const
551 {
552 return _getResource<spk::OpenGL::SSBO>();
553 }
554
560 {
561 return _getResource<spk::OpenGL::SamplerObject>();
562 }
563
569 {
570 return _getResource<spk::OpenGL::SamplerObject>();
571 }
572
578 template <typename TResourceType>
579 TResourceType &as()
580 {
581 static_assert(
582 std::is_same_v<TResourceType, spk::OpenGL::UBO> ||
583 std::is_same_v<TResourceType, spk::OpenGL::SSBO> ||
584 std::is_same_v<TResourceType, spk::OpenGL::SamplerObject>,
585 "Pipeline::Object::Attribute::as only supports UBO, SSBO, or SamplerObject");
586
587 return _getResource<TResourceType>();
588 }
589
595 template <typename TResourceType>
596 const TResourceType &as() const
597 {
598 static_assert(
599 std::is_same_v<TResourceType, spk::OpenGL::UBO> ||
600 std::is_same_v<TResourceType, spk::OpenGL::SSBO> ||
601 std::is_same_v<TResourceType, spk::OpenGL::SamplerObject>,
602 "Pipeline::Object::Attribute::as only supports UBO, SSBO, or SamplerObject");
603
604 return _getResource<TResourceType>();
605 }
606 };
607
608 private:
609 Pipeline *_owner = nullptr;
610 std::shared_ptr<spk::OpenGL::BufferSetObject> _bufferSet = nullptr;
611 std::unordered_map<std::wstring, Attribute> _attributes;
612
613 explicit Object(Pipeline *p_owner) :
614 _owner(p_owner),
615 _bufferSet(nullptr),
616 _attributes(_owner->_constructObjectAttributes())
617 {
618 }
619
620 public:
624 Object() = default;
625
630 void render(GLsizei p_instanceCount = 1);
631
636 std::shared_ptr<spk::OpenGL::BufferSetObject> &bufferSet()
637 {
638 return _bufferSet;
639 }
640
645 const std::shared_ptr<spk::OpenGL::BufferSetObject> &bufferSet() const
646 {
647 return _bufferSet;
648 }
649
654 void setBufferSet(const std::shared_ptr<spk::OpenGL::BufferSetObject> &p_bufferSet)
655 {
656 _bufferSet = p_bufferSet;
657 }
658
665 Attribute &attribute(const std::wstring &p_name)
666 {
667 return _attribute(p_name);
668 }
669
676 const Attribute &attribute(const std::wstring &p_name) const
677 {
678 return _attribute(p_name);
679 }
680
681 private:
682 Attribute &_attribute(const std::wstring &p_name)
683 {
684 if (_attributes.contains(p_name) == false)
685 {
686 throw std::runtime_error("No attribute [" + spk::StringUtils::wstringToString(p_name) + "] created in pipeline");
687 }
688 return _attributes.at(p_name);
689 }
690
691 const Attribute &_attribute(const std::wstring &p_name) const
692 {
693 if (_attributes.contains(p_name) == false)
694 {
695 throw std::runtime_error("No attribute [" + spk::StringUtils::wstringToString(p_name) + "] created in pipeline");
696 }
697 return _attributes.at(p_name);
698 }
699 };
700
701 friend class Object;
702
703 private:
704 struct State;
705
706 static std::unordered_map<std::wstring, Constant> _constants;
707 static GLuint _nextBindingPoint;
708
709 std::unique_ptr<State> _state;
710
711 void _ensureBlockBindingsLinked();
712 void _activate();
713 void _deactivate();
714 void _activateConstants();
715 void _deactivateConstants();
716 void _render(GLsizei p_indexCount, GLsizei p_instanceCount);
717
718 std::unordered_map<std::wstring, Object::Attribute> _constructObjectAttributes() const;
719 spk::OpenGL::BufferSetObject _constructObjectBufferSet() const;
720
721 explicit Pipeline(std::unique_ptr<State> p_state);
722
723 public:
728 explicit Pipeline(const std::string &p_input);
729 ~Pipeline();
734 Pipeline(Pipeline &&p_other) noexcept = default;
740 Pipeline &operator=(Pipeline &&p_other) noexcept = default;
741 Pipeline(const Pipeline &) = delete;
742 Pipeline &operator=(const Pipeline &) = delete;
748 static Pipeline fromFile(const std::filesystem::path &p_filePath);
749
755
760 std::shared_ptr<spk::OpenGL::BufferSetObject> createBufferSet() const;
761
783 static Constant &insertConstant(const std::string &p_jsonBlock);
784
793 static Constant &insertConstant(const std::wstring &p_jsonBlock);
794
800 static bool containConstant(const std::wstring &p_name);
801
808 static Constant &constant(const std::wstring &p_name);
809
815 static Constant &getOrCreateConstant(const std::string &p_jsonBlock);
821 static Constant &getOrCreateConstant(const std::wstring &p_jsonBlock);
822
829 spk::OpenGL::FrameBufferObject &frameBuffer(const std::wstring &p_name);
836 const spk::OpenGL::FrameBufferObject &frameBuffer(const std::wstring &p_name) const;
837 };
838}
Encapsulates a shader resource (UBO, SSBO, or sampler) bound by a pipeline.
Definition spk_pipeline.hpp:45
Constant()=default
Default constructor for an empty constant.
Constant(Constant &&)=default
Move-constructs a constant, transferring ownership of the underlying resource.
Constant & operator=(Constant &&)=default
Move-assigns from another constant instance.
const spk::OpenGL::UBO & ubo() const
Accesses the constant as a uniform buffer object.
Definition spk_pipeline.hpp:219
std::size_t size() const noexcept
Size of the buffer-backed constant in bytes.
Definition spk_pipeline.hpp:141
spk::OpenGL::SamplerObject & sampler()
Accesses the constant as a sampler object.
Definition spk_pipeline.hpp:245
Kind kind() const noexcept
Reports the currently configured resource type.
Definition spk_pipeline.hpp:125
void setSampler(GLint p_uniformLocation, GLuint p_textureUnitIndex)
Initializes the constant as a sampler bound to a texture unit.
Definition spk_pipeline.hpp:179
void deactivate()
Deactivates the underlying resource on the GPU.
Definition spk_pipeline.hpp:200
const spk::OpenGL::SamplerObject & sampler() const
Accesses the constant as a sampler object.
Definition spk_pipeline.hpp:253
void activate()
Activates the underlying resource on the GPU.
Definition spk_pipeline.hpp:190
GLuint bindingPoint() const noexcept
Binding slot used when the constant represents a buffer or sampler.
Definition spk_pipeline.hpp:133
Kind
Enumerates the supported constant types.
Definition spk_pipeline.hpp:52
void setUBO(GLuint p_bindingPoint, std::size_t p_size, spk::OpenGL::BufferObject::Usage p_usage)
Initializes the constant as a uniform buffer.
Definition spk_pipeline.hpp:152
spk::OpenGL::UBO & ubo()
Accesses the constant as a uniform buffer object.
Definition spk_pipeline.hpp:211
const spk::OpenGL::SSBO & ssbo() const
Accesses the constant as a shader storage buffer object.
Definition spk_pipeline.hpp:236
spk::OpenGL::SSBO & ssbo()
Accesses the constant as a shader storage buffer object.
Definition spk_pipeline.hpp:228
void setSSBO(GLuint p_bindingPoint, std::size_t p_size, spk::OpenGL::BufferObject::Usage p_usage)
Initializes the constant as a shader storage buffer.
Definition spk_pipeline.hpp:166
Attribute instance holding shared OpenGL resources.
Definition spk_pipeline.hpp:332
Attribute(const Attribute &p_other)=default
Copies an attribute and its resource handle.
GLuint bindingPoint() const noexcept
Returns the binding point associated with this attribute.
Definition spk_pipeline.hpp:414
Kind
Enumerates supported attribute resource types.
Definition spk_pipeline.hpp:339
std::size_t size() const noexcept
Returns the attribute resource size in bytes.
Definition spk_pipeline.hpp:423
Attribute(Attribute &&p_other) noexcept=default
Moves an attribute and its resource handle.
TResourceType & as()
Returns the attribute as the requested resource type.
Definition spk_pipeline.hpp:579
void setUBO(GLuint p_bindingPoint, std::size_t p_size, spk::OpenGL::BufferObject::Usage p_usage)
Configures the attribute as a UBO resource.
Definition spk_pipeline.hpp:443
const spk::OpenGL::SamplerObject & sampler() const
Returns the attribute as a sampler resource.
Definition spk_pipeline.hpp:568
Attribute()=default
Builds an empty attribute with no bound resource.
const spk::OpenGL::UBO & ubo() const
Returns the attribute as a UBO resource.
Definition spk_pipeline.hpp:532
const TResourceType & as() const
Returns the attribute as the requested resource type.
Definition spk_pipeline.hpp:596
void deactivate()
Deactivates the underlying resource after rendering.
Definition spk_pipeline.hpp:502
spk::OpenGL::SSBO & ssbo()
Returns the attribute as an SSBO resource.
Definition spk_pipeline.hpp:541
void setSampler(GLint p_uniformLocation, GLuint p_textureUnitIndex)
Configures the attribute as a sampler resource.
Definition spk_pipeline.hpp:470
GLint uniformLocation() const noexcept
Returns the uniform location for sampler attributes.
Definition spk_pipeline.hpp:432
Kind kind() const noexcept
Returns the attribute resource kind.
Definition spk_pipeline.hpp:405
Attribute & operator=(const Attribute &p_other)=default
Copies an attribute and its resource handle.
const spk::OpenGL::SSBO & ssbo() const
Returns the attribute as an SSBO resource.
Definition spk_pipeline.hpp:550
spk::OpenGL::SamplerObject & sampler()
Returns the attribute as a sampler resource.
Definition spk_pipeline.hpp:559
void activate()
Activates the underlying resource for rendering.
Definition spk_pipeline.hpp:482
void setSSBO(GLuint p_bindingPoint, std::size_t p_size, spk::OpenGL::BufferObject::Usage p_usage)
Configures the attribute as an SSBO resource.
Definition spk_pipeline.hpp:457
spk::OpenGL::UBO & ubo()
Returns the attribute as a UBO resource.
Definition spk_pipeline.hpp:523
Attribute & operator=(Attribute &&p_other) noexcept=default
Moves an attribute and its resource handle.
Represents a drawable entity configured with pipeline attributes.
Definition spk_pipeline.hpp:324
std::shared_ptr< spk::OpenGL::BufferSetObject > & bufferSet()
Provides mutable access to the buffer set associated with this object.
Definition spk_pipeline.hpp:636
void render(GLsizei p_instanceCount=1)
Issues a draw call using the object's buffers and configured attributes.
Definition spk_pipeline.cpp:973
void setBufferSet(const std::shared_ptr< spk::OpenGL::BufferSetObject > &p_bufferSet)
Replaces the buffer set used by this object.
Definition spk_pipeline.hpp:654
Object()=default
Constructs an empty pipeline object; attributes become available after assignment from createObject()...
const Attribute & attribute(const std::wstring &p_name) const
Retrieves a named attribute configured on the pipeline.
Definition spk_pipeline.hpp:676
const std::shared_ptr< spk::OpenGL::BufferSetObject > & bufferSet() const
Provides read-only access to the object's buffer set.
Definition spk_pipeline.hpp:645
Attribute & attribute(const std::wstring &p_name)
Retrieves a named attribute configured on the pipeline.
Definition spk_pipeline.hpp:665
Pipeline & operator=(Pipeline &&p_other) noexcept=default
Move-assigns pipeline ownership.
static bool containConstant(const std::wstring &p_name)
Check if the constant defined by name exist in the global registry.
Definition spk_pipeline.cpp:803
static Pipeline fromFile(const std::filesystem::path &p_filePath)
Loads a pipeline definition from disk.
Definition spk_pipeline.cpp:729
std::shared_ptr< spk::OpenGL::BufferSetObject > createBufferSet() const
Creates a buffer set matching the pipeline's vertex layout.
Definition spk_pipeline.cpp:754
Pipeline(Pipeline &&p_other) noexcept=default
Moves pipeline ownership to a new instance.
static Constant & insertConstant(const std::string &p_jsonBlock)
Inserts a global constant from a JSON description block.
Definition spk_pipeline.cpp:759
static Constant & getOrCreateConstant(const std::string &p_jsonBlock)
Retrieves or creates a constant from a JSON description block.
Definition spk_pipeline.cpp:821
spk::OpenGL::FrameBufferObject & frameBuffer(const std::wstring &p_name)
Accesses a framebuffer configured on the pipeline.
Definition spk_pipeline.cpp:852
Object createObject()
Instantiates a drawable object using the pipeline layout.
Definition spk_pipeline.cpp:749
static Constant & constant(const std::wstring &p_name)
Retrieves a mutable constant defined by name in the global registry.
Definition spk_pipeline.cpp:808
Usage
Usage hints forwarded to the OpenGL driver.
Definition spk_buffer_object.hpp:61
RAII wrapper for an OpenGL framebuffer with typed attachments.
Definition spk_frame_buffer_object.hpp:31
Binds a TextureObject to a uniform sampler location and texture unit.
Definition spk_sampler_object.hpp:18