Blender V5.0
draw_pass.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2022 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
42
43#include "BLI_assert.h"
45#include "BLI_vector.hh"
46
47#include "BKE_image.hh"
48
49#include "GPU_batch.hh"
50#include "GPU_debug.hh"
51#include "GPU_index_buffer.hh"
52#include "GPU_material.hh"
53#include "GPU_pass.hh"
54
55#include "DRW_gpu_wrapper.hh"
56
57#include "draw_command.hh"
58#include "draw_handle.hh"
59#include "draw_manager.hh"
60#include "draw_shader_shared.hh"
61#include "draw_state.hh"
62
63#include <cstdint>
64#include <sstream>
65
66namespace blender::draw {
67using namespace blender::draw;
68using namespace blender::draw::command;
69
72
73class Manager;
74
75namespace command {
76class DrawCommandBuf;
77}
78
79/* -------------------------------------------------------------------- */
82
83namespace detail {
84
88template<typename T,
90 int64_t block_size = 16>
92 private:
94
95 public:
96 void clear()
97 {
98 blocks_.clear();
99 }
100
102 {
103 /* Do not go over the inline size so that existing members never move. */
104 if (blocks_.is_empty() || blocks_.last()->size() == block_size) {
105 blocks_.append(std::make_unique<Vector<T, block_size>>());
106 }
107 return blocks_.last()->append_and_get_index(std::move(elem)) +
108 (blocks_.size() - 1) * block_size;
109 }
110
112 {
113 return (*blocks_[index / block_size])[index % block_size];
114 }
115
116 const T &operator[](int64_t index) const
117 {
118 return (*blocks_[index / block_size])[index % block_size];
119 }
120};
121
125template<
127 typename DrawCommandBufType>
128class PassBase {
129 friend Manager;
130 friend DrawCommandBuf;
131
133 static constexpr GPUSamplerState sampler_auto = GPUSamplerState::internal_sampler();
134
135 protected:
141 DrawCommandBufType &draw_commands_buf_;
146
149
150 bool is_empty_ = true;
151
152 public:
153 const char *debug_name;
154
156
157 PassBase(const char *name,
158 DrawCommandBufType &draw_command_buf,
160 gpu::Shader *shader = nullptr)
161 : draw_commands_buf_(draw_command_buf),
162 sub_passes_(sub_passes),
163 shader_(shader),
166
172 void init();
173
177 bool is_empty() const;
178
183
194 void state_set(DRWState state, int clip_plane_count = 0);
195
200 void clear_depth(float depth);
201 void clear_stencil(uint8_t stencil);
202 void clear_depth_stencil(float depth, uint8_t stencil);
203 void clear_color_depth_stencil(float4 color, float depth, uint8_t stencil);
208 void clear_multi(Span<float4> colors);
209
222 void state_stencil(uint8_t write_mask, uint8_t reference, uint8_t compare_mask);
223
227 void shader_set(gpu::Shader *shader);
228
234 void framebuffer_set(gpu::FrameBuffer **framebuffer);
235
241 void subpass_transition(GPUAttachmentState depth_attachment,
242 Span<GPUAttachmentState> color_attachments);
243
249 void material_set(Manager &manager,
250 GPUMaterial *material,
251 bool deferred_texture_loading = false);
252
258 void draw(gpu::Batch *batch,
259 uint instance_len = -1,
260 uint vertex_len = -1,
261 uint vertex_first = -1,
262 ResourceIndexRange res_index = {},
263 uint custom_id = 0);
264
269 void draw(gpu::Batch *batch, ResourceIndexRange res_index, uint custom_id = 0);
270
275 void draw_procedural(GPUPrimType primitive,
276 uint instance_len,
277 uint vertex_len,
278 uint vertex_first = -1,
279 ResourceIndexRange res_index = {},
280 uint custom_id = 0);
281
295 void draw_expand(gpu::Batch *batch,
296 GPUPrimType primitive_type,
297 uint primitive_len,
298 uint instance_len,
299 uint vertex_len,
300 uint vertex_first,
301 ResourceIndexRange res_index = {},
302 uint custom_id = 0);
303
308 void draw_expand(gpu::Batch *batch,
309 GPUPrimType primitive_type,
310 uint primitive_len,
311 uint instance_len,
312 ResourceIndexRange res_index = {},
313 uint custom_id = 0);
314
319 void draw_indirect(gpu::Batch *batch,
320 StorageBuffer<DrawCommand, true> &indirect_buffer,
321 ResourceIndex res_index = {0});
323 StorageBuffer<DrawCommand, true> &indirect_buffer,
324 ResourceIndex res_index = {0});
325
329 void dispatch(int group_len);
330 void dispatch(int2 group_len);
331 void dispatch(int3 group_len);
332 void dispatch(int3 *group_len);
333 void dispatch(StorageBuffer<DispatchCommand> &indirect_buffer);
334
338 void barrier(GPUBarrier type);
339
352 void bind_image(const char *name, gpu::Texture *image);
353 void bind_image(const char *name, gpu::Texture **image);
354 void bind_image(int slot, gpu::Texture *image);
355 void bind_image(int slot, gpu::Texture **image);
356 void bind_texture(const char *name, gpu::Texture *texture, GPUSamplerState state = sampler_auto);
357 void bind_texture(const char *name,
358 gpu::Texture **texture,
359 GPUSamplerState state = sampler_auto);
360 void bind_texture(const char *name, gpu::VertBuf *buffer);
361 void bind_texture(const char *name, gpu::VertBuf **buffer);
362 void bind_texture(const char *name, gpu::VertBufPtr &buffer);
363 void bind_texture(int slot, gpu::Texture *texture, GPUSamplerState state = sampler_auto);
364 void bind_texture(int slot, gpu::Texture **texture, GPUSamplerState state = sampler_auto);
365 void bind_texture(int slot, gpu::VertBuf *buffer);
366 void bind_texture(int slot, gpu::VertBuf **buffer);
367 void bind_texture(int slot, gpu::VertBufPtr &buffer);
368 void bind_ssbo(const char *name, gpu::StorageBuf *buffer);
369 void bind_ssbo(const char *name, gpu::StorageBuf **buffer);
370 void bind_ssbo(int slot, gpu::StorageBuf *buffer);
371 void bind_ssbo(int slot, gpu::StorageBuf **buffer);
372 void bind_ssbo(const char *name, gpu::UniformBuf *buffer);
373 void bind_ssbo(const char *name, gpu::UniformBuf **buffer);
374 void bind_ssbo(int slot, gpu::UniformBuf *buffer);
375 void bind_ssbo(int slot, gpu::UniformBuf **buffer);
376 void bind_ssbo(const char *name, gpu::VertBuf *buffer);
377 void bind_ssbo(const char *name, gpu::VertBuf **buffer);
378 void bind_ssbo(const char *name, gpu::VertBufPtr &buffer);
379 void bind_ssbo(int slot, gpu::VertBuf *buffer);
380 void bind_ssbo(int slot, gpu::VertBuf **buffer);
381 void bind_ssbo(int slot, gpu::VertBufPtr &buffer);
382 void bind_ssbo(const char *name, gpu::IndexBuf *buffer);
383 void bind_ssbo(const char *name, gpu::IndexBuf **buffer);
384 void bind_ssbo(int slot, gpu::IndexBuf *buffer);
385 void bind_ssbo(int slot, gpu::IndexBuf **buffer);
386 void bind_ubo(const char *name, gpu::UniformBuf *buffer);
387 void bind_ubo(const char *name, gpu::UniformBuf **buffer);
388 void bind_ubo(int slot, gpu::UniformBuf *buffer);
389 void bind_ubo(int slot, gpu::UniformBuf **buffer);
390
402 void push_constant(const char *name, const float &data);
403 void push_constant(const char *name, const float2 &data);
404 void push_constant(const char *name, const float3 &data);
405 void push_constant(const char *name, const float4 &data);
406 void push_constant(const char *name, const int &data);
407 void push_constant(const char *name, const int2 &data);
408 void push_constant(const char *name, const int3 &data);
409 void push_constant(const char *name, const int4 &data);
410 void push_constant(const char *name, const bool &data);
411 void push_constant(const char *name, const float4x4 &data);
412 void push_constant(const char *name, const float *data, int array_len = 1);
413 void push_constant(const char *name, const float2 *data, int array_len = 1);
414 void push_constant(const char *name, const float3 *data, int array_len = 1);
415 void push_constant(const char *name, const float4 *data, int array_len = 1);
416 void push_constant(const char *name, const int *data, int array_len = 1);
417 void push_constant(const char *name, const int2 *data, int array_len = 1);
418 void push_constant(const char *name, const int3 *data, int array_len = 1);
419 void push_constant(const char *name, const int4 *data, int array_len = 1);
420 void push_constant(const char *name, const float4x4 *data);
421
434 void specialize_constant(gpu::Shader *shader, const char *name, const float &data);
435 void specialize_constant(gpu::Shader *shader, const char *name, const int &data);
436 void specialize_constant(gpu::Shader *shader, const char *name, const uint &data);
437 void specialize_constant(gpu::Shader *shader, const char *name, const bool &data);
438 void specialize_constant(gpu::Shader *shader, const char *name, const float *data);
439 void specialize_constant(gpu::Shader *shader, const char *name, const int *data);
440 void specialize_constant(gpu::Shader *shader, const char *name, const uint *data);
441 void specialize_constant(gpu::Shader *shader, const char *name, const bool *data);
442
449 template<class U> void bind_resources(U &resources)
450 {
451 resources.bind_resources(*this);
452 }
453
457 std::string serialize(std::string line_prefix = "") const;
458
459 friend std::ostream &operator<<(std::ostream &stream, const PassBase &pass)
460 {
461 return stream << pass.serialize();
462 }
463
464 protected:
468
469 int push_constant_offset(const char *name);
470
471 void clear(GPUFrameBufferBits planes, float4 color, float depth, uint8_t stencil);
472
473 gpu::Batch *procedural_batch_get(GPUPrimType primitive);
474
479
485
487
489 {
490 /* NOTE: Even though manager fingerprint is not enough to check for update, it is still
491 * guaranteed to not be 0. So we can check weather or not this pass has generated commands
492 * after sync. Asserts will catch invalid usage . */
493 return manager_fingerprint_ != 0;
494 }
495};
496
497template<typename DrawCommandBufType> class Pass : public detail::PassBase<DrawCommandBufType> {
498 public:
500
501 private:
505 DrawCommandBufType draw_commands_buf_main_;
506
507 public:
508 Pass(const char *name)
509 : detail::PassBase<DrawCommandBufType>(name, draw_commands_buf_main_, sub_passes_main_) {};
510
511 void init()
512 {
513 this->manager_fingerprint_ = 0;
514 this->view_fingerprint_ = 0;
515 this->headers_.clear();
516 this->commands_.clear();
517 this->sub_passes_.clear();
518 this->draw_commands_buf_.clear();
519 this->is_empty_ = true;
520 }
521}; // namespace blender::draw
522
523} // namespace detail
524
526
527/* -------------------------------------------------------------------- */
530
534// using PassSimple = detail::Pass<DrawCommandBuf>;
535
543// using PassMain = detail::Pass<DrawMultiBuf>;
544
549class PassSortable : public PassMain {
550 friend Manager;
551
552 private:
554 Vector<float> sorting_values_;
555
556 bool sorted_ = false;
557
558 public:
559 PassSortable(const char *name_) : PassMain(name_) {};
560
561 void init()
562 {
563 sorting_values_.clear();
564 sorted_ = false;
566 }
567
568 PassMain::Sub &sub(const char *name, float sorting_value)
569 {
570 int64_t index = sub_passes_.append_and_get_index(
572 headers_.append({Type::SubPass, uint(index)});
573 /* Some sub-pass can also create sub-sub-passes (curve, point-clouds...) which will de-sync
574 * the `sub_passes_.size()` and `sorting_values_.size()`, making the `Header::index` not
575 * reusable for the sorting value in the `sort()` function. To fix this, we flood the
576 * `sorting_values_` to ensure the same index is valid for `sorting_values_` and
577 * `sub_passes_`. */
578 int64_t sorting_index;
579 do {
580 sorting_index = sorting_values_.append_and_get_index(sorting_value);
581 } while (sorting_index != index);
582 return sub_passes_[index];
583 }
584
585 std::string serialize(std::string line_prefix = "") const
586 {
587 if (sorted_ == false) {
588 const_cast<PassSortable *>(this)->sort();
589 }
590 return PassMain::serialize(line_prefix);
591 }
592
593 protected:
594 void sort()
595 {
596 if (sorted_ == false) {
597 std::sort(headers_.begin(), headers_.end(), [&](Header &a, Header &b) {
598 BLI_assert(a.type == Type::SubPass && b.type == Type::SubPass);
599 float a_val = sorting_values_[a.index];
600 float b_val = sorting_values_[b.index];
601 return a_val < b_val || (a_val == b_val && a.index < b.index);
602 });
603 sorted_ = true;
604 }
605 }
606};
607
609
610namespace detail {
611
612/* -------------------------------------------------------------------- */
615
616template<class T> inline bool PassBase<T>::is_empty() const
617{
618 if (!is_empty_) {
619 return false;
620 }
621
622 for (const command::Header &header : headers_) {
623 if (header.type != Type::SubPass) {
624 continue;
625 }
626 if (!sub_passes_[header.index].is_empty()) {
627 return false;
628 }
629 }
630
631 return true;
632}
633
635{
636 /* After render commands have been generated, the pass is read only.
637 * Call `init()` to be able modify it again. */
638 BLI_assert_msg(this->has_generated_commands() == false, "Command added after submission");
639 int64_t index = commands_.append_and_get_index({});
640 headers_.append({type, uint(index)});
641
642 if (ELEM(type,
650 {
651 is_empty_ = false;
652 }
653
654 return commands_[index];
655}
656
657template<class T>
660 float depth,
661 uint8_t stencil)
662{
663 create_command(command::Type::Clear).clear = {uint8_t(planes), stencil, depth, color};
664}
665
666template<class T> inline void PassBase<T>::clear_multi(Span<float4> colors)
667{
668 create_command(command::Type::ClearMulti).clear_multi = {colors.data(),
669 static_cast<int>(colors.size())};
670}
671
672template<class T> inline gpu::Batch *PassBase<T>::procedural_batch_get(GPUPrimType primitive)
673{
674 switch (primitive) {
675 case GPU_PRIM_POINTS:
677 case GPU_PRIM_LINES:
679 case GPU_PRIM_TRIS:
683 default:
684 /* Add new one as needed. */
686 return nullptr;
687 }
688}
689
690template<class T> inline PassBase<T> &PassBase<T>::sub(const char *name)
691{
692 int64_t index = sub_passes_.append_and_get_index(
694 headers_.append({command::Type::SubPass, uint(index)});
695 return sub_passes_[index];
696}
697
698template<class T>
700{
701 GPU_debug_group_begin("warm_shader_specialization");
702 GPU_debug_group_begin(this->debug_name);
703
704 for (const command::Header &header : headers_) {
705 switch (header.type) {
706 default:
707 case Type::None:
708 break;
709 case Type::SubPass:
710 sub_passes_[header.index].warm_shader_specialization(state);
711 break;
713 break;
715 break;
717 commands_[header.index].shader_bind.execute(state);
718 break;
720 break;
722 break;
724 commands_[header.index].specialize_constant.execute(state);
725 break;
727 break;
729 break;
731 break;
733 break;
735 break;
737 break;
739 break;
741 break;
743 break;
745 break;
746 }
747 }
748
751}
752
754{
755 if (headers_.is_empty()) {
756 return;
757 }
758
760
761 for (const command::Header &header : headers_) {
762 switch (header.type) {
763 default:
764 case Type::None:
765 break;
766 case Type::SubPass:
767 sub_passes_[header.index].submit(state);
768 break;
770 commands_[header.index].framebuffer_bind.execute();
771 break;
773 commands_[header.index].subpass_transition.execute();
774 break;
776 commands_[header.index].shader_bind.execute(state);
777 break;
779 commands_[header.index].resource_bind.execute();
780 break;
782 commands_[header.index].push_constant.execute(state);
783 break;
785 commands_[header.index].specialize_constant.execute(state);
786 break;
788 commands_[header.index].draw.execute(state);
789 break;
791 commands_[header.index].draw_multi.execute(state);
792 break;
794 commands_[header.index].draw_indirect.execute(state);
795 break;
797 commands_[header.index].dispatch.execute(state);
798 break;
800 commands_[header.index].dispatch_indirect.execute(state);
801 break;
803 commands_[header.index].barrier.execute();
804 break;
806 commands_[header.index].clear.execute();
807 break;
809 commands_[header.index].clear_multi.execute();
810 break;
812 commands_[header.index].state_set.execute(state);
813 break;
815 commands_[header.index].stencil_set.execute();
816 break;
817 }
818 }
819
821}
822
823template<class T> std::string PassBase<T>::serialize(std::string line_prefix) const
824{
825 std::stringstream ss;
826 ss << line_prefix << "." << debug_name << std::endl;
827 line_prefix += " ";
828 for (const command::Header &header : headers_) {
829 switch (header.type) {
830 default:
831 case Type::None:
832 break;
833 case Type::SubPass:
834 ss << sub_passes_[header.index].serialize(line_prefix);
835 break;
837 ss << line_prefix << commands_[header.index].framebuffer_bind.serialize() << std::endl;
838 break;
840 ss << line_prefix << commands_[header.index].subpass_transition.serialize() << std::endl;
841 break;
842 case Type::ShaderBind:
843 ss << line_prefix << commands_[header.index].shader_bind.serialize() << std::endl;
844 break;
846 ss << line_prefix << commands_[header.index].resource_bind.serialize() << std::endl;
847 break;
849 ss << line_prefix << commands_[header.index].push_constant.serialize() << std::endl;
850 break;
851 case Type::Draw:
852 ss << line_prefix << commands_[header.index].draw.serialize() << std::endl;
853 break;
854 case Type::DrawMulti:
855 ss << commands_[header.index].draw_multi.serialize(line_prefix);
856 break;
858 ss << line_prefix << commands_[header.index].draw_indirect.serialize() << std::endl;
859 break;
860 case Type::Dispatch:
861 ss << line_prefix << commands_[header.index].dispatch.serialize() << std::endl;
862 break;
864 ss << line_prefix << commands_[header.index].dispatch_indirect.serialize() << std::endl;
865 break;
866 case Type::Barrier:
867 ss << line_prefix << commands_[header.index].barrier.serialize() << std::endl;
868 break;
869 case Type::Clear:
870 ss << line_prefix << commands_[header.index].clear.serialize() << std::endl;
871 break;
872 case Type::ClearMulti:
873 ss << line_prefix << commands_[header.index].clear_multi.serialize() << std::endl;
874 break;
875 case Type::StateSet:
876 ss << line_prefix << commands_[header.index].state_set.serialize() << std::endl;
877 break;
878 case Type::StencilSet:
879 ss << line_prefix << commands_[header.index].stencil_set.serialize() << std::endl;
880 break;
881 }
882 }
883 return ss.str();
884}
885
887
888/* -------------------------------------------------------------------- */
891
892template<class T>
893inline void PassBase<T>::draw(gpu::Batch *batch,
894 uint instance_len,
895 uint vertex_len,
896 uint vertex_first,
897 ResourceIndexRange res_index,
898 uint custom_id)
899{
900 if (instance_len == 0 || vertex_len == 0) {
901 return;
902 }
905 draw_commands_buf_.append_draw(headers_,
906 commands_,
907 batch,
908 instance_len,
909 vertex_len,
910 vertex_first,
911 res_index,
912 custom_id,
914 0);
915 is_empty_ = false;
916}
917
918template<class T>
919inline void PassBase<T>::draw(gpu::Batch *batch, ResourceIndexRange res_index, uint custom_id)
920{
921 this->draw(batch, -1, -1, -1, res_index, custom_id);
922}
923
924template<class T>
925inline void PassBase<T>::draw_expand(gpu::Batch *batch,
926 GPUPrimType primitive_type,
927 uint primitive_len,
928 uint instance_len,
929 uint vertex_len,
930 uint vertex_first,
931 ResourceIndexRange res_index,
932 uint custom_id)
933{
934 if (instance_len == 0 || vertex_len == 0 || primitive_len == 0) {
935 return;
936 }
938 draw_commands_buf_.append_draw(headers_,
939 commands_,
940 batch,
941 instance_len,
942 vertex_len,
943 vertex_first,
944 res_index,
945 custom_id,
946 primitive_type,
947 primitive_len);
948 is_empty_ = false;
949}
950
951template<class T>
952inline void PassBase<T>::draw_expand(gpu::Batch *batch,
953 GPUPrimType primitive_type,
954 uint primitive_len,
955 uint instance_len,
956 ResourceIndexRange res_index,
957 uint custom_id)
958{
959 this->draw_expand(
960 batch, primitive_type, primitive_len, instance_len, -1, -1, res_index, custom_id);
961}
962
963template<class T>
965 uint instance_len,
966 uint vertex_len,
967 uint vertex_first,
968 ResourceIndexRange res_index,
969 uint custom_id)
970{
971 this->draw(procedural_batch_get(primitive),
972 instance_len,
973 vertex_len,
974 vertex_first,
975 res_index,
976 custom_id);
977}
978
980
981/* -------------------------------------------------------------------- */
984
985template<class T>
986inline void PassBase<T>::draw_indirect(gpu::Batch *batch,
987 StorageBuffer<DrawCommand, true> &indirect_buffer,
988 ResourceIndex res_index)
989{
991 create_command(Type::DrawIndirect).draw_indirect = {batch, &indirect_buffer, res_index};
992}
993
994template<class T>
996 GPUPrimType primitive,
997 StorageBuffer<DrawCommand, true> &indirect_buffer,
998 ResourceIndex res_index)
999{
1000 this->draw_indirect(procedural_batch_get(primitive), indirect_buffer, res_index);
1001}
1002
1004
1005/* -------------------------------------------------------------------- */
1008
1009template<class T> inline void PassBase<T>::dispatch(int group_len)
1010{
1012 create_command(Type::Dispatch).dispatch = {int3(group_len, 1, 1)};
1013}
1014
1015template<class T> inline void PassBase<T>::dispatch(int2 group_len)
1016{
1018 create_command(Type::Dispatch).dispatch = {int3(group_len.x, group_len.y, 1)};
1019}
1020
1021template<class T> inline void PassBase<T>::dispatch(int3 group_len)
1022{
1024 create_command(Type::Dispatch).dispatch = {group_len};
1025}
1026
1027template<class T> inline void PassBase<T>::dispatch(int3 *group_len)
1028{
1030 create_command(Type::Dispatch).dispatch = {group_len};
1031}
1032
1033template<class T>
1035{
1037 create_command(Type::DispatchIndirect).dispatch_indirect = {&indirect_buffer};
1038}
1039
1041
1042/* -------------------------------------------------------------------- */
1045
1046template<class T> inline void PassBase<T>::clear_color(float4 color)
1047{
1048 this->clear(GPU_COLOR_BIT, color, 0.0f, 0);
1049}
1050
1051template<class T> inline void PassBase<T>::clear_depth(float depth)
1052{
1053 this->clear(GPU_DEPTH_BIT, float4(0.0f), depth, 0);
1054}
1055
1056template<class T> inline void PassBase<T>::clear_stencil(uint8_t stencil)
1057{
1058 this->clear(GPU_STENCIL_BIT, float4(0.0f), 0.0f, stencil);
1059}
1060
1061template<class T> inline void PassBase<T>::clear_depth_stencil(float depth, uint8_t stencil)
1062{
1063 this->clear(GPU_DEPTH_BIT | GPU_STENCIL_BIT, float4(0.0f), depth, stencil);
1064}
1065
1066template<class T>
1067inline void PassBase<T>::clear_color_depth_stencil(float4 color, float depth, uint8_t stencil)
1068{
1069 this->clear(GPU_DEPTH_BIT | GPU_STENCIL_BIT | GPU_COLOR_BIT, color, depth, stencil);
1070}
1071
1073
1074/* -------------------------------------------------------------------- */
1077
1078template<class T> inline void PassBase<T>::barrier(GPUBarrier type)
1079{
1080 create_command(Type::Barrier).barrier = {type};
1081}
1082
1084
1085/* -------------------------------------------------------------------- */
1088
1089template<class T> inline void PassBase<T>::state_set(DRWState state, int clip_plane_count)
1090{
1092 if (clip_plane_count > 0) {
1094 }
1095 /* Assumed to always be enabled. */
1097 create_command(Type::StateSet).state_set = {state, clip_plane_count};
1098}
1099
1100template<class T>
1101inline void PassBase<T>::state_stencil(uint8_t write_mask, uint8_t reference, uint8_t compare_mask)
1102{
1103 create_command(Type::StencilSet).stencil_set = {write_mask, compare_mask, reference};
1104}
1105
1106template<class T> inline void PassBase<T>::shader_set(gpu::Shader *shader)
1107{
1108 shader_ = shader;
1109 create_command(Type::ShaderBind).shader_bind = {shader};
1110}
1111
1112template<class T> inline void PassBase<T>::framebuffer_set(gpu::FrameBuffer **framebuffer)
1113{
1114 create_command(Type::FramebufferBind).framebuffer_bind = {framebuffer};
1115}
1116
1117template<class T>
1119 Span<GPUAttachmentState> color_attachments)
1120{
1121 uint8_t color_states[8] = {GPU_ATTACHMENT_IGNORE};
1122 for (auto i : color_attachments.index_range()) {
1123 color_states[i] = uint8_t(color_attachments[i]);
1124 }
1125 create_command(Type::SubPassTransition).subpass_transition = {uint8_t(depth_attachment),
1126 {color_states[0],
1127 color_states[1],
1128 color_states[2],
1129 color_states[3],
1130 color_states[4],
1131 color_states[5],
1132 color_states[6],
1133 color_states[7]}};
1134}
1135
1136template<class T>
1137inline void PassBase<T>::material_set(Manager &manager,
1138 GPUMaterial *material,
1139 bool deferred_texture_loading)
1140{
1141 GPUPass *gpupass = GPU_material_get_pass(material);
1143
1144 /* Bind all textures needed by the material. */
1145 ListBase textures = GPU_material_textures(material);
1147 if (tex->ima) {
1148 /* Image */
1149 const bool use_tile_mapping = tex->tiled_mapping_name[0];
1150 ImageUser *iuser = tex->iuser_available ? &tex->iuser : nullptr;
1151
1152 ImageGPUTextures gputex;
1153 if (deferred_texture_loading) {
1154 gputex = BKE_image_get_gpu_material_texture_try(tex->ima, iuser, use_tile_mapping);
1155 }
1156 else {
1157 gputex = BKE_image_get_gpu_material_texture(tex->ima, iuser, use_tile_mapping);
1158 }
1159
1160 if (*gputex.texture == nullptr) {
1161 /* Texture not yet loaded. Register a reference inside the draw pass.
1162 * The texture will be acquired once it is created. */
1163 bind_texture(tex->sampler_name, gputex.texture, tex->sampler_state);
1164 if (gputex.tile_mapping) {
1165 bind_texture(tex->tiled_mapping_name, gputex.tile_mapping, tex->sampler_state);
1166 }
1167 }
1168 else {
1169 /* Texture is loaded. Acquire. */
1170 manager.acquire_texture(*gputex.texture);
1171 bind_texture(tex->sampler_name, *gputex.texture, tex->sampler_state);
1172 if (gputex.tile_mapping) {
1173 manager.acquire_texture(*gputex.tile_mapping);
1174 bind_texture(tex->tiled_mapping_name, *gputex.tile_mapping, tex->sampler_state);
1175 }
1176 }
1177 }
1178 else if (tex->colorband) {
1179 /* Color Ramp */
1180 bind_texture(tex->sampler_name, *tex->colorband);
1181 }
1182 else if (tex->sky) {
1183 /* Sky */
1184 bind_texture(tex->sampler_name, *tex->sky, tex->sampler_state);
1185 }
1186 }
1187
1189 if (ubo != nullptr) {
1191 }
1192}
1193
1195
1196/* -------------------------------------------------------------------- */
1199
1200template<class T> inline int PassBase<T>::push_constant_offset(const char *name)
1201{
1203}
1204
1205template<class T> inline void PassBase<T>::bind_ssbo(const char *name, gpu::StorageBuf *buffer)
1206{
1207 BLI_assert(buffer != nullptr);
1209}
1210
1211template<class T> inline void PassBase<T>::bind_ssbo(const char *name, gpu::UniformBuf *buffer)
1212{
1213 BLI_assert(buffer != nullptr);
1215}
1216
1217template<class T> inline void PassBase<T>::bind_ssbo(const char *name, gpu::UniformBuf **buffer)
1218{
1219 BLI_assert(buffer != nullptr);
1221}
1222
1223template<class T> inline void PassBase<T>::bind_ssbo(const char *name, gpu::VertBuf *buffer)
1224{
1225 BLI_assert(buffer != nullptr);
1227}
1228
1229template<class T> inline void PassBase<T>::bind_ssbo(const char *name, gpu::VertBuf **buffer)
1230{
1231 BLI_assert(buffer != nullptr);
1233}
1234
1235template<class T> inline void PassBase<T>::bind_ssbo(const char *name, gpu::VertBufPtr &buffer)
1236{
1237 BLI_assert(buffer.get() != nullptr);
1238 this->bind_ssbo(GPU_shader_get_ssbo_binding(shader_, name), buffer.get());
1239}
1240
1241template<class T> inline void PassBase<T>::bind_ssbo(const char *name, gpu::IndexBuf *buffer)
1242{
1243 BLI_assert(buffer != nullptr);
1245}
1246
1247template<class T> inline void PassBase<T>::bind_ssbo(const char *name, gpu::IndexBuf **buffer)
1248{
1249 BLI_assert(buffer != nullptr);
1251}
1252
1253template<class T> inline void PassBase<T>::bind_ubo(const char *name, gpu::UniformBuf *buffer)
1254{
1255 BLI_assert(buffer != nullptr);
1257}
1258
1259template<class T>
1267
1268template<class T> inline void PassBase<T>::bind_texture(const char *name, gpu::VertBuf *buffer)
1269{
1270 BLI_assert(buffer != nullptr);
1272}
1273
1274template<class T> inline void PassBase<T>::bind_texture(const char *name, gpu::VertBuf **buffer)
1275{
1276 BLI_assert(buffer != nullptr);
1278}
1279
1280template<class T> inline void PassBase<T>::bind_texture(const char *name, gpu::VertBufPtr &buffer)
1281{
1282 BLI_assert(buffer.get() != nullptr);
1284}
1285
1286template<class T> inline void PassBase<T>::bind_image(const char *name, gpu::Texture *image)
1287{
1288 BLI_assert(image != nullptr);
1290}
1291
1292template<class T> inline void PassBase<T>::bind_ssbo(int slot, gpu::StorageBuf *buffer)
1293{
1294 BLI_assert(buffer != nullptr);
1295 create_command(Type::ResourceBind).resource_bind = {slot, buffer};
1296}
1297
1298template<class T> inline void PassBase<T>::bind_ssbo(int slot, gpu::UniformBuf *buffer)
1299{
1300 BLI_assert(buffer != nullptr);
1301 create_command(Type::ResourceBind).resource_bind = {
1303}
1304
1305template<class T> inline void PassBase<T>::bind_ssbo(int slot, gpu::UniformBuf **buffer)
1306{
1307 BLI_assert(buffer != nullptr);
1308 create_command(Type::ResourceBind).resource_bind = {
1310}
1311
1312template<class T> inline void PassBase<T>::bind_ssbo(int slot, gpu::VertBuf *buffer)
1313{
1314 BLI_assert(buffer != nullptr);
1315 create_command(Type::ResourceBind).resource_bind = {
1317}
1318
1319template<class T> inline void PassBase<T>::bind_ssbo(int slot, gpu::VertBuf **buffer)
1320{
1321 BLI_assert(buffer != nullptr);
1322 create_command(Type::ResourceBind).resource_bind = {
1324}
1325
1326template<class T> inline void PassBase<T>::bind_ssbo(int slot, gpu::VertBufPtr &buffer)
1327{
1328 BLI_assert(buffer.get() != nullptr);
1329 create_command(Type::ResourceBind).resource_bind = {
1330 slot, buffer.get(), ResourceBind::Type::VertexAsStorageBuf};
1331}
1332
1333template<class T> inline void PassBase<T>::bind_ssbo(int slot, gpu::IndexBuf *buffer)
1334{
1335 BLI_assert(buffer != nullptr);
1336 create_command(Type::ResourceBind).resource_bind = {
1338}
1339
1340template<class T> inline void PassBase<T>::bind_ssbo(int slot, gpu::IndexBuf **buffer)
1341{
1342 BLI_assert(buffer != nullptr);
1343 create_command(Type::ResourceBind).resource_bind = {
1345}
1346
1347template<class T> inline void PassBase<T>::bind_ubo(int slot, gpu::UniformBuf *buffer)
1348{
1349 BLI_assert(buffer != nullptr);
1350 create_command(Type::ResourceBind).resource_bind = {slot, buffer};
1351}
1352
1353template<class T>
1355{
1356 BLI_assert(texture != nullptr);
1357 create_command(Type::ResourceBind).resource_bind = {slot, texture, state};
1358}
1359
1360template<class T> inline void PassBase<T>::bind_texture(int slot, gpu::VertBuf *buffer)
1361{
1362 BLI_assert(buffer != nullptr);
1363 create_command(Type::ResourceBind).resource_bind = {slot, buffer};
1364}
1365
1366template<class T> inline void PassBase<T>::bind_texture(int slot, gpu::VertBuf **buffer)
1367{
1368 BLI_assert(buffer != nullptr);
1369 create_command(Type::ResourceBind).resource_bind = {slot, buffer};
1370}
1371
1372template<class T> inline void PassBase<T>::bind_texture(int slot, gpu::VertBufPtr &buffer)
1373{
1374 BLI_assert(buffer.get() != nullptr);
1375 create_command(Type::ResourceBind).resource_bind = {slot, buffer.get()};
1376}
1377
1378template<class T> inline void PassBase<T>::bind_image(int slot, gpu::Texture *image)
1379{
1380 BLI_assert(image != nullptr);
1381 create_command(Type::ResourceBind).resource_bind = {slot, as_image(image)};
1382}
1383
1384template<class T> inline void PassBase<T>::bind_ssbo(const char *name, gpu::StorageBuf **buffer)
1385{
1386 BLI_assert(buffer != nullptr);
1388}
1389
1390template<class T> inline void PassBase<T>::bind_ubo(const char *name, gpu::UniformBuf **buffer)
1391{
1392 BLI_assert(buffer != nullptr);
1394}
1395
1396template<class T>
1404
1405template<class T> inline void PassBase<T>::bind_image(const char *name, gpu::Texture **image)
1406{
1407 BLI_assert(image != nullptr);
1409}
1410
1411template<class T> inline void PassBase<T>::bind_ssbo(int slot, gpu::StorageBuf **buffer)
1412{
1413
1414 BLI_assert(buffer != nullptr);
1415 create_command(Type::ResourceBind).resource_bind = {slot, buffer};
1416}
1417
1418template<class T> inline void PassBase<T>::bind_ubo(int slot, gpu::UniformBuf **buffer)
1419{
1420 BLI_assert(buffer != nullptr);
1421 create_command(Type::ResourceBind).resource_bind = {slot, buffer};
1422}
1423
1424template<class T>
1426{
1427 BLI_assert(texture != nullptr);
1428 create_command(Type::ResourceBind).resource_bind = {slot, texture, state};
1429}
1430
1431template<class T> inline void PassBase<T>::bind_image(int slot, gpu::Texture **image)
1432{
1433 BLI_assert(image != nullptr);
1434 create_command(Type::ResourceBind).resource_bind = {slot, as_image(image)};
1435}
1436
1438
1439/* -------------------------------------------------------------------- */
1442
1443template<class T> inline void PassBase<T>::push_constant(const char *name, const float &data)
1444{
1446}
1447
1448template<class T> inline void PassBase<T>::push_constant(const char *name, const float2 &data)
1449{
1451}
1452
1453template<class T> inline void PassBase<T>::push_constant(const char *name, const float3 &data)
1454{
1456}
1457
1458template<class T> inline void PassBase<T>::push_constant(const char *name, const float4 &data)
1459{
1461}
1462
1463template<class T> inline void PassBase<T>::push_constant(const char *name, const int &data)
1464{
1466}
1467
1468template<class T> inline void PassBase<T>::push_constant(const char *name, const int2 &data)
1469{
1471}
1472
1473template<class T> inline void PassBase<T>::push_constant(const char *name, const int3 &data)
1474{
1476}
1477
1478template<class T> inline void PassBase<T>::push_constant(const char *name, const int4 &data)
1479{
1481}
1482
1483template<class T> inline void PassBase<T>::push_constant(const char *name, const bool &data)
1484{
1486}
1487
1488template<class T>
1489inline void PassBase<T>::push_constant(const char *name, const float *data, int array_len)
1490{
1491 create_command(Type::PushConstant).push_constant = {push_constant_offset(name), data, array_len};
1492}
1493
1494template<class T>
1495inline void PassBase<T>::push_constant(const char *name, const float2 *data, int array_len)
1496{
1497 create_command(Type::PushConstant).push_constant = {push_constant_offset(name), data, array_len};
1498}
1499
1500template<class T>
1501inline void PassBase<T>::push_constant(const char *name, const float3 *data, int array_len)
1502{
1503 create_command(Type::PushConstant).push_constant = {push_constant_offset(name), data, array_len};
1504}
1505
1506template<class T>
1507inline void PassBase<T>::push_constant(const char *name, const float4 *data, int array_len)
1508{
1509 create_command(Type::PushConstant).push_constant = {push_constant_offset(name), data, array_len};
1510}
1511
1512template<class T>
1513inline void PassBase<T>::push_constant(const char *name, const int *data, int array_len)
1514{
1515 create_command(Type::PushConstant).push_constant = {push_constant_offset(name), data, array_len};
1516}
1517
1518template<class T>
1519inline void PassBase<T>::push_constant(const char *name, const int2 *data, int array_len)
1520{
1521 create_command(Type::PushConstant).push_constant = {push_constant_offset(name), data, array_len};
1522}
1523
1524template<class T>
1525inline void PassBase<T>::push_constant(const char *name, const int3 *data, int array_len)
1526{
1527 create_command(Type::PushConstant).push_constant = {push_constant_offset(name), data, array_len};
1528}
1529
1530template<class T>
1531inline void PassBase<T>::push_constant(const char *name, const int4 *data, int array_len)
1532{
1533 create_command(Type::PushConstant).push_constant = {push_constant_offset(name), data, array_len};
1534}
1535
1536template<class T> inline void PassBase<T>::push_constant(const char *name, const float4x4 *data)
1537{
1539}
1540
1541template<class T> inline void PassBase<T>::push_constant(const char *name, const float4x4 &data)
1542{
1543 /* WORKAROUND: Push 3 consecutive commands to hold the 64 bytes of the float4x4.
1544 * This assumes that all commands are always stored in flat array of memory. */
1545 Undetermined commands[3];
1546
1547 PushConstant &cmd = commands[0].push_constant;
1549 cmd.array_len = 1;
1550 cmd.comp_len = 16;
1552 /* Copy overrides the next 2 commands. We append them as Type::None to not evaluate them. */
1553 *reinterpret_cast<float4x4 *>(&cmd.float4_value) = data;
1554
1555 create_command(Type::PushConstant) = commands[0];
1556 create_command(Type::None) = commands[1];
1557 create_command(Type::None) = commands[2];
1558}
1559
1561
1562/* -------------------------------------------------------------------- */
1565
1566template<class T>
1568 const char *constant_name,
1569 const int &constant_value)
1570{
1571 create_command(Type::SpecializeConstant).specialize_constant = {
1572 shader, GPU_shader_get_constant(shader, constant_name), constant_value};
1573}
1574
1575template<class T>
1577 const char *constant_name,
1578 const uint &constant_value)
1579{
1580 create_command(Type::SpecializeConstant).specialize_constant = {
1581 shader, GPU_shader_get_constant(shader, constant_name), constant_value};
1582}
1583
1584template<class T>
1586 const char *constant_name,
1587 const float &constant_value)
1588{
1589 create_command(Type::SpecializeConstant).specialize_constant = {
1590 shader, GPU_shader_get_constant(shader, constant_name), constant_value};
1591}
1592
1593template<class T>
1595 const char *constant_name,
1596 const bool &constant_value)
1597{
1598 create_command(Type::SpecializeConstant).specialize_constant = {
1599 shader, GPU_shader_get_constant(shader, constant_name), constant_value};
1600}
1601
1602template<class T>
1604 const char *constant_name,
1605 const int *constant_value)
1606{
1607 create_command(Type::SpecializeConstant).specialize_constant = {
1608 shader, GPU_shader_get_constant(shader, constant_name), constant_value};
1609}
1610
1611template<class T>
1613 const char *constant_name,
1614 const uint *constant_value)
1615{
1616 create_command(Type::SpecializeConstant).specialize_constant = {
1617 shader, GPU_shader_get_constant(shader, constant_name), constant_value};
1618}
1619
1620template<class T>
1622 const char *constant_name,
1623 const float *constant_value)
1624{
1625 create_command(Type::SpecializeConstant).specialize_constant = {
1626 shader, GPU_shader_get_constant(shader, constant_name), constant_value};
1627}
1628
1629template<class T>
1631 const char *constant_name,
1632 const bool *constant_value)
1633{
1634 create_command(Type::SpecializeConstant).specialize_constant = {
1635 shader, GPU_shader_get_constant(shader, constant_name), constant_value};
1636}
1637
1639
1640} // namespace detail
1641
1642} // namespace blender::draw
ImageGPUTextures BKE_image_get_gpu_material_texture_try(Image *image, ImageUser *iuser, const bool use_tile_mapping)
Definition image_gpu.cc:513
ImageGPUTextures BKE_image_get_gpu_material_texture(Image *image, ImageUser *iuser, const bool use_tile_mapping)
Definition image_gpu.cc:506
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
unsigned int uint
#define ELEM(...)
blender::gpu::Batch * GPU_batch_procedural_triangle_strips_get()
Definition gpu_batch.cc:525
blender::gpu::Batch * GPU_batch_procedural_lines_get()
Definition gpu_batch.cc:515
blender::gpu::Batch * GPU_batch_procedural_points_get()
Definition gpu_batch.cc:510
blender::gpu::Batch * GPU_batch_procedural_triangles_get()
Definition gpu_batch.cc:520
GPUAttachmentState
@ GPU_ATTACHMENT_IGNORE
void GPU_debug_group_end()
Definition gpu_debug.cc:33
void GPU_debug_group_begin(const char *name)
Definition gpu_debug.cc:22
GPUFrameBufferBits
@ GPU_DEPTH_BIT
@ GPU_STENCIL_BIT
@ GPU_COLOR_BIT
GPUPass * GPU_material_get_pass(GPUMaterial *material)
ListBase GPU_material_textures(GPUMaterial *material)
blender::gpu::UniformBuf * GPU_material_uniform_buffer_get(GPUMaterial *material)
blender::gpu::Shader * GPU_pass_shader_get(GPUPass *pass)
Definition gpu_pass.cc:175
GPUPrimType
@ GPU_PRIM_NONE
@ GPU_PRIM_LINES
@ GPU_PRIM_POINTS
@ GPU_PRIM_TRI_STRIP
@ GPU_PRIM_TRIS
int GPU_shader_get_ubo_binding(blender::gpu::Shader *shader, const char *name)
int GPU_shader_get_constant(blender::gpu::Shader *shader, const char *name)
int GPU_shader_get_sampler_binding(blender::gpu::Shader *shader, const char *name)
int GPU_shader_get_ssbo_binding(blender::gpu::Shader *shader, const char *name)
int GPU_shader_get_uniform(blender::gpu::Shader *shader, const char *name)
GPUBarrier
Definition GPU_state.hh:29
static constexpr int GPU_NODE_TREE_UBO_SLOT
#define U
BMesh const char void * data
long long int int64_t
unsigned long long int uint64_t
constexpr const T * data() const
Definition BLI_span.hh:215
constexpr int64_t size() const
Definition BLI_span.hh:252
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
void acquire_texture(gpu::Texture *texture)
std::string serialize(std::string line_prefix="") const
Definition draw_pass.hh:585
PassSortable(const char *name_)
Definition draw_pass.hh:559
PassMain::Sub & sub(const char *name, float sorting_value)
Definition draw_pass.hh:568
void clear_multi(Span< float4 > colors)
Definition draw_pass.hh:666
void bind_resources(U &resources)
Definition draw_pass.hh:449
void framebuffer_set(gpu::FrameBuffer **framebuffer)
friend std::ostream & operator<<(std::ostream &stream, const PassBase &pass)
Definition draw_pass.hh:459
void shader_set(gpu::Shader *shader)
void bind_texture(const char *name, gpu::Texture *texture, GPUSamplerState state=sampler_auto)
Vector< command::Header, 0 > headers_
Definition draw_pass.hh:137
void clear_stencil(uint8_t stencil)
void clear(GPUFrameBufferBits planes, float4 color, float depth, uint8_t stencil)
Definition draw_pass.hh:658
void clear_color(float4 color)
void warm_shader_specialization(command::RecordingState &state) const
Definition draw_pass.hh:699
void specialize_constant(gpu::Shader *shader, const char *name, const float &data)
void subpass_transition(GPUAttachmentState depth_attachment, Span< GPUAttachmentState > color_attachments)
void bind_image(const char *name, gpu::Texture *image)
void clear_depth_stencil(float depth, uint8_t stencil)
void draw_procedural(GPUPrimType primitive, uint instance_len, uint vertex_len, uint vertex_first=-1, ResourceIndexRange res_index={}, uint custom_id=0)
Definition draw_pass.hh:964
PassBase(const char *name, DrawCommandBufType &draw_command_buf, SubPassVector< PassBase< DrawCommandBufType > > &sub_passes, gpu::Shader *shader=nullptr)
Definition draw_pass.hh:157
SubPassVector< PassBase< DrawCommandBufType > > & sub_passes_
Definition draw_pass.hh:143
command::Undetermined & create_command(command::Type type)
Definition draw_pass.hh:634
PassBase< DrawCommandBufType > & sub(const char *name)
Definition draw_pass.hh:690
void dispatch(int group_len)
int push_constant_offset(const char *name)
void submit(command::RecordingState &state) const
Definition draw_pass.hh:753
void draw_procedural_indirect(GPUPrimType primitive, StorageBuffer< DrawCommand, true > &indirect_buffer, ResourceIndex res_index={0})
Definition draw_pass.hh:995
void draw_indirect(gpu::Batch *batch, StorageBuffer< DrawCommand, true > &indirect_buffer, ResourceIndex res_index={0})
Definition draw_pass.hh:986
void draw_expand(gpu::Batch *batch, GPUPrimType primitive_type, uint primitive_len, uint instance_len, uint vertex_len, uint vertex_first, ResourceIndexRange res_index={}, uint custom_id=0)
Definition draw_pass.hh:925
void state_set(DRWState state, int clip_plane_count=0)
void barrier(GPUBarrier type)
Vector< command::Undetermined, 0 > commands_
Definition draw_pass.hh:139
void draw(gpu::Batch *batch, uint instance_len=-1, uint vertex_len=-1, uint vertex_first=-1, ResourceIndexRange res_index={}, uint custom_id=0)
Definition draw_pass.hh:893
void state_stencil(uint8_t write_mask, uint8_t reference, uint8_t compare_mask)
void clear_color_depth_stencil(float4 color, float depth, uint8_t stencil)
void bind_ubo(const char *name, gpu::UniformBuf *buffer)
void material_set(Manager &manager, GPUMaterial *material, bool deferred_texture_loading=false)
std::string serialize(std::string line_prefix="") const
Definition draw_pass.hh:823
void push_constant(const char *name, const float &data)
void bind_ssbo(const char *name, gpu::StorageBuf *buffer)
gpu::Batch * procedural_batch_get(GPUPrimType primitive)
Definition draw_pass.hh:672
DrawCommandBufType & draw_commands_buf_
Definition draw_pass.hh:141
detail::PassBase< command::DrawCommandBuf > Sub
Definition draw_pass.hh:499
Pass(const char *name)
Definition draw_pass.hh:508
const T & operator[](int64_t index) const
Definition draw_pass.hh:116
DRWState
Definition draw_state.hh:25
@ DRW_STATE_CLIP_PLANES
Definition draw_state.hh:71
@ DRW_STATE_PROGRAM_POINT_SIZE
Definition draw_state.hh:74
struct @021025263243242147216143265077100330027142264337::@225245033123204053237120173316075113304004012000 batch
TEX_TEMPLATE DataVec texture(T, FltCoord, float=0.0f) RET
static ulong state[N]
#define T
static void clear(Message &msg)
Definition msgfmt.cc:213
draw::StorageBuffer< DrawCommand, true > DrawIndirectBuf
Definition draw_pass.hh:71
detail::Pass< command::DrawMultiBuf > PassMain
static Image * as_image(gpu::Texture *tex)
draw::StorageBuffer< DispatchCommand > DispatchIndirectBuf
Definition draw_pass.hh:70
std::unique_ptr< gpu::VertBuf, gpu::VertBufDeleter > VertBufPtr
VecBase< int32_t, 4 > int4
MatBase< float, 4, 4 > float4x4
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
VecBase< int32_t, 3 > int3
ListBaseWrapperTemplate< ListBase, T > ListBaseWrapper
VecBase< float, 3 > float3
const char * name
static constexpr GPUSamplerState internal_sampler()
blender::gpu::Texture ** tile_mapping
Definition BKE_image.hh:615
blender::gpu::Texture ** texture
Definition BKE_image.hh:614
enum blender::draw::command::PushConstant::Type type
i
Definition text_draw.cc:230