LiteFX 0.5.1.2025
Computer Graphics Engine
Loading...
Searching...
No Matches
rendering_builders.hpp
1#pragma once
2
3#include "rendering_api.hpp"
4#include "rendering.hpp"
5
6#if defined(LITEFX_BUILD_DEFINE_BUILDERS)
7namespace LiteFX::Rendering {
8
15 template <typename TBarrier> requires
16 meta::implements<TBarrier, Barrier<typename TBarrier::buffer_type, typename TBarrier::image_type>>
17 class BarrierBuilder : public Builder<TBarrier> {
18 public:
19 template <typename TParent> requires
20 meta::implements<TParent, BarrierBuilder<TBarrier>>
21 struct [[nodiscard]] ImageBarrierBuilder;
22
27 template <typename TParent> requires
28 meta::implements<TParent, BarrierBuilder<TBarrier>>
29 struct [[nodiscard]] SecondStageBuilder {
30 private:
31 TParent m_parent;
32 PipelineStage m_from;
33
39 constexpr SecondStageBuilder(TParent&& parent, PipelineStage waitFor) noexcept :
40 m_parent(std::move(parent)), m_from(waitFor) { }
41
42 public:
43 friend class BarrierBuilder;
44
50 constexpr auto toContinueWith(PipelineStage stage) -> TParent {
51 this->m_parent.stagesCallback(this->m_from, stage);
52 return std::move(this->m_parent);
53 }
54 };
55
60 template <typename TParent> requires
61 meta::implements<TParent, BarrierBuilder<TBarrier>>
62 struct [[nodiscard]] GlobalBarrierBuilder {
63 private:
64 ResourceAccess m_access;
65 TParent m_parent;
66
72 constexpr GlobalBarrierBuilder(TParent&& parent, ResourceAccess access) noexcept :
73 m_parent(std::move(parent)), m_access(access) { }
74
75 public:
76 friend class BarrierBuilder;
77
82 constexpr auto untilFinishedWith(ResourceAccess access) -> TParent {
83 this->m_parent.globalBarrierCallback(access, m_access);
84 return std::move(this->m_parent);
85 }
86 };
87
92 template <typename TParent> requires
93 meta::implements<TParent, BarrierBuilder<TBarrier>>
94 struct [[nodiscard]] BufferBarrierBuilder {
95 private:
96 ResourceAccess m_access;
97 SharedPtr<IBuffer> m_buffer;
98 TParent m_parent;
99
106 constexpr BufferBarrierBuilder(TParent&& parent, IBuffer& buffer, ResourceAccess access) noexcept :
107 m_parent(std::move(parent)), m_buffer(buffer.shared_from_this()), m_access(access) { }
108
109 public:
110 friend class BarrierBuilder;
111
116 constexpr auto untilFinishedWith(ResourceAccess access) -> TParent {
117 this->m_parent.bufferBarrierCallback(*m_buffer, access, m_access);
118 return std::move(this->m_parent);
119 }
120 };
121
126 template <typename TParent> requires
127 meta::implements<TParent, BarrierBuilder<TBarrier>>
128 struct [[nodiscard]] ImageLayoutBarrierBuilder {
129 private:
130 TParent m_parent;
131 ResourceAccess m_access;
132 SharedPtr<IImage> m_image;
133 ImageLayout m_layout;
134 UInt32 m_level{ 0 }, m_levels{ 1 }, m_layer{ 0 }, m_layers{ 1 }, m_plane{ 0 };
135
148 constexpr ImageLayoutBarrierBuilder(TParent&& parent, IImage& image, ResourceAccess access, ImageLayout layout, UInt32 level, UInt32 levels, UInt32 layer, UInt32 layers, UInt32 plane) noexcept :
149 m_parent(std::move(parent)), m_access(access), m_image(image.shared_from_this()), m_layout(layout), m_level(level), m_levels(levels), m_layer(layer), m_layers(layers), m_plane(plane) { }
150
151 public:
152 friend class BarrierBuilder;
153 friend struct ImageBarrierBuilder<TParent>;
154
159 constexpr auto whenFinishedWith(ResourceAccess access) -> TParent {
160 this->m_parent.imageBarrierCallback(*m_image, access, m_access, m_layout, m_level, m_levels, m_layer, m_layers, m_plane);
161 return std::move(this->m_parent);
162 }
163 };
164
169 template <typename TParent> requires
170 meta::implements<TParent, BarrierBuilder<TBarrier>>
171 struct [[nodiscard]] ImageBarrierBuilder {
172 private:
173 TParent m_parent;
174 ResourceAccess m_access;
175 SharedPtr<IImage> m_image;
176 UInt32 m_level{ 0 }, m_levels{ 0 }, m_layer{ 0 }, m_layers{ 0 }, m_plane{ 0 };
177
184 constexpr ImageBarrierBuilder(TParent&& parent, IImage& image, ResourceAccess access) noexcept :
185 m_parent(std::move(parent)), m_access(access), m_image(image.shared_from_this()) { }
186
187 public:
188 friend class BarrierBuilder;
189
194 constexpr auto transitionLayout(ImageLayout layout) -> ImageLayoutBarrierBuilder<TParent> {
195 return ImageLayoutBarrierBuilder<TParent>{ std::move(m_parent), *m_image, m_access, layout, m_level, m_levels, m_layer, m_layers, m_plane };
196 }
197
206 constexpr auto subresource(UInt32 level, UInt32 levels, UInt32 layer = 0, UInt32 layers = 1, UInt32 plane = 0) -> ImageBarrierBuilder<TParent>& {
207 m_level = level;
208 m_levels = levels;
209 m_layer = layer;
210 m_layers = layers;
211 m_plane = plane;
212
213 return *this;
214 };
215 };
216
217 private:
223 constexpr void stagesCallback(PipelineStage waitFor, PipelineStage continueWith) {
224 this->setupStages(waitFor, continueWith);
225 }
226
232 constexpr void globalBarrierCallback(ResourceAccess before, ResourceAccess after) {
233 this->setupGlobalBarrier(before, after);
234 }
235
242 constexpr void bufferBarrierCallback(IBuffer& buffer, ResourceAccess before, ResourceAccess after) {
243 this->setupBufferBarrier(buffer, before, after);
244 }
245
258 constexpr void imageBarrierCallback(IImage& image, ResourceAccess before, ResourceAccess after, ImageLayout layout, UInt32 level, UInt32 levels, UInt32 layer, UInt32 layers, UInt32 plane) {
259 this->setupImageBarrier(image, before, after, layout, level, levels, layer, layers, plane);
260 }
261
262 protected:
268 constexpr virtual void setupStages(PipelineStage waitFor, PipelineStage continueWith) = 0;
269
275 constexpr virtual void setupGlobalBarrier(ResourceAccess before, ResourceAccess after) = 0;
276
283 constexpr virtual void setupBufferBarrier(IBuffer& buffer, ResourceAccess before, ResourceAccess after) = 0;
284
297 constexpr virtual void setupImageBarrier(IImage& image, ResourceAccess before, ResourceAccess after, ImageLayout layout, UInt32 level, UInt32 levels, UInt32 layer, UInt32 layers, UInt32 plane) = 0;
298
299 public:
300 using Builder<TBarrier>::Builder;
301 using barrier_type = TBarrier;
302
303 public:
308 template <typename TSelf>
309 [[nodiscard]] constexpr auto waitFor(this TSelf&& self, PipelineStage stage) -> SecondStageBuilder<TSelf> {
310 return SecondStageBuilder<TSelf>{ std::forward<TSelf>(self), stage };
311 }
312
317 template <typename TSelf>
318 [[nodiscard]] constexpr auto blockAccessTo(this TSelf&& self, ResourceAccess access) -> GlobalBarrierBuilder<TSelf> {
319 return GlobalBarrierBuilder<TSelf>{ std::forward<TSelf>(self), access };
320 }
321
327 template <typename TSelf>
328 [[nodiscard]] constexpr auto blockAccessTo(this TSelf&& self, IBuffer& buffer, ResourceAccess access) -> BufferBarrierBuilder<TSelf> {
329 return BufferBarrierBuilder<TSelf>{ std::forward<TSelf>(self), buffer, access };
330 }
331
338 template <typename TSelf>
339 [[nodiscard]] constexpr auto blockAccessTo(this TSelf&& self, IBuffer& buffer, UInt32 subresource, ResourceAccess access) -> BufferBarrierBuilder<TSelf> {
340 return BufferBarrierBuilder<TSelf>{ std::forward<TSelf>(self), buffer, subresource, access };
341 }
342
348 template <typename TSelf>
349 [[nodiscard]] constexpr auto blockAccessTo(this TSelf&& self, IImage& image, ResourceAccess access) -> ImageBarrierBuilder<TSelf> {
350 return ImageBarrierBuilder<TSelf>{ std::forward<TSelf>(self), image, access };
351 }
352 };
353
359 template <typename TShaderProgram> requires
360 meta::implements<TShaderProgram, ShaderProgram<typename TShaderProgram::shader_module_type>>
361 class ShaderProgramBuilder : public Builder<TShaderProgram, std::nullptr_t, SharedPtr<TShaderProgram>> {
362 public:
363 using Builder<TShaderProgram, std::nullptr_t, SharedPtr<TShaderProgram>>::Builder;
364 using shader_program_type = TShaderProgram;
365 using shader_module_type = shader_program_type::shader_module_type;
366
367 private:
371 struct ShaderProgramState {
376 } m_state;
377
378 protected:
383 inline ShaderProgramState& state() noexcept {
384 return m_state;
385 }
386
395 constexpr virtual UniquePtr<shader_module_type> makeShaderModule(ShaderStage type, const String& fileName, const String& entryPoint, const Optional<DescriptorBindingPoint>& shaderLocalDescriptor) = 0;
396
406 constexpr virtual UniquePtr<shader_module_type> makeShaderModule(ShaderStage type, std::istream& stream, const String& name, const String& entryPoint, const Optional<DescriptorBindingPoint>& shaderLocalDescriptor) = 0;
407
408 public:
416 template<typename TSelf>
417 [[nodiscard]] constexpr auto withShaderModule(this TSelf&& self, ShaderStage type, const String& fileName, const String& entryPoint = "main", const Optional<DescriptorBindingPoint>& shaderLocalDescriptor = std::nullopt) -> TSelf&& {
418 self.m_state.modules.push_back(std::move(static_cast<ShaderProgramBuilder&>(self).makeShaderModule(type, fileName, entryPoint, shaderLocalDescriptor)));
419 return std::forward<TSelf>(self);
420 }
421
430 template<typename TSelf>
431 [[nodiscard]] constexpr auto withShaderModule(this TSelf&& self, ShaderStage type, std::istream& stream, const String& name, const String& entryPoint = "main", const Optional<DescriptorBindingPoint>& shaderLocalDescriptor = std::nullopt) -> TSelf&& {
432 self.m_state.modules.push_back(std::move(static_cast<ShaderProgramBuilder&>(self).makeShaderModule(type, stream, name, entryPoint, shaderLocalDescriptor)));
433 return std::forward<TSelf>(self);
434 }
435
441 template<typename TSelf>
442 [[nodiscard]] constexpr auto withVertexShaderModule(this TSelf&& self, const String& fileName, const String& entryPoint = "main") -> TSelf&& {
443 return std::forward<TSelf>(self).withShaderModule(ShaderStage::Vertex, fileName, entryPoint);
444 }
445
452 template<typename TSelf>
453 [[nodiscard]] constexpr auto withVertexShaderModule(this TSelf&& self, std::istream& stream, const String& name, const String& entryPoint = "main") -> TSelf&& {
454 return std::forward<TSelf>(self).withShaderModule(ShaderStage::Vertex, stream, name, entryPoint);
455 }
456
465 template<typename TSelf>
466 [[nodiscard]] constexpr auto withTaskShaderModule(this TSelf&& self, const String& fileName, const String& entryPoint = "main") -> TSelf&& {
467 return std::forward<TSelf>(self).withShaderModule(ShaderStage::Task, fileName, entryPoint);
468 }
478 template<typename TSelf>
479 [[nodiscard]] constexpr auto withTaskShaderModule(this TSelf&& self, std::istream& stream, const String& name, const String& entryPoint = "main") -> TSelf&& {
480 return std::forward<TSelf>(self).withShaderModule(ShaderStage::Task, stream, name, entryPoint);
481 }
482
491 template<typename TSelf>
492 [[nodiscard]] constexpr auto withMeshShaderModule(this TSelf&& self, const String& fileName, const String& entryPoint = "main") -> TSelf&& {
493 return std::forward<TSelf>(self).withShaderModule(ShaderStage::Mesh, fileName, entryPoint);
494 }
495
505 template<typename TSelf>
506 [[nodiscard]] constexpr auto withMeshShaderModule(this TSelf&& self, std::istream& stream, const String& name, const String& entryPoint = "main") -> TSelf&& {
507 return std::forward<TSelf>(self).withShaderModule(ShaderStage::Mesh, stream, name, entryPoint);
508 }
509
515 template<typename TSelf>
516 [[nodiscard]] constexpr auto withTessellationControlShaderModule(this TSelf&& self, const String& fileName, const String& entryPoint = "main") -> TSelf&& {
517 return std::forward<TSelf>(self).withShaderModule(ShaderStage::TessellationControl, fileName, entryPoint);
518 }
519
526 template<typename TSelf>
527 [[nodiscard]] constexpr auto withTessellationControlShaderModule(this TSelf&& self, std::istream& stream, const String& name, const String& entryPoint = "main") -> TSelf&& {
528 return std::forward<TSelf>(self).withShaderModule(ShaderStage::TessellationControl, stream, name, entryPoint);
529 }
530
536 template<typename TSelf>
537 [[nodiscard]] constexpr auto withTessellationEvaluationShaderModule(this TSelf&& self, const String& fileName, const String& entryPoint = "main") -> TSelf&& {
538 return std::forward<TSelf>(self).withShaderModule(ShaderStage::TessellationEvaluation, fileName, entryPoint);
539 }
540
547 template<typename TSelf>
548 [[nodiscard]] constexpr auto withTessellationEvaluationShaderModule(this TSelf&& self, std::istream& stream, const String& name, const String& entryPoint = "main") -> TSelf&& {
549 return std::forward<TSelf>(self).withShaderModule(ShaderStage::TessellationEvaluation, stream, name, entryPoint);
550 }
551
557 template<typename TSelf>
558 [[nodiscard]] constexpr auto withGeometryShaderModule(this TSelf&& self, const String& fileName, const String& entryPoint = "main") -> TSelf&& {
559 return std::forward<TSelf>(self).withShaderModule(ShaderStage::Geometry, fileName, entryPoint);
560 }
561
568 template<typename TSelf>
569 [[nodiscard]] constexpr auto withGeometryShaderModule(this TSelf&& self, std::istream& stream, const String& name, const String& entryPoint = "main") -> TSelf&& {
570 return std::forward<TSelf>(self).withShaderModule(ShaderStage::Geometry, stream, name, entryPoint);
571 }
572
578 template<typename TSelf>
579 [[nodiscard]] constexpr auto withFragmentShaderModule(this TSelf&& self, const String& fileName, const String& entryPoint = "main") -> TSelf&& {
580 return std::forward<TSelf>(self).withShaderModule(ShaderStage::Fragment, fileName, entryPoint);
581 }
582
589 template<typename TSelf>
590 [[nodiscard]] constexpr auto withFragmentShaderModule(this TSelf&& self, std::istream& stream, const String& name, const String& entryPoint = "main") -> TSelf&& {
591 return std::forward<TSelf>(self).withShaderModule(ShaderStage::Fragment, stream, name, entryPoint);
592 }
593
599 template<typename TSelf>
600 [[nodiscard]] constexpr auto withComputeShaderModule(this TSelf&& self, const String& fileName, const String& entryPoint = "main") -> TSelf&& {
601 return std::forward<TSelf>(self).withShaderModule(ShaderStage::Compute, fileName, entryPoint);
602 }
603
610 template<typename TSelf>
611 [[nodiscard]] constexpr auto withComputeShaderModule(this TSelf&& self, std::istream& stream, const String& name, const String& entryPoint = "main") -> TSelf&& {
612 return std::forward<TSelf>(self).withShaderModule(ShaderStage::Compute, stream, name, entryPoint);
613 }
614
624 template<typename TSelf>
625 [[nodiscard]] constexpr auto withRayGenerationShaderModule(this TSelf&& self, const String& fileName, const Optional<DescriptorBindingPoint>& shaderLocalDescriptor = std::nullopt, const String& entryPoint = "main") -> TSelf&& {
626 return std::forward<TSelf>(self).withShaderModule(ShaderStage::RayGeneration, fileName, entryPoint, shaderLocalDescriptor);
627 }
628
639 template<typename TSelf>
640 [[nodiscard]] constexpr auto withRayGenerationShaderModule(this TSelf&& self, std::istream& stream, const String& name, const Optional<DescriptorBindingPoint>& shaderLocalDescriptor = std::nullopt, const String& entryPoint = "main") -> TSelf&& {
641 return std::forward<TSelf>(self).withShaderModule(ShaderStage::RayGeneration, stream, name, entryPoint, shaderLocalDescriptor);
642 }
643
653 template<typename TSelf>
654 [[nodiscard]] constexpr auto withMissShaderModule(this TSelf&& self, const String& fileName, const Optional<DescriptorBindingPoint>& shaderLocalDescriptor = std::nullopt, const String& entryPoint = "main") -> TSelf&& {
655 return std::forward<TSelf>(self).withShaderModule(ShaderStage::Miss, fileName, entryPoint, shaderLocalDescriptor);
656 }
657
668 template<typename TSelf>
669 [[nodiscard]] constexpr auto withMissShaderModule(this TSelf&& self, std::istream& stream, const String& name, const Optional<DescriptorBindingPoint>& shaderLocalDescriptor = std::nullopt, const String& entryPoint = "main") -> TSelf&& {
670 return std::forward<TSelf>(self).withShaderModule(ShaderStage::Miss, stream, name, entryPoint, shaderLocalDescriptor);
671 }
672
682 template<typename TSelf>
683 [[nodiscard]] constexpr auto withCallableShaderModule(this TSelf&& self, const String& fileName, const Optional<DescriptorBindingPoint>& shaderLocalDescriptor = std::nullopt, const String& entryPoint = "main") -> TSelf&& {
684 return std::forward<TSelf>(self).withShaderModule(ShaderStage::Callable, fileName, entryPoint, shaderLocalDescriptor);
685 }
686
697 template<typename TSelf>
698 [[nodiscard]] constexpr auto withCallableShaderModule(this TSelf&& self, std::istream& stream, const String& name, const Optional<DescriptorBindingPoint>& shaderLocalDescriptor = std::nullopt, const String& entryPoint = "main") -> TSelf&& {
699 return std::forward<TSelf>(self).withShaderModule(ShaderStage::Callable, stream, name, entryPoint, shaderLocalDescriptor);
700 }
701
710 template<typename TSelf>
711 [[nodiscard]] constexpr auto withIntersectionShaderModule(this TSelf&& self, const String& fileName, const Optional<DescriptorBindingPoint>& shaderLocalDescriptor = std::nullopt, const String& entryPoint = "main") -> TSelf&& {
712 return std::forward<TSelf>(self).withShaderModule(ShaderStage::Intersection, fileName, entryPoint, shaderLocalDescriptor);
713 }
714
725 template<typename TSelf>
726 [[nodiscard]] constexpr auto withIntersectionShaderModule(this TSelf&& self, std::istream& stream, const String& name, const Optional<DescriptorBindingPoint>& shaderLocalDescriptor = std::nullopt, const String& entryPoint = "main") -> TSelf&& {
727 return std::forward<TSelf>(self).withShaderModule(ShaderStage::Intersection, stream, name, entryPoint, shaderLocalDescriptor);
728 }
729
739 template<typename TSelf>
740 [[nodiscard]] constexpr auto withAnyHitShaderModule(this TSelf&& self, const String& fileName, const Optional<DescriptorBindingPoint>& shaderLocalDescriptor = std::nullopt, const String& entryPoint = "main") -> TSelf&& {
741 return std::forward<TSelf>(self).withShaderModule(ShaderStage::AnyHit, fileName, entryPoint, shaderLocalDescriptor);
742 }
743
754 template<typename TSelf>
755 [[nodiscard]] constexpr auto withAnyHitShaderModule(this TSelf&& self, std::istream& stream, const String& name, const Optional<DescriptorBindingPoint>& shaderLocalDescriptor = std::nullopt, const String& entryPoint = "main") -> TSelf&& {
756 return std::forward<TSelf>(self).withShaderModule(ShaderStage::AnyHit, stream, name, entryPoint, shaderLocalDescriptor);
757 }
758
768 template<typename TSelf>
769 [[nodiscard]] constexpr auto withClosestHitShaderModule(this TSelf&& self, const String& fileName, const Optional<DescriptorBindingPoint>& shaderLocalDescriptor = std::nullopt, const String& entryPoint = "main") -> TSelf&& {
770 return std::forward<TSelf>(self).withShaderModule(ShaderStage::ClosestHit, fileName, entryPoint, shaderLocalDescriptor);
771 }
772
783 template<typename TSelf>
784 [[nodiscard]] constexpr auto withClosestHitShaderModule(this TSelf&& self, std::istream& stream, const String& name, const Optional<DescriptorBindingPoint>& shaderLocalDescriptor = std::nullopt, const String& entryPoint = "main") -> TSelf&& {
785 return std::forward<TSelf>(self).withShaderModule(ShaderStage::ClosestHit, stream, name, entryPoint, shaderLocalDescriptor);
786 }
787 };
788
794 template <typename TRasterizer> requires
795 meta::implements<TRasterizer, IRasterizer>
796 class RasterizerBuilder : public Builder<TRasterizer, std::nullptr_t, SharedPtr<TRasterizer>> {
797 public:
798 using Builder<TRasterizer, std::nullptr_t, SharedPtr<TRasterizer>>::Builder;
799 using rasterizer_type = TRasterizer;
800
801 private:
805 struct RasterizerState {
809 PolygonMode polygonMode{ PolygonMode::Solid };
810
814 CullMode cullMode{ CullMode::BackFaces };
815
819 CullOrder cullOrder{ CullOrder::ClockWise };
820
824 Float lineWidth{ 1.0f };
825
829 bool depthClip{ true };
830
834 DepthStencilState::DepthBias depthBias{ };
835
839 DepthStencilState::DepthState depthState{ };
840
844 DepthStencilState::StencilState stencilState{ };
845
849 bool conservativeRasterization{ false };
850 } m_state;
851
852 protected:
857 inline RasterizerState& state() noexcept {
858 return m_state;
859 }
860
861 public:
866 template<typename TSelf>
867 [[nodiscard]] constexpr auto polygonMode(this TSelf&& self, PolygonMode mode) noexcept -> TSelf&& {
868 self.m_state.polygonMode = mode;
869 return std::forward<TSelf>(self);
870 }
871
876 template<typename TSelf>
877 [[nodiscard]] constexpr auto cullMode(this TSelf&& self, CullMode mode) noexcept -> TSelf&& {
878 self.m_state.cullMode = mode;
879 return std::forward<TSelf>(self);
880 }
881
886 template<typename TSelf>
887 [[nodiscard]] constexpr auto cullOrder(this TSelf&& self, CullOrder order) noexcept -> TSelf&& {
888 self.m_state.cullOrder = order;
889 return std::forward<TSelf>(self);
890 }
891
896 template<typename TSelf>
897 [[nodiscard]] constexpr auto lineWidth(this TSelf&& self, Float width) noexcept -> TSelf&& {
898 self.m_state.lineWidth = width;
899 return std::forward<TSelf>(self);
900 }
901
906 template<typename TSelf>
907 [[nodiscard]] constexpr auto depthClip(this TSelf&& self, bool depthClip) noexcept -> TSelf&& {
908 self.m_state.depthClip = depthClip;
909 return std::forward<TSelf>(self);
910 }
911
916 template<typename TSelf>
917 [[nodiscard]] constexpr auto conservativeRasterization(this TSelf&& self, bool enable) noexcept -> TSelf&& {
918 self.m_state.conservativeRasterization = enable;
919 return std::forward<TSelf>(self);
920 }
921
926 template<typename TSelf>
927 [[nodiscard]] constexpr auto depthBias(this TSelf&& self, const DepthStencilState::DepthBias& depthBias) noexcept -> TSelf&& {
928 self.m_state.depthBias = depthBias;
929 return std::forward<TSelf>(self);
930 }
931
936 template<typename TSelf>
937 [[nodiscard]] constexpr auto depthState(this TSelf&& self, const DepthStencilState::DepthState& depthState) noexcept -> TSelf&& {
938 self.m_state.depthState = depthState;
939 return std::forward<TSelf>(self);
940 }
941
946 template<typename TSelf>
947 [[nodiscard]] constexpr auto stencilState(this TSelf&& self, const DepthStencilState::StencilState& stencilState) noexcept -> TSelf&& {
948 self.m_state.stencilState = stencilState;
949 return std::forward<TSelf>(self);
950 }
951 };
952
958 template <typename TVertexBufferLayout, typename TParent> requires
959 meta::implements<TVertexBufferLayout, IVertexBufferLayout>
960 class VertexBufferLayoutBuilder : public Builder<TVertexBufferLayout, TParent, SharedPtr<TVertexBufferLayout>> {
961 public:
962 using Builder<TVertexBufferLayout, TParent, SharedPtr<TVertexBufferLayout>>::Builder;
963 using vertex_buffer_layout_type = TVertexBufferLayout;
964
965 private:
969 struct VertexBufferLayoutState {
973 Array<BufferAttribute> attributes{ };
974
978 VertexBufferInputRate inputRate{ VertexBufferInputRate::Vertex };
979 } m_state;
980
981 protected:
986 inline VertexBufferLayoutState& state() noexcept {
987 return m_state;
988 }
989
990 public:
995 template <typename TSelf>
996 [[nodiscard]] constexpr auto withAttribute(this TSelf&& self, BufferAttribute&& attribute) -> TSelf&& {
997 self.m_state.attributes.push_back(std::move(attribute));
998 return std::forward<TSelf>(self);
999 }
1000
1011 template <typename TSelf>
1012 [[nodiscard]] constexpr auto withAttribute(this TSelf&& self, BufferFormat format, UInt32 offset, AttributeSemantic semantic = AttributeSemantic::Arbitrary, UInt32 semanticIndex = 0) -> TSelf&& {
1013 return std::forward<TSelf>(self).withAttribute({ static_cast<UInt32>(self.m_state.attributes.size()), offset, format, semantic, semanticIndex });
1014 }
1015
1024 template <typename TSelf>
1025 [[nodiscard]] constexpr auto withAttribute(this TSelf&& self, UInt32 location, BufferFormat format, UInt32 offset, AttributeSemantic semantic = AttributeSemantic::Arbitrary, UInt32 semanticIndex = 0) -> TSelf&& {
1026 return std::forward<TSelf>(self).withAttribute({ location, offset, format, semantic, semanticIndex });
1027 }
1028
1033 template <typename TSelf>
1034 [[nodiscard]] constexpr auto atRate(this TSelf&& self, VertexBufferInputRate inputRate) -> TSelf&& {
1035 self.m_state.inputRate = inputRate;
1036 return std::forward<TSelf>(self);
1037 }
1038 };
1039
1046 template <typename TDescriptorSetLayout, typename TParent> requires
1047 meta::implements<TDescriptorSetLayout, DescriptorSetLayout<typename TDescriptorSetLayout::descriptor_layout_type, typename TDescriptorSetLayout::descriptor_set_type>>
1048 class DescriptorSetLayoutBuilder : public Builder<TDescriptorSetLayout, TParent, SharedPtr<TDescriptorSetLayout>> {
1049 public:
1050 using Builder<TDescriptorSetLayout, TParent, SharedPtr<TDescriptorSetLayout>>::Builder;
1051 using descriptor_set_layout_type = TDescriptorSetLayout;
1052 using descriptor_layout_type = descriptor_set_layout_type::descriptor_layout_type;
1053 using descriptor_set_type = descriptor_set_layout_type::descriptor_set_type;
1054
1055 private:
1059 struct DescriptorSetLayoutState {
1063 UInt32 space{};
1064
1068 ShaderStage stages{};
1069
1073 Array<descriptor_layout_type> descriptorLayouts{};
1074 } m_state;
1075
1076 protected:
1081 inline DescriptorSetLayoutState& state() noexcept {
1082 return m_state;
1083 }
1084
1094 constexpr virtual descriptor_layout_type makeDescriptor(DescriptorType type, UInt32 binding, UInt32 descriptorSize, UInt32 descriptors, bool unbounded) = 0;
1095
1111 constexpr virtual descriptor_layout_type makeDescriptor(UInt32 binding, FilterMode magFilter, FilterMode minFilter, BorderMode borderU, BorderMode borderV, BorderMode borderW, MipMapMode mipMapMode, Float mipMapBias, Float minLod, Float maxLod, Float anisotropy) = 0;
1112
1113 public:
1118 template <typename TSelf>
1119 [[nodiscard]] constexpr auto withDescriptor(this TSelf&& self, descriptor_layout_type&& layout) -> TSelf&& {
1120 self.m_state.descriptorLayouts.push_back(std::move(layout));
1121 return std::forward<TSelf>(self);
1122 }
1123
1132 template <typename TSelf>
1133 [[nodiscard]] constexpr auto withDescriptor(this TSelf&& self, DescriptorType type, UInt32 binding, UInt32 descriptorSize, UInt32 descriptors = 1, bool unbounded = false) -> TSelf&& {
1134 self.m_state.descriptorLayouts.push_back(std::move(static_cast<DescriptorSetLayoutBuilder&>(self).makeDescriptor(type, binding, descriptorSize, descriptors, unbounded)));
1135 return std::forward<TSelf>(self);
1136 }
1137
1152 template <typename TSelf>
1153 [[nodiscard]] constexpr auto withStaticSampler(this TSelf&& self, UInt32 binding, FilterMode magFilter = FilterMode::Nearest, FilterMode minFilter = FilterMode::Nearest, BorderMode borderU = BorderMode::Repeat, BorderMode borderV = BorderMode::Repeat, BorderMode borderW = BorderMode::Repeat, MipMapMode mipMapMode = MipMapMode::Nearest, Float mipMapBias = 0.f, Float minLod = 0.f, Float maxLod = std::numeric_limits<Float>::max(), Float anisotropy = 0.f) -> TSelf&& {
1154 self.m_state.descriptorLayouts.push_back(std::move(static_cast<DescriptorSetLayoutBuilder&>(self).makeDescriptor(binding, magFilter, minFilter, borderU, borderV, borderW, mipMapMode, mipMapBias, minLod, maxLod, anisotropy)));
1155 return std::forward<TSelf>(self);
1156 }
1157
1163 template <typename TSelf>
1164 [[nodiscard]] constexpr auto withConstantBuffer(this TSelf&& self, UInt32 binding, UInt32 descriptorSize) -> TSelf&& {
1165 self.m_state.descriptorLayouts.push_back(std::move(static_cast<DescriptorSetLayoutBuilder&>(self).makeDescriptor(DescriptorType::ConstantBuffer, binding, descriptorSize, 1u, false)));
1166 return std::forward<TSelf>(self);
1167 }
1168
1180 template <typename TSelf>
1181 [[nodiscard]] constexpr auto withConstantBufferArray(this TSelf&& self, UInt32 binding, UInt32 descriptorSize, UInt32 descriptors, bool unbounded = false) -> TSelf&& {
1182 self.m_state.descriptorLayouts.push_back(std::move(static_cast<DescriptorSetLayoutBuilder&>(self).makeDescriptor(DescriptorType::ConstantBuffer, binding, descriptorSize, descriptors, unbounded)));
1183 return std::forward<TSelf>(self);
1184 }
1185
1191 template <typename TSelf>
1192 [[nodiscard]] constexpr auto withBuffer(this TSelf&& self, UInt32 binding, bool writable = false) -> TSelf&& {
1193 self.m_state.descriptorLayouts.push_back(std::move(static_cast<DescriptorSetLayoutBuilder&>(self).makeDescriptor(writable ? DescriptorType::RWBuffer : DescriptorType::Buffer, binding, 0u, 1u, false)));
1194 return std::forward<TSelf>(self);
1195 }
1196
1207 template <typename TSelf>
1208 [[nodiscard]] constexpr auto withBufferArray(this TSelf&& self, UInt32 binding, UInt32 descriptors = 1, bool writable = false, bool unbounded = false) -> TSelf&& {
1209 self.m_state.descriptorLayouts.push_back(std::move(static_cast<DescriptorSetLayoutBuilder&>(self).makeDescriptor(writable ? DescriptorType::RWBuffer : DescriptorType::Buffer, binding, 0, descriptors, unbounded)));
1210 return std::forward<TSelf>(self);
1211 }
1212
1218 template <typename TSelf>
1219 [[nodiscard]] constexpr auto withStructuredBuffer(this TSelf&& self, UInt32 binding, bool writable = false) -> TSelf&& {
1220 self.m_state.descriptorLayouts.push_back(std::move(static_cast<DescriptorSetLayoutBuilder&>(self).makeDescriptor(writable ? DescriptorType::RWStructuredBuffer : DescriptorType::StructuredBuffer, binding, 0u, 1u, false)));
1221 return std::forward<TSelf>(self);
1222 }
1223
1234 template <typename TSelf>
1235 [[nodiscard]] constexpr auto withStructuredBufferArray(this TSelf&& self, UInt32 binding, UInt32 descriptors = 1, bool writable = false, bool unbounded = false) -> TSelf&& {
1236 self.m_state.descriptorLayouts.push_back(std::move(static_cast<DescriptorSetLayoutBuilder&>(self).makeDescriptor(writable ? DescriptorType::RWStructuredBuffer : DescriptorType::StructuredBuffer, binding, 0, descriptors, unbounded)));
1237 return std::forward<TSelf>(self);
1238 }
1239
1245 template <typename TSelf>
1246 [[nodiscard]] constexpr auto withByteAddressBuffer(this TSelf&& self, UInt32 binding, bool writable = false) -> TSelf&& {
1247 self.m_state.descriptorLayouts.push_back(std::move(static_cast<DescriptorSetLayoutBuilder&>(self).makeDescriptor(writable ? DescriptorType::RWByteAddressBuffer : DescriptorType::ByteAddressBuffer, binding, 0u, 1u, false)));
1248 return std::forward<TSelf>(self);
1249 }
1250
1261 template <typename TSelf>
1262 [[nodiscard]] constexpr auto withByteAddressBufferArray(this TSelf&& self, UInt32 binding, UInt32 descriptors = 1, bool writable = false, bool unbounded = false) -> TSelf&& {
1263 self.m_state.descriptorLayouts.push_back(std::move(static_cast<DescriptorSetLayoutBuilder&>(self).makeDescriptor(writable ? DescriptorType::RWByteAddressBuffer : DescriptorType::ByteAddressBuffer, binding, 0, descriptors, unbounded)));
1264 return std::forward<TSelf>(self);
1265 }
1266
1272 template <typename TSelf>
1273 [[nodiscard]] constexpr auto withTexture(this TSelf&& self, UInt32 binding, bool writable = false) -> TSelf&& {
1274 self.m_state.descriptorLayouts.push_back(std::move(static_cast<DescriptorSetLayoutBuilder&>(self).makeDescriptor(writable ? DescriptorType::RWTexture : DescriptorType::Texture, binding, 0u, 1u, false)));
1275 return std::forward<TSelf>(self);
1276 }
1277
1288 template <typename TSelf>
1289 [[nodiscard]] constexpr auto withTextureArray(this TSelf&& self, UInt32 binding, UInt32 descriptors = 1, bool writable = false, bool unbounded = false) -> TSelf&& {
1290 self.m_state.descriptorLayouts.push_back(std::move(static_cast<DescriptorSetLayoutBuilder&>(self).makeDescriptor(writable ? DescriptorType::RWTexture : DescriptorType::Texture, binding, 0, descriptors, unbounded)));
1291 return std::forward<TSelf>(self);
1292 }
1293
1298 template <typename TSelf>
1299 [[nodiscard]] constexpr auto withInputAttachment(this TSelf&& self, UInt32 binding) -> TSelf&& {
1300 self.m_state.descriptorLayouts.push_back(std::move(static_cast<DescriptorSetLayoutBuilder&>(self).makeDescriptor(DescriptorType::InputAttachment, binding, 0, false)));
1301 return std::forward<TSelf>(self);
1302 }
1303
1311 template <typename TSelf>
1312 [[nodiscard]] constexpr auto withAccelerationStructure(this TSelf&& self, UInt32 binding) -> TSelf&& {
1313 self.m_state.descriptorLayouts.push_back(std::move(static_cast<DescriptorSetLayoutBuilder&>(self).makeDescriptor(DescriptorType::AccelerationStructure, binding, 0, false)));
1314 return std::forward<TSelf>(self);
1315 }
1316
1321 template <typename TSelf>
1322 [[nodiscard]] constexpr auto withSampler(this TSelf&& self, UInt32 binding) -> TSelf&& {
1323 self.m_state.descriptorLayouts.push_back(std::move(static_cast<DescriptorSetLayoutBuilder&>(self).makeDescriptor(DescriptorType::Sampler, binding, 0u, 1u, false)));
1324 return std::forward<TSelf>(self);
1325 }
1326
1336 template <typename TSelf>
1337 [[nodiscard]] constexpr auto withSamplerArray(this TSelf&& self, UInt32 binding, UInt32 descriptors = 1, bool unbounded = false) -> TSelf&& {
1338 self.m_state.descriptorLayouts.push_back(std::move(static_cast<DescriptorSetLayoutBuilder&>(self).makeDescriptor(DescriptorType::Sampler, binding, 0, descriptors, unbounded)));
1339 return std::forward<TSelf>(self);
1340 }
1341
1348 template <typename TSelf>
1349 [[nodiscard]] constexpr auto withResourceHeapAccess(this TSelf&& self, UInt32 binding, UInt32 heapSize) -> TSelf&& {
1350 self.m_state.descriptorLayouts.push_back(std::move(static_cast<DescriptorSetLayoutBuilder&>(self).makeDescriptor(DescriptorType::ResourceDescriptorHeap, binding, 0u, heapSize, false)));
1351 return std::forward<TSelf>(self);
1352 }
1353
1360 template <typename TSelf>
1361 [[nodiscard]] constexpr auto withSamplerHeapAccess(this TSelf&& self, UInt32 binding, UInt32 heapSize) -> TSelf&& {
1362 self.m_state.descriptorLayouts.push_back(std::move(static_cast<DescriptorSetLayoutBuilder&>(self).makeDescriptor(DescriptorType::SamplerDescriptorHeap, binding, 0u, heapSize, false)));
1363 return std::forward<TSelf>(self);
1364 }
1365
1370 template <typename TSelf>
1371 constexpr auto space(this TSelf&& self, UInt32 space) noexcept -> TSelf&& {
1372 self.m_state.space = space;
1373 return std::forward<TSelf>(self);
1374 }
1375
1380 template <typename TSelf>
1381 constexpr auto shaderStages(this TSelf&& self, ShaderStage stages) noexcept -> TSelf&& {
1382 self.m_state.stages = stages;
1383 return std::forward<TSelf>(self);
1384 }
1385
1386 public:
1392 template <typename TSelf>
1393 [[nodiscard]] constexpr auto use(this TSelf&& self, UniquePtr<descriptor_layout_type>&& layout) -> TSelf&& {
1394 self.m_state.descriptorLayouts.push_back(std::move(layout));
1395 return std::forward<TSelf>(self);
1396 }
1397 };
1398
1404 template <typename TPushConstantsLayout, typename TParent> requires
1405 meta::implements<TPushConstantsLayout, PushConstantsLayout<typename TPushConstantsLayout::push_constants_range_type>>
1406 class PushConstantsLayoutBuilder : public Builder<TPushConstantsLayout, TParent> {
1407 public:
1408 using Builder<TPushConstantsLayout, TParent>::Builder;
1409 using push_constants_layout_type = TPushConstantsLayout;
1410 using push_constants_range_type = push_constants_layout_type::push_constants_range_type;
1411
1412 private:
1416 struct PushConstantsLayoutState {
1421 } m_state;
1422
1423 protected:
1428 inline PushConstantsLayoutState& state() noexcept {
1429 return m_state;
1430 }
1431
1441 virtual UniquePtr<push_constants_range_type> makeRange(ShaderStage shaderStages, UInt32 offset, UInt32 size, UInt32 space, UInt32 binding) = 0;
1442
1443 public:
1452 template <typename TSelf>
1453 constexpr auto withRange(this TSelf&& self, ShaderStage shaderStages, UInt32 offset, UInt32 size, UInt32 space, UInt32 binding) -> TSelf&& {
1454 self.m_state.ranges.push_back(std::move(static_cast<PushConstantsLayoutBuilder&>(self).makeRange(shaderStages, offset, size, space, binding)));
1455 return std::forward<TSelf>(self);
1456 }
1457 };
1458
1464 template <typename TPipelineLayout> requires
1465 meta::implements<TPipelineLayout, PipelineLayout<typename TPipelineLayout::descriptor_set_layout_type, typename TPipelineLayout::push_constants_layout_type>>
1466 class PipelineLayoutBuilder : public Builder<TPipelineLayout, std::nullptr_t, SharedPtr<TPipelineLayout>> {
1467 public:
1468 using Builder<TPipelineLayout, std::nullptr_t, SharedPtr<TPipelineLayout>>::Builder;
1469 using pipeline_layout_type = TPipelineLayout;
1470 using descriptor_set_layout_type = pipeline_layout_type::descriptor_set_layout_type;
1471 using push_constants_layout_type = pipeline_layout_type::push_constants_layout_type;
1472
1473 private:
1477 struct PipelineLayoutState {
1481 Array<SharedPtr<descriptor_set_layout_type>> descriptorSetLayouts{ };
1482
1486 UniquePtr<push_constants_layout_type> pushConstantsLayout{ };
1487 } m_state;
1488
1489 protected:
1494 inline PipelineLayoutState& state() noexcept {
1495 return m_state;
1496 }
1497
1498 public:
1504 template <typename TSelf>
1505 constexpr auto use(this TSelf&& self, SharedPtr<descriptor_set_layout_type>&& layout) -> TSelf&& {
1506 self.m_state.descriptorSetLayouts.push_back(std::move(layout));
1507 return std::forward<TSelf>(self);
1508 }
1509
1515 template <typename TSelf>
1516 constexpr auto use(this TSelf&& self, UniquePtr<push_constants_layout_type>&& layout) -> TSelf&& {
1517 self.m_state.pushConstantsLayout = std::move(layout);
1518 return std::forward<TSelf>(self);
1519 }
1520 };
1521
1527 template <typename TInputAssembler> requires
1528 meta::implements<TInputAssembler, InputAssembler<typename TInputAssembler::vertex_buffer_layout_type, typename TInputAssembler::index_buffer_layout_type>>
1529 class InputAssemblerBuilder : public Builder<TInputAssembler, std::nullptr_t, SharedPtr<TInputAssembler>> {
1530 public:
1531 using Builder<TInputAssembler, std::nullptr_t, SharedPtr<TInputAssembler>>::Builder;
1532 using input_assembler_type = TInputAssembler;
1533 using vertex_buffer_layout_type = input_assembler_type::vertex_buffer_layout_type;
1534 using index_buffer_layout_type = input_assembler_type::index_buffer_layout_type;
1535
1536 private:
1540 struct InputAssemblerState {
1544 PrimitiveTopology topology{};
1545
1549 Array<SharedPtr<vertex_buffer_layout_type>> vertexBufferLayouts{};
1550
1554 SharedPtr<index_buffer_layout_type> indexBufferLayout{};
1555 } m_state;
1556
1557 protected:
1562 inline InputAssemblerState& state() noexcept {
1563 return m_state;
1564 }
1565
1566 public:
1571 template <typename TSelf>
1572 constexpr auto topology(this TSelf&& self, PrimitiveTopology topology) -> TSelf&& {
1573 self.m_state.topology = topology;
1574 return std::forward<TSelf>(self);
1575 }
1576
1581 template <typename TSelf>
1582 constexpr auto use(this TSelf&& self, SharedPtr<vertex_buffer_layout_type>&& layout) -> TSelf&& {
1583 self.m_state.vertexBufferLayouts.push_back(std::move(layout));
1584 return std::forward<TSelf>(self);
1585 }
1586
1592 template <typename TSelf>
1593 constexpr auto use(this TSelf&& self, SharedPtr<index_buffer_layout_type>&& layout) -> TSelf&& {
1594 self.m_state.indexBufferLayout = std::move(layout);
1595 return std::forward<TSelf>(self);
1596 }
1597 };
1598
1604 template <typename TRenderPipeline> requires
1605 meta::implements<TRenderPipeline, RenderPipeline<typename TRenderPipeline::pipeline_layout_type, typename TRenderPipeline::shader_program_type, typename TRenderPipeline::input_assembler_type, typename TRenderPipeline::rasterizer_type>>
1606 class RenderPipelineBuilder : public Builder<TRenderPipeline> {
1607 public:
1608 using Builder<TRenderPipeline>::Builder;
1609 using render_pipeline_type = TRenderPipeline;
1610 using pipeline_layout_type = render_pipeline_type::pipeline_layout_type;
1611 using shader_program_type = render_pipeline_type::shader_program_type;
1612 using input_assembler_type = render_pipeline_type::input_assembler_type;
1613 using rasterizer_type = render_pipeline_type::rasterizer_type;
1614
1615 private:
1619 struct RenderPipelineState {
1623 SharedPtr<shader_program_type> shaderProgram{ };
1624
1628 SharedPtr<pipeline_layout_type> pipelineLayout{ };
1629
1633 SharedPtr<rasterizer_type> rasterizer{ };
1634
1638 SharedPtr<input_assembler_type> inputAssembler{ };
1639
1643 bool enableAlphaToCoverage{ false };
1644
1648 MultiSamplingLevel samples { MultiSamplingLevel::x1 };
1649 } m_state;
1650
1651 protected:
1656 inline RenderPipelineState& state() noexcept {
1657 return m_state;
1658 }
1659
1660 public:
1669 template <typename TSelf>
1670 constexpr auto shaderProgram(this TSelf&& self, SharedPtr<shader_program_type> program) -> TSelf&& {
1671 self.m_state.shaderProgram = std::move(program);
1672 return std::forward<TSelf>(self);
1673 }
1674
1679 template <typename TSelf>
1680 constexpr auto layout(this TSelf&& self, SharedPtr<pipeline_layout_type> layout) -> TSelf&& {
1681 self.m_state.pipelineLayout = std::move(layout);
1682 return std::forward<TSelf>(self);
1683 }
1684
1689 template <typename TSelf>
1690 constexpr auto rasterizer(this TSelf&& self, SharedPtr<rasterizer_type> rasterizer) -> TSelf&& {
1691 self.m_state.rasterizer = std::move(rasterizer);
1692 return std::forward<TSelf>(self);
1693 }
1694
1699 template <typename TSelf>
1700 constexpr auto inputAssembler(this TSelf&& self, SharedPtr<input_assembler_type> inputAssembler) -> TSelf&& {
1701 self.m_state.inputAssembler = std::move(inputAssembler);
1702 return std::forward<TSelf>(self);
1703 }
1704
1712 template <typename TSelf>
1713 constexpr auto enableAlphaToCoverage(this TSelf&& self, bool enable = true) -> TSelf&& {
1714 self.m_state.enableAlphaToCoverage = enable;
1715 return std::forward<TSelf>(self);
1716 }
1717
1722 template <typename TSelf>
1723 constexpr auto samples(this TSelf&& self, MultiSamplingLevel samples) -> TSelf&& {
1724 self.m_state.samples = samples;
1725 return std::forward<TSelf>(self);
1726 }
1727 };
1728
1734 template <typename TComputePipeline> requires
1735 meta::implements<TComputePipeline, ComputePipeline<typename TComputePipeline::pipeline_layout_type, typename TComputePipeline::shader_program_type>>
1736 class ComputePipelineBuilder : public Builder<TComputePipeline> {
1737 public:
1738 using Builder<TComputePipeline>::Builder;
1739 using compute_pipeline_type = TComputePipeline;
1740 using pipeline_layout_type = compute_pipeline_type::pipeline_layout_type;
1741 using shader_program_type = compute_pipeline_type::shader_program_type;
1742
1743 private:
1747 struct ComputePipelineState {
1751 SharedPtr<shader_program_type> shaderProgram{ };
1752
1756 SharedPtr<pipeline_layout_type> pipelineLayout{ };
1757 } m_state;
1758
1759 protected:
1764 inline ComputePipelineState& state() noexcept {
1765 return m_state;
1766 }
1767
1768 public:
1777 template <typename TSelf>
1778 constexpr auto shaderProgram(this TSelf&& self, SharedPtr<shader_program_type> program) -> TSelf&& {
1779 self.m_state.shaderProgram = std::move(program);
1780 return std::forward<TSelf>(self);
1781 }
1782
1787 template <typename TSelf>
1788 constexpr auto layout(this TSelf&& self, SharedPtr<pipeline_layout_type> layout) -> TSelf&& {
1789 self.m_state.pipelineLayout = std::move(layout);
1790 return std::forward<TSelf>(self);
1791 }
1792 };
1793
1799 template <typename TRayTracingPipeline> requires
1800 meta::implements<TRayTracingPipeline, RayTracingPipeline<typename TRayTracingPipeline::pipeline_layout_type, typename TRayTracingPipeline::shader_program_type>>
1801 class RayTracingPipelineBuilder : public Builder<TRayTracingPipeline> {
1802 public:
1803 using Builder<TRayTracingPipeline>::Builder;
1804 using raytracing_pipeline_type = TRayTracingPipeline;
1805 using pipeline_layout_type = raytracing_pipeline_type::pipeline_layout_type;
1806 using shader_program_type = raytracing_pipeline_type::shader_program_type;
1807
1808 private:
1812 struct RayTracingPipelineState {
1816 SharedPtr<pipeline_layout_type> pipelineLayout { };
1817
1821 UInt32 maxRecursionDepth { 10 }; // NOLINT(cppcoreguidelines-avoid-magic-numbers)
1822
1826 UInt32 maxPayloadSize { 0 }; // NOLINT(cppcoreguidelines-avoid-magic-numbers)
1827
1831 UInt32 maxAttributeSize { 32 }; // NOLINT(cppcoreguidelines-avoid-magic-numbers)
1832 } m_state;
1833
1834 protected:
1839 inline RayTracingPipelineState& state() noexcept {
1840 return m_state;
1841 }
1842
1843 public:
1848 template <typename TSelf>
1849 constexpr auto layout(this TSelf&& self, SharedPtr<pipeline_layout_type> layout) -> TSelf&& {
1850 self.m_state.pipelineLayout = std::move(layout);
1851 return std::forward<TSelf>(self);
1852 }
1853
1858 template <typename TSelf>
1859 constexpr auto maxBounces(this TSelf&& self, UInt32 maxRecursionDepth) -> TSelf&& {
1860 self.m_state.maxRecursionDepth = maxRecursionDepth;
1861 return std::forward<TSelf>(self);
1862 }
1863
1868 template <typename TSelf>
1869 constexpr auto maxPayloadSize(this TSelf&& self, UInt32 maxPayloadSize) -> TSelf&& {
1870 self.m_state.maxPayloadSize = maxPayloadSize;
1871 return std::forward<TSelf>(self);
1872 }
1873
1878 template <typename TSelf>
1879 constexpr auto maxAttributeSize(this TSelf&& self, UInt32 maxAttributeSize) -> TSelf&& {
1880 self.m_state.maxAttributeSize = maxAttributeSize;
1881 return std::forward<TSelf>(self);
1882 }
1883 };
1884
1891 template <typename TRenderPass> requires
1892 meta::implements<TRenderPass, RenderPass<typename TRenderPass::command_queue_type, typename TRenderPass::frame_buffer_type>>
1893 class RenderPassBuilder : public Builder<TRenderPass, std::nullptr_t, SharedPtr<TRenderPass>> {
1894 public:
1895 using Builder<TRenderPass, std::nullptr_t, SharedPtr<TRenderPass>>::Builder;
1896 using render_pass_type = TRenderPass;
1897 using command_queue_type = render_pass_type::command_queue_type;
1898
1899 private:
1903 struct RenderPassState {
1907 UInt32 commandBufferCount{ 0 };
1908
1912 Array<RenderTarget> renderTargets{ };
1913
1917 Array<RenderPassDependency> inputAttachments{ };
1918
1922 SharedPtr<const command_queue_type> commandQueue{ nullptr };
1923
1927 Optional<DescriptorBindingPoint> inputAttachmentSamplerBinding{ std::nullopt };
1928
1933 UInt32 viewMask{ 0b0000 };
1934 } m_state;
1935
1936 protected:
1941 inline RenderPassState& state() noexcept {
1942 return m_state;
1943 }
1944
1951 virtual RenderPassDependency makeInputAttachment(DescriptorBindingPoint binding, const RenderTarget& renderTarget) = 0;
1952
1953 public:
1962 template <typename TSelf>
1963 constexpr auto executeOn(this TSelf&& self, const command_queue_type& queue) -> TSelf&& {
1964 self.m_state.commandQueue = queue.shared_from_this();
1965 return std::forward<TSelf>(self);
1966 }
1967
1972 template <typename TSelf>
1973 constexpr auto commandBuffers(this TSelf&& self, UInt32 count) -> TSelf&& {
1974 self.m_state.commandBufferCount = count;
1975 return std::forward<TSelf>(self);
1976 }
1977
1985 template <typename TSelf>
1986 constexpr auto renderTarget(this TSelf&& self, RenderTargetType type, Format format, RenderTargetFlags flags = RenderTargetFlags::None, const Vector4f& clearValues = { 0.0f, 0.0f, 0.0f, 0.0f }) -> TSelf&& {
1987 self.renderTarget("", static_cast<UInt32>(self.m_state.renderTargets.size()), type, format, flags, clearValues);
1988 return std::forward<TSelf>(self);
1989 }
1990
1999 template <typename TSelf>
2000 constexpr auto renderTarget(this TSelf&& self, const String& name, RenderTargetType type, Format format, RenderTargetFlags flags = RenderTargetFlags::None, const Vector4f& clearValues = { 0.0f, 0.0f, 0.0f, 0.0f }) -> TSelf&& {
2001 self.renderTarget(name, static_cast<UInt32>(self.m_state.renderTargets.size()), type, format, flags, clearValues);
2002 return std::forward<TSelf>(self);
2003 }
2004
2013 template <typename TSelf>
2014 constexpr auto renderTarget(this TSelf&& self, UInt32 location, RenderTargetType type, Format format, RenderTargetFlags flags = RenderTargetFlags::None, const Vector4f& clearValues = { 0.0f, 0.0f, 0.0f, 0.0f }) -> TSelf&& {
2015 self.renderTarget("", location, type, format, flags, clearValues);
2016 return std::forward<TSelf>(self);
2017 }
2018
2028 template <typename TSelf>
2029 constexpr auto renderTarget(this TSelf&& self, const String& name, UInt32 location, RenderTargetType type, Format format, RenderTargetFlags flags = RenderTargetFlags::None, const Vector4f& clearValues = { 0.0f, 0.0f, 0.0f, 0.0f }) -> TSelf&& {
2030 self.m_state.renderTargets.push_back(RenderTarget(name, location, type, format, flags, clearValues));
2031 return std::forward<TSelf>(self);
2032 }
2033
2040 template <typename TSelf>
2041 constexpr auto inputAttachment(this TSelf&& self, DescriptorBindingPoint binding, const render_pass_type& renderPass, UInt32 outputLocation) -> TSelf&& {
2042 self.m_state.inputAttachments.push_back(static_cast<RenderPassBuilder&>(self).makeInputAttachment(binding, renderPass.renderTarget(outputLocation)));
2043 return std::forward<TSelf>(self);
2044 }
2045
2051 template <typename TSelf>
2052 auto inputAttachment(this TSelf&& self, DescriptorBindingPoint binding, RenderTarget renderTarget) -> TSelf&& {
2053 self.m_state.inputAttachments.push_back(static_cast<RenderPassBuilder&>(self).makeInputAttachment(binding, renderTarget));
2054 return std::forward<TSelf>(self);
2055 }
2056
2061 template <typename TSelf>
2062 constexpr auto inputAttachmentSamplerBinding(this TSelf&& self, const DescriptorBindingPoint& bindingPoint) -> TSelf&& {
2063 self.m_state.inputAttachmentSamplerBinding = bindingPoint;
2064 return std::forward<TSelf>(self);
2065 }
2066
2071 template <typename TSelf>
2072 constexpr auto inputAttachmentSamplerBinding(this TSelf&& self, UInt32 viewMask) -> TSelf&& {
2073 self.m_state.viewMask = viewMask;
2074 return std::forward<TSelf>(self);
2075 }
2076 };
2077
2078}
2079#endif // defined(LITEFX_BUILD_DEFINE_BUILDERS)
Describes an generic builder type.
Definition containers.hpp:960
Definition math.hpp:548
Stores meta data about a buffer attribute, i.e. a member or field of a descriptor or buffer.
Definition rendering_api.hpp:4437
Base interface for buffer objects.
Definition rendering_api.hpp:4997
Describes a generic image.
Definition rendering_api.hpp:5019
Represents a mapping between a set of RenderTarget instances and the input attachments of a IRenderPa...
Definition rendering_api.hpp:3684
Implements a render target.
Definition rendering_api.hpp:3584
float_t Float
A type for a floating point value with single precision.
Definition math.hpp:76
uint32_t UInt32
A type for an unsigned 32 bit integer.
Definition math.hpp:61
Definition dx12.hpp:11
BorderMode
Describes how to treat texture coordinates that are outside the domain [0..1].
Definition rendering_api.hpp:1356
CullOrder
Describes the order or vertex winding, that is used to determine, whether a polygon is facing towards...
Definition rendering_api.hpp:1190
RenderTargetFlags
Describes the behavior of render targets.
Definition rendering_api.hpp:1228
ImageLayout
Specifies the layout of an IImage resource.
Definition rendering_api.hpp:1858
MipMapMode
Describes the filter operation between two mip-map levels.
Definition rendering_api.hpp:1341
CullMode
Describes which faces are culled by the Rasterizer stage.
Definition rendering_api.hpp:1163
ShaderStage
Describes the valid shader stages of a graphics pipeline.
Definition rendering_api.hpp:971
RenderTargetType
Describes the type of a render target.
Definition rendering_api.hpp:1205
PrimitiveTopology
Describes the topology of a mesh primitive.
Definition rendering_api.hpp:937
PolygonMode
Describes the draw mode for polygons.
Definition rendering_api.hpp:1142
AttributeSemantic
Describes the semantic of a buffer attribute.
Definition rendering_api.hpp:372
@ RenderTarget
Allows the resource to be used as a render target.
DescriptorType
Describes the type of a IDescriptor.
Definition rendering_api.hpp:442
FilterMode
Describes the filter operation when accessing a pixel from a texture coordinate.
Definition rendering_api.hpp:1324
VertexBufferInputRate
The rate at which a vertex buffer of a certain IVertexBufferLayout is made available for vertex shade...
Definition rendering_api.hpp:922
PipelineStage
Defines pipeline stages as points where synchronization may occur.
Definition rendering_api.hpp:1545
BufferFormat
Describes a buffer attribute format.
Definition rendering_api.hpp:340
ResourceAccess
Defines how a IBuffer or IImage resource is accessed.
Definition rendering_api.hpp:1709
Format
Describes a texel format.
Definition rendering_api.hpp:183
MultiSamplingLevel
Describes the number of samples with which a IImage is sampled.
Definition rendering_api.hpp:1283
std::vector< T > Array
Represents a dynamic array.
Definition containers.hpp:73
std::optional< T > Optional
Represents an optional value.
Definition containers.hpp:94
std::shared_ptr< T > SharedPtr
Represents a shared pointer, that expresses non-exclusive ownership.
Definition containers.hpp:109
std::unique_ptr< T, TDeleter > UniquePtr
Represents a unique pointer, that expresses exclusive ownership.
Definition containers.hpp:102
std::string String
Definition string.hpp:24
Describes the rasterizer depth bias.
Definition rendering_api.hpp:3797
Describes the rasterizer depth state.
Definition rendering_api.hpp:3758
Describes the rasterizer stencil state.
Definition rendering_api.hpp:3849
Describes a single descriptor binding point within a IShaderModule.
Definition rendering_api.hpp:3309