Blender V4.5
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
70class Manager;
71
72namespace command {
73class DrawCommandBuf;
74}
75
76/* -------------------------------------------------------------------- */
79
80namespace detail {
81
85template<typename T,
87 int64_t block_size = 16>
89 private:
91
92 public:
93 void clear()
94 {
95 blocks_.clear();
96 }
97
99 {
100 /* Do not go over the inline size so that existing members never move. */
101 if (blocks_.is_empty() || blocks_.last()->size() == block_size) {
102 blocks_.append(std::make_unique<Vector<T, block_size>>());
103 }
104 return blocks_.last()->append_and_get_index(std::move(elem)) +
105 (blocks_.size() - 1) * block_size;
106 }
107
109 {
110 return (*blocks_[index / block_size])[index % block_size];
111 }
112
113 const T &operator[](int64_t index) const
114 {
115 return (*blocks_[index / block_size])[index % block_size];
116 }
117};
118
122template<
124 typename DrawCommandBufType>
125class PassBase {
126 friend Manager;
127 friend DrawCommandBuf;
128
130 static constexpr GPUSamplerState sampler_auto = GPUSamplerState::internal_sampler();
131
132 protected:
138 DrawCommandBufType &draw_commands_buf_;
142 GPUShader *shader_;
143
146
147 bool is_empty_ = true;
148
149 public:
150 const char *debug_name;
151
153
154 PassBase(const char *name,
155 DrawCommandBufType &draw_command_buf,
157 GPUShader *shader = nullptr)
158 : draw_commands_buf_(draw_command_buf),
159 sub_passes_(sub_passes),
160 shader_(shader),
161 debug_name(name),
163
169 void init();
170
174 bool is_empty() const;
175
179 PassBase<DrawCommandBufType> &sub(const char *name);
180
191 void state_set(DRWState state, int clip_plane_count = 0);
192
197 void clear_depth(float depth);
198 void clear_stencil(uint8_t stencil);
199 void clear_depth_stencil(float depth, uint8_t stencil);
200 void clear_color_depth_stencil(float4 color, float depth, uint8_t stencil);
205 void clear_multi(Span<float4> colors);
206
219 void state_stencil(uint8_t write_mask, uint8_t reference, uint8_t compare_mask);
220
224 void shader_set(GPUShader *shader);
225
231 void framebuffer_set(GPUFrameBuffer **framebuffer);
232
238 void subpass_transition(GPUAttachmentState depth_attachment,
239 Span<GPUAttachmentState> color_attachments);
240
246 void material_set(Manager &manager,
247 GPUMaterial *material,
248 bool deferred_texture_loading = false);
249
255 void draw(gpu::Batch *batch,
256 uint instance_len = -1,
257 uint vertex_len = -1,
258 uint vertex_first = -1,
259 ResourceHandleRange handle = {0},
260 uint custom_id = 0);
261
266 void draw(gpu::Batch *batch, ResourceHandleRange handle, uint custom_id = 0);
267
272 void draw_procedural(GPUPrimType primitive,
273 uint instance_len,
274 uint vertex_len,
275 uint vertex_first = -1,
276 ResourceHandleRange handle = {0},
277 uint custom_id = 0);
278
292 void draw_expand(gpu::Batch *batch,
293 GPUPrimType primitive_type,
294 uint primitive_len,
295 uint instance_len,
296 uint vertex_len = -1,
297 uint vertex_first = -1,
298 ResourceHandleRange handle = {0},
299 uint custom_id = 0);
300
305 void draw_expand(gpu::Batch *batch,
306 GPUPrimType primitive_type,
307 uint primitive_len,
308 uint instance_len,
309 ResourceHandleRange handle = {0},
310 uint custom_id = 0);
311
316 void draw_indirect(gpu::Batch *batch,
317 StorageBuffer<DrawCommand, true> &indirect_buffer,
318 ResourceHandle handle = {0});
320 StorageBuffer<DrawCommand, true> &indirect_buffer,
321 ResourceHandle handle = {0});
322
326 void dispatch(int group_len);
327 void dispatch(int2 group_len);
328 void dispatch(int3 group_len);
329 void dispatch(int3 *group_len);
330 void dispatch(StorageBuffer<DispatchCommand> &indirect_buffer);
331
335 void barrier(eGPUBarrier type);
336
349 void bind_image(const char *name, GPUTexture *image);
350 void bind_image(const char *name, GPUTexture **image);
351 void bind_image(int slot, GPUTexture *image);
352 void bind_image(int slot, GPUTexture **image);
353 void bind_texture(const char *name, GPUTexture *texture, GPUSamplerState state = sampler_auto);
354 void bind_texture(const char *name, GPUTexture **texture, GPUSamplerState state = sampler_auto);
355 void bind_texture(const char *name, gpu::VertBuf *buffer);
356 void bind_texture(const char *name, gpu::VertBuf **buffer);
357 void bind_texture(int slot, GPUTexture *texture, GPUSamplerState state = sampler_auto);
358 void bind_texture(int slot, GPUTexture **texture, GPUSamplerState state = sampler_auto);
359 void bind_texture(int slot, gpu::VertBuf *buffer);
360 void bind_texture(int slot, gpu::VertBuf **buffer);
361 void bind_ssbo(const char *name, GPUStorageBuf *buffer);
362 void bind_ssbo(const char *name, GPUStorageBuf **buffer);
363 void bind_ssbo(int slot, GPUStorageBuf *buffer);
364 void bind_ssbo(int slot, GPUStorageBuf **buffer);
365 void bind_ssbo(const char *name, GPUUniformBuf *buffer);
366 void bind_ssbo(const char *name, GPUUniformBuf **buffer);
367 void bind_ssbo(int slot, GPUUniformBuf *buffer);
368 void bind_ssbo(int slot, GPUUniformBuf **buffer);
369 void bind_ssbo(const char *name, gpu::VertBuf *buffer);
370 void bind_ssbo(const char *name, gpu::VertBuf **buffer);
371 void bind_ssbo(int slot, gpu::VertBuf *buffer);
372 void bind_ssbo(int slot, gpu::VertBuf **buffer);
373 void bind_ssbo(const char *name, gpu::IndexBuf *buffer);
374 void bind_ssbo(const char *name, gpu::IndexBuf **buffer);
375 void bind_ssbo(int slot, gpu::IndexBuf *buffer);
376 void bind_ssbo(int slot, gpu::IndexBuf **buffer);
377 void bind_ubo(const char *name, GPUUniformBuf *buffer);
378 void bind_ubo(const char *name, GPUUniformBuf **buffer);
379 void bind_ubo(int slot, GPUUniformBuf *buffer);
380 void bind_ubo(int slot, GPUUniformBuf **buffer);
381
393 void push_constant(const char *name, const float &data);
394 void push_constant(const char *name, const float2 &data);
395 void push_constant(const char *name, const float3 &data);
396 void push_constant(const char *name, const float4 &data);
397 void push_constant(const char *name, const int &data);
398 void push_constant(const char *name, const int2 &data);
399 void push_constant(const char *name, const int3 &data);
400 void push_constant(const char *name, const int4 &data);
401 void push_constant(const char *name, const bool &data);
402 void push_constant(const char *name, const float4x4 &data);
403 void push_constant(const char *name, const float *data, int array_len = 1);
404 void push_constant(const char *name, const float2 *data, int array_len = 1);
405 void push_constant(const char *name, const float3 *data, int array_len = 1);
406 void push_constant(const char *name, const float4 *data, int array_len = 1);
407 void push_constant(const char *name, const int *data, int array_len = 1);
408 void push_constant(const char *name, const int2 *data, int array_len = 1);
409 void push_constant(const char *name, const int3 *data, int array_len = 1);
410 void push_constant(const char *name, const int4 *data, int array_len = 1);
411 void push_constant(const char *name, const float4x4 *data);
412
425 void specialize_constant(GPUShader *shader, const char *name, const float &data);
426 void specialize_constant(GPUShader *shader, const char *name, const int &data);
427 void specialize_constant(GPUShader *shader, const char *name, const uint &data);
428 void specialize_constant(GPUShader *shader, const char *name, const bool &data);
429 void specialize_constant(GPUShader *shader, const char *name, const float *data);
430 void specialize_constant(GPUShader *shader, const char *name, const int *data);
431 void specialize_constant(GPUShader *shader, const char *name, const uint *data);
432 void specialize_constant(GPUShader *shader, const char *name, const bool *data);
433
440 template<class U> void bind_resources(U &resources)
441 {
442 resources.bind_resources(*this);
443 }
444
448 std::string serialize(std::string line_prefix = "") const;
449
450 friend std::ostream &operator<<(std::ostream &stream, const PassBase &pass)
451 {
452 return stream << pass.serialize();
453 }
454
455 protected:
459
460 int push_constant_offset(const char *name);
461
462 void clear(eGPUFrameBufferBits planes, float4 color, float depth, uint8_t stencil);
463
464 gpu::Batch *procedural_batch_get(GPUPrimType primitive);
465
470
476
478
480 {
481 /* NOTE: Even though manager fingerprint is not enough to check for update, it is still
482 * guaranteed to not be 0. So we can check weather or not this pass has generated commands
483 * after sync. Asserts will catch invalid usage . */
484 return manager_fingerprint_ != 0;
485 }
486};
487
488template<typename DrawCommandBufType> class Pass : public detail::PassBase<DrawCommandBufType> {
489 public:
491
492 private:
496 DrawCommandBufType draw_commands_buf_main_;
497
498 public:
499 Pass(const char *name)
500 : detail::PassBase<DrawCommandBufType>(name, draw_commands_buf_main_, sub_passes_main_){};
501
502 void init()
503 {
504 this->manager_fingerprint_ = 0;
505 this->view_fingerprint_ = 0;
506 this->headers_.clear();
507 this->commands_.clear();
508 this->sub_passes_.clear();
509 this->draw_commands_buf_.clear();
510 this->is_empty_ = true;
511 }
512}; // namespace blender::draw
513
514} // namespace detail
515
517
518/* -------------------------------------------------------------------- */
521
525// using PassSimple = detail::Pass<DrawCommandBuf>;
526
534// using PassMain = detail::Pass<DrawMultiBuf>;
535
540class PassSortable : public PassMain {
541 friend Manager;
542
543 private:
545 Vector<float> sorting_values_;
546
547 bool sorted_ = false;
548
549 public:
550 PassSortable(const char *name_) : PassMain(name_){};
551
552 void init()
553 {
554 sorting_values_.clear();
555 sorted_ = false;
557 }
558
559 PassMain::Sub &sub(const char *name, float sorting_value)
560 {
561 int64_t index = sub_passes_.append_and_get_index(
563 headers_.append({Type::SubPass, uint(index)});
564 /* Some sub-pass can also create sub-sub-passes (curve, point-clouds...) which will de-sync
565 * the `sub_passes_.size()` and `sorting_values_.size()`, making the `Header::index` not
566 * reusable for the sorting value in the `sort()` function. To fix this, we flood the
567 * `sorting_values_` to ensure the same index is valid for `sorting_values_` and
568 * `sub_passes_`. */
569 int64_t sorting_index;
570 do {
571 sorting_index = sorting_values_.append_and_get_index(sorting_value);
572 } while (sorting_index != index);
573 return sub_passes_[index];
574 }
575
576 std::string serialize(std::string line_prefix = "") const
577 {
578 if (sorted_ == false) {
579 const_cast<PassSortable *>(this)->sort();
580 }
581 return PassMain::serialize(line_prefix);
582 }
583
584 protected:
585 void sort()
586 {
587 if (sorted_ == false) {
588 std::sort(headers_.begin(), headers_.end(), [&](Header &a, Header &b) {
589 BLI_assert(a.type == Type::SubPass && b.type == Type::SubPass);
590 float a_val = sorting_values_[a.index];
591 float b_val = sorting_values_[b.index];
592 return a_val < b_val || (a_val == b_val && a.index < b.index);
593 });
594 sorted_ = true;
595 }
596 }
597};
598
600
601namespace detail {
602
603/* -------------------------------------------------------------------- */
606
607template<class T> inline bool PassBase<T>::is_empty() const
608{
609 if (!is_empty_) {
610 return false;
611 }
612
613 for (const command::Header &header : headers_) {
614 if (header.type != Type::SubPass) {
615 continue;
616 }
617 if (!sub_passes_[header.index].is_empty()) {
618 return false;
619 }
620 }
621
622 return true;
623}
624
626{
627 /* After render commands have been generated, the pass is read only.
628 * Call `init()` to be able modify it again. */
629 BLI_assert_msg(this->has_generated_commands() == false, "Command added after submission");
630 int64_t index = commands_.append_and_get_index({});
631 headers_.append({type, uint(index)});
632
633 if (ELEM(type,
641 {
642 is_empty_ = false;
643 }
644
645 return commands_[index];
646}
647
648template<class T>
651 float depth,
652 uint8_t stencil)
653{
654 create_command(command::Type::Clear).clear = {uint8_t(planes), stencil, depth, color};
655}
656
657template<class T> inline void PassBase<T>::clear_multi(Span<float4> colors)
658{
659 create_command(command::Type::ClearMulti).clear_multi = {colors.data(),
660 static_cast<int>(colors.size())};
661}
662
663template<class T> inline gpu::Batch *PassBase<T>::procedural_batch_get(GPUPrimType primitive)
664{
665 switch (primitive) {
666 case GPU_PRIM_POINTS:
668 case GPU_PRIM_LINES:
670 case GPU_PRIM_TRIS:
674 default:
675 /* Add new one as needed. */
677 return nullptr;
678 }
679}
680
681template<class T> inline PassBase<T> &PassBase<T>::sub(const char *name)
682{
683 int64_t index = sub_passes_.append_and_get_index(
685 headers_.append({command::Type::SubPass, uint(index)});
686 return sub_passes_[index];
687}
688
689template<class T>
691{
692 GPU_debug_group_begin("warm_shader_specialization");
693 GPU_debug_group_begin(this->debug_name);
694
695 for (const command::Header &header : headers_) {
696 switch (header.type) {
697 default:
698 case Type::None:
699 break;
700 case Type::SubPass:
701 sub_passes_[header.index].warm_shader_specialization(state);
702 break;
704 break;
706 break;
708 commands_[header.index].shader_bind.execute(state);
709 break;
711 break;
713 break;
715 commands_[header.index].specialize_constant.execute(state);
716 break;
718 break;
720 break;
722 break;
724 break;
726 break;
728 break;
730 break;
732 break;
734 break;
736 break;
737 }
738 }
739
742}
743
745{
746 if (headers_.is_empty()) {
747 return;
748 }
749
751
752 for (const command::Header &header : headers_) {
753 switch (header.type) {
754 default:
755 case Type::None:
756 break;
757 case Type::SubPass:
758 sub_passes_[header.index].submit(state);
759 break;
761 commands_[header.index].framebuffer_bind.execute();
762 break;
764 commands_[header.index].subpass_transition.execute();
765 break;
767 commands_[header.index].shader_bind.execute(state);
768 break;
770 commands_[header.index].resource_bind.execute();
771 break;
773 commands_[header.index].push_constant.execute(state);
774 break;
776 commands_[header.index].specialize_constant.execute(state);
777 break;
779 commands_[header.index].draw.execute(state);
780 break;
782 commands_[header.index].draw_multi.execute(state);
783 break;
785 commands_[header.index].draw_indirect.execute(state);
786 break;
788 commands_[header.index].dispatch.execute(state);
789 break;
791 commands_[header.index].dispatch_indirect.execute(state);
792 break;
794 commands_[header.index].barrier.execute();
795 break;
797 commands_[header.index].clear.execute();
798 break;
800 commands_[header.index].clear_multi.execute();
801 break;
803 commands_[header.index].state_set.execute(state);
804 break;
806 commands_[header.index].stencil_set.execute();
807 break;
808 }
809 }
810
812}
813
814template<class T> std::string PassBase<T>::serialize(std::string line_prefix) const
815{
816 std::stringstream ss;
817 ss << line_prefix << "." << debug_name << std::endl;
818 line_prefix += " ";
819 for (const command::Header &header : headers_) {
820 switch (header.type) {
821 default:
822 case Type::None:
823 break;
824 case Type::SubPass:
825 ss << sub_passes_[header.index].serialize(line_prefix);
826 break;
828 ss << line_prefix << commands_[header.index].framebuffer_bind.serialize() << std::endl;
829 break;
831 ss << line_prefix << commands_[header.index].subpass_transition.serialize() << std::endl;
832 break;
833 case Type::ShaderBind:
834 ss << line_prefix << commands_[header.index].shader_bind.serialize() << std::endl;
835 break;
837 ss << line_prefix << commands_[header.index].resource_bind.serialize() << std::endl;
838 break;
840 ss << line_prefix << commands_[header.index].push_constant.serialize() << std::endl;
841 break;
842 case Type::Draw:
843 ss << line_prefix << commands_[header.index].draw.serialize() << std::endl;
844 break;
845 case Type::DrawMulti:
846 ss << commands_[header.index].draw_multi.serialize(line_prefix);
847 break;
849 ss << line_prefix << commands_[header.index].draw_indirect.serialize() << std::endl;
850 break;
851 case Type::Dispatch:
852 ss << line_prefix << commands_[header.index].dispatch.serialize() << std::endl;
853 break;
855 ss << line_prefix << commands_[header.index].dispatch_indirect.serialize() << std::endl;
856 break;
857 case Type::Barrier:
858 ss << line_prefix << commands_[header.index].barrier.serialize() << std::endl;
859 break;
860 case Type::Clear:
861 ss << line_prefix << commands_[header.index].clear.serialize() << std::endl;
862 break;
863 case Type::ClearMulti:
864 ss << line_prefix << commands_[header.index].clear_multi.serialize() << std::endl;
865 break;
866 case Type::StateSet:
867 ss << line_prefix << commands_[header.index].state_set.serialize() << std::endl;
868 break;
869 case Type::StencilSet:
870 ss << line_prefix << commands_[header.index].stencil_set.serialize() << std::endl;
871 break;
872 }
873 }
874 return ss.str();
875}
876
878
879/* -------------------------------------------------------------------- */
882
883template<class T>
884inline void PassBase<T>::draw(gpu::Batch *batch,
885 uint instance_len,
886 uint vertex_len,
887 uint vertex_first,
888 ResourceHandleRange handle,
889 uint custom_id)
890{
891 if (instance_len == 0 || vertex_len == 0) {
892 return;
893 }
895 draw_commands_buf_.append_draw(headers_,
896 commands_,
897 batch,
898 instance_len,
899 vertex_len,
900 vertex_first,
901 handle,
902 custom_id,
904 0);
905 is_empty_ = false;
906}
907
908template<class T>
909inline void PassBase<T>::draw(gpu::Batch *batch, ResourceHandleRange handle, uint custom_id)
910{
911 this->draw(batch, -1, -1, -1, handle, custom_id);
912}
913
914template<class T>
915inline void PassBase<T>::draw_expand(gpu::Batch *batch,
916 GPUPrimType primitive_type,
917 uint primitive_len,
918 uint instance_len,
919 uint vertex_len,
920 uint vertex_first,
921 ResourceHandleRange handle,
922 uint custom_id)
923{
924 if (instance_len == 0 || vertex_len == 0 || primitive_len == 0) {
925 return;
926 }
928 draw_commands_buf_.append_draw(headers_,
929 commands_,
930 batch,
931 instance_len,
932 vertex_len,
933 vertex_first,
934 handle,
935 custom_id,
936 primitive_type,
937 primitive_len);
938 is_empty_ = false;
939}
940
941template<class T>
942inline void PassBase<T>::draw_expand(gpu::Batch *batch,
943 GPUPrimType primitive_type,
944 uint primitive_len,
945 uint instance_len,
946 ResourceHandleRange handle,
947 uint custom_id)
948{
949 this->draw_expand(batch, primitive_type, primitive_len, instance_len, -1, -1, handle, custom_id);
950}
951
952template<class T>
954 uint instance_len,
955 uint vertex_len,
956 uint vertex_first,
957 ResourceHandleRange handle,
958 uint custom_id)
959{
960 this->draw(
961 procedural_batch_get(primitive), instance_len, vertex_len, vertex_first, handle, custom_id);
962}
963
965
966/* -------------------------------------------------------------------- */
969
970template<class T>
971inline void PassBase<T>::draw_indirect(gpu::Batch *batch,
972 StorageBuffer<DrawCommand, true> &indirect_buffer,
973 ResourceHandle handle)
974{
976 create_command(Type::DrawIndirect).draw_indirect = {batch, &indirect_buffer, handle};
977}
978
979template<class T>
981 GPUPrimType primitive,
982 StorageBuffer<DrawCommand, true> &indirect_buffer,
983 ResourceHandle handle)
984{
985 this->draw_indirect(procedural_batch_get(primitive), indirect_buffer, handle);
986}
987
989
990/* -------------------------------------------------------------------- */
993
994template<class T> inline void PassBase<T>::dispatch(int group_len)
995{
997 create_command(Type::Dispatch).dispatch = {int3(group_len, 1, 1)};
998}
999
1000template<class T> inline void PassBase<T>::dispatch(int2 group_len)
1001{
1003 create_command(Type::Dispatch).dispatch = {int3(group_len.x, group_len.y, 1)};
1004}
1005
1006template<class T> inline void PassBase<T>::dispatch(int3 group_len)
1007{
1009 create_command(Type::Dispatch).dispatch = {group_len};
1010}
1011
1012template<class T> inline void PassBase<T>::dispatch(int3 *group_len)
1013{
1015 create_command(Type::Dispatch).dispatch = {group_len};
1016}
1017
1018template<class T>
1020{
1022 create_command(Type::DispatchIndirect).dispatch_indirect = {&indirect_buffer};
1023}
1024
1026
1027/* -------------------------------------------------------------------- */
1030
1031template<class T> inline void PassBase<T>::clear_color(float4 color)
1032{
1033 this->clear(GPU_COLOR_BIT, color, 0.0f, 0);
1034}
1035
1036template<class T> inline void PassBase<T>::clear_depth(float depth)
1037{
1038 this->clear(GPU_DEPTH_BIT, float4(0.0f), depth, 0);
1039}
1040
1041template<class T> inline void PassBase<T>::clear_stencil(uint8_t stencil)
1042{
1043 this->clear(GPU_STENCIL_BIT, float4(0.0f), 0.0f, stencil);
1044}
1045
1046template<class T> inline void PassBase<T>::clear_depth_stencil(float depth, uint8_t stencil)
1047{
1048 this->clear(GPU_DEPTH_BIT | GPU_STENCIL_BIT, float4(0.0f), depth, stencil);
1049}
1050
1051template<class T>
1052inline void PassBase<T>::clear_color_depth_stencil(float4 color, float depth, uint8_t stencil)
1053{
1054 this->clear(GPU_DEPTH_BIT | GPU_STENCIL_BIT | GPU_COLOR_BIT, color, depth, stencil);
1055}
1056
1058
1059/* -------------------------------------------------------------------- */
1062
1063template<class T> inline void PassBase<T>::barrier(eGPUBarrier type)
1064{
1065 create_command(Type::Barrier).barrier = {type};
1066}
1067
1069
1070/* -------------------------------------------------------------------- */
1073
1074template<class T> inline void PassBase<T>::state_set(DRWState state, int clip_plane_count)
1075{
1077 if (clip_plane_count > 0) {
1079 }
1080 /* Assumed to always be enabled. */
1082 create_command(Type::StateSet).state_set = {state, clip_plane_count};
1083}
1084
1085template<class T>
1086inline void PassBase<T>::state_stencil(uint8_t write_mask, uint8_t reference, uint8_t compare_mask)
1087{
1088 create_command(Type::StencilSet).stencil_set = {write_mask, compare_mask, reference};
1089}
1090
1091template<class T> inline void PassBase<T>::shader_set(GPUShader *shader)
1092{
1093 shader_ = shader;
1094 create_command(Type::ShaderBind).shader_bind = {shader};
1095}
1096
1097template<class T> inline void PassBase<T>::framebuffer_set(GPUFrameBuffer **framebuffer)
1098{
1099 create_command(Type::FramebufferBind).framebuffer_bind = {framebuffer};
1100}
1101
1102template<class T>
1104 Span<GPUAttachmentState> color_attachments)
1105{
1106 uint8_t color_states[8] = {GPU_ATTACHMENT_IGNORE};
1107 for (auto i : color_attachments.index_range()) {
1108 color_states[i] = uint8_t(color_attachments[i]);
1109 }
1110 create_command(Type::SubPassTransition).subpass_transition = {uint8_t(depth_attachment),
1111 {color_states[0],
1112 color_states[1],
1113 color_states[2],
1114 color_states[3],
1115 color_states[4],
1116 color_states[5],
1117 color_states[6],
1118 color_states[7]}};
1119}
1120
1121template<class T>
1122inline void PassBase<T>::material_set(Manager &manager,
1123 GPUMaterial *material,
1124 bool deferred_texture_loading)
1125{
1126 GPUPass *gpupass = GPU_material_get_pass(material);
1128
1129 /* Bind all textures needed by the material. */
1130 ListBase textures = GPU_material_textures(material);
1132 if (tex->ima) {
1133 /* Image */
1134 const bool use_tile_mapping = tex->tiled_mapping_name[0];
1135 ImageUser *iuser = tex->iuser_available ? &tex->iuser : nullptr;
1136
1137 ImageGPUTextures gputex;
1138 if (deferred_texture_loading) {
1139 gputex = BKE_image_get_gpu_material_texture_try(tex->ima, iuser, use_tile_mapping);
1140 }
1141 else {
1142 gputex = BKE_image_get_gpu_material_texture(tex->ima, iuser, use_tile_mapping);
1143 }
1144
1145 if (*gputex.texture == nullptr) {
1146 /* Texture not yet loaded. Register a reference inside the draw pass.
1147 * The texture will be acquired once it is created. */
1148 bind_texture(tex->sampler_name, gputex.texture, tex->sampler_state);
1149 if (gputex.tile_mapping) {
1150 bind_texture(tex->tiled_mapping_name, gputex.tile_mapping, tex->sampler_state);
1151 }
1152 }
1153 else {
1154 /* Texture is loaded. Acquire. */
1155 manager.acquire_texture(*gputex.texture);
1156 bind_texture(tex->sampler_name, *gputex.texture, tex->sampler_state);
1157 if (gputex.tile_mapping) {
1158 manager.acquire_texture(*gputex.tile_mapping);
1159 bind_texture(tex->tiled_mapping_name, *gputex.tile_mapping, tex->sampler_state);
1160 }
1161 }
1162 }
1163 else if (tex->colorband) {
1164 /* Color Ramp */
1165 bind_texture(tex->sampler_name, *tex->colorband);
1166 }
1167 else if (tex->sky) {
1168 /* Sky */
1169 bind_texture(tex->sampler_name, *tex->sky, tex->sampler_state);
1170 }
1171 }
1172
1173 GPUUniformBuf *ubo = GPU_material_uniform_buffer_get(material);
1174 if (ubo != nullptr) {
1176 }
1177}
1178
1180
1181/* -------------------------------------------------------------------- */
1184
1185template<class T> inline int PassBase<T>::push_constant_offset(const char *name)
1186{
1187 return GPU_shader_get_uniform(shader_, name);
1188}
1189
1190template<class T> inline void PassBase<T>::bind_ssbo(const char *name, GPUStorageBuf *buffer)
1191{
1192 BLI_assert(buffer != nullptr);
1193 this->bind_ssbo(GPU_shader_get_ssbo_binding(shader_, name), buffer);
1194}
1195
1196template<class T> inline void PassBase<T>::bind_ssbo(const char *name, GPUUniformBuf *buffer)
1197{
1198 BLI_assert(buffer != nullptr);
1199 this->bind_ssbo(GPU_shader_get_ssbo_binding(shader_, name), buffer);
1200}
1201
1202template<class T> inline void PassBase<T>::bind_ssbo(const char *name, GPUUniformBuf **buffer)
1203{
1204 BLI_assert(buffer != nullptr);
1205 this->bind_ssbo(GPU_shader_get_ssbo_binding(shader_, name), buffer);
1206}
1207
1208template<class T> inline void PassBase<T>::bind_ssbo(const char *name, gpu::VertBuf *buffer)
1209{
1210 BLI_assert(buffer != nullptr);
1211 this->bind_ssbo(GPU_shader_get_ssbo_binding(shader_, name), buffer);
1212}
1213
1214template<class T> inline void PassBase<T>::bind_ssbo(const char *name, gpu::VertBuf **buffer)
1215{
1216 BLI_assert(buffer != nullptr);
1217 this->bind_ssbo(GPU_shader_get_ssbo_binding(shader_, name), buffer);
1218}
1219
1220template<class T> inline void PassBase<T>::bind_ssbo(const char *name, gpu::IndexBuf *buffer)
1221{
1222 BLI_assert(buffer != nullptr);
1223 this->bind_ssbo(GPU_shader_get_ssbo_binding(shader_, name), buffer);
1224}
1225
1226template<class T> inline void PassBase<T>::bind_ssbo(const char *name, gpu::IndexBuf **buffer)
1227{
1228 BLI_assert(buffer != nullptr);
1229 this->bind_ssbo(GPU_shader_get_ssbo_binding(shader_, name), buffer);
1230}
1231
1232template<class T> inline void PassBase<T>::bind_ubo(const char *name, GPUUniformBuf *buffer)
1233{
1234 BLI_assert(buffer != nullptr);
1235 this->bind_ubo(GPU_shader_get_ubo_binding(shader_, name), buffer);
1236}
1237
1238template<class T>
1239inline void PassBase<T>::bind_texture(const char *name, GPUTexture *texture, GPUSamplerState state)
1240{
1241 BLI_assert(texture != nullptr);
1243}
1244
1245template<class T> inline void PassBase<T>::bind_texture(const char *name, gpu::VertBuf *buffer)
1246{
1247 BLI_assert(buffer != nullptr);
1249}
1250
1251template<class T> inline void PassBase<T>::bind_texture(const char *name, gpu::VertBuf **buffer)
1252{
1253 BLI_assert(buffer != nullptr);
1255}
1256
1257template<class T> inline void PassBase<T>::bind_image(const char *name, GPUTexture *image)
1258{
1259 BLI_assert(image != nullptr);
1261}
1262
1263template<class T> inline void PassBase<T>::bind_ssbo(int slot, GPUStorageBuf *buffer)
1264{
1265 BLI_assert(buffer != nullptr);
1266 create_command(Type::ResourceBind).resource_bind = {slot, buffer};
1267}
1268
1269template<class T> inline void PassBase<T>::bind_ssbo(int slot, GPUUniformBuf *buffer)
1270{
1271 BLI_assert(buffer != nullptr);
1272 create_command(Type::ResourceBind).resource_bind = {
1274}
1275
1276template<class T> inline void PassBase<T>::bind_ssbo(int slot, GPUUniformBuf **buffer)
1277{
1278 BLI_assert(buffer != nullptr);
1279 create_command(Type::ResourceBind).resource_bind = {
1281}
1282
1283template<class T> inline void PassBase<T>::bind_ssbo(int slot, gpu::VertBuf *buffer)
1284{
1285 BLI_assert(buffer != nullptr);
1286 create_command(Type::ResourceBind).resource_bind = {
1288}
1289
1290template<class T> inline void PassBase<T>::bind_ssbo(int slot, gpu::VertBuf **buffer)
1291{
1292 BLI_assert(buffer != nullptr);
1293 create_command(Type::ResourceBind).resource_bind = {
1295}
1296
1297template<class T> inline void PassBase<T>::bind_ssbo(int slot, gpu::IndexBuf *buffer)
1298{
1299 BLI_assert(buffer != nullptr);
1300 create_command(Type::ResourceBind).resource_bind = {
1302}
1303
1304template<class T> inline void PassBase<T>::bind_ssbo(int slot, gpu::IndexBuf **buffer)
1305{
1306 BLI_assert(buffer != nullptr);
1307 create_command(Type::ResourceBind).resource_bind = {
1309}
1310
1311template<class T> inline void PassBase<T>::bind_ubo(int slot, GPUUniformBuf *buffer)
1312{
1313 BLI_assert(buffer != nullptr);
1314 create_command(Type::ResourceBind).resource_bind = {slot, buffer};
1315}
1316
1317template<class T>
1318inline void PassBase<T>::bind_texture(int slot, GPUTexture *texture, GPUSamplerState state)
1319{
1320 BLI_assert(texture != nullptr);
1321 create_command(Type::ResourceBind).resource_bind = {slot, texture, state};
1322}
1323
1324template<class T> inline void PassBase<T>::bind_texture(int slot, gpu::VertBuf *buffer)
1325{
1326 BLI_assert(buffer != nullptr);
1327 create_command(Type::ResourceBind).resource_bind = {slot, buffer};
1328}
1329
1330template<class T> inline void PassBase<T>::bind_texture(int slot, gpu::VertBuf **buffer)
1331{
1332 BLI_assert(buffer != nullptr);
1333 create_command(Type::ResourceBind).resource_bind = {slot, buffer};
1334}
1335
1336template<class T> inline void PassBase<T>::bind_image(int slot, GPUTexture *image)
1337{
1338 BLI_assert(image != nullptr);
1339 create_command(Type::ResourceBind).resource_bind = {slot, as_image(image)};
1340}
1341
1342template<class T> inline void PassBase<T>::bind_ssbo(const char *name, GPUStorageBuf **buffer)
1343{
1344 BLI_assert(buffer != nullptr);
1345 this->bind_ssbo(GPU_shader_get_ssbo_binding(shader_, name), buffer);
1346}
1347
1348template<class T> inline void PassBase<T>::bind_ubo(const char *name, GPUUniformBuf **buffer)
1349{
1350 BLI_assert(buffer != nullptr);
1351 this->bind_ubo(GPU_shader_get_ubo_binding(shader_, name), buffer);
1352}
1353
1354template<class T>
1355inline void PassBase<T>::bind_texture(const char *name,
1356 GPUTexture **texture,
1358{
1359 BLI_assert(texture != nullptr);
1361}
1362
1363template<class T> inline void PassBase<T>::bind_image(const char *name, GPUTexture **image)
1364{
1365 BLI_assert(image != nullptr);
1367}
1368
1369template<class T> inline void PassBase<T>::bind_ssbo(int slot, GPUStorageBuf **buffer)
1370{
1371
1372 BLI_assert(buffer != nullptr);
1373 create_command(Type::ResourceBind).resource_bind = {slot, buffer};
1374}
1375
1376template<class T> inline void PassBase<T>::bind_ubo(int slot, GPUUniformBuf **buffer)
1377{
1378 BLI_assert(buffer != nullptr);
1379 create_command(Type::ResourceBind).resource_bind = {slot, buffer};
1380}
1381
1382template<class T>
1383inline void PassBase<T>::bind_texture(int slot, GPUTexture **texture, GPUSamplerState state)
1384{
1385 BLI_assert(texture != nullptr);
1386 create_command(Type::ResourceBind).resource_bind = {slot, texture, state};
1387}
1388
1389template<class T> inline void PassBase<T>::bind_image(int slot, GPUTexture **image)
1390{
1391 BLI_assert(image != nullptr);
1392 create_command(Type::ResourceBind).resource_bind = {slot, as_image(image)};
1393}
1394
1396
1397/* -------------------------------------------------------------------- */
1400
1401template<class T> inline void PassBase<T>::push_constant(const char *name, const float &data)
1402{
1404}
1405
1406template<class T> inline void PassBase<T>::push_constant(const char *name, const float2 &data)
1407{
1409}
1410
1411template<class T> inline void PassBase<T>::push_constant(const char *name, const float3 &data)
1412{
1414}
1415
1416template<class T> inline void PassBase<T>::push_constant(const char *name, const float4 &data)
1417{
1419}
1420
1421template<class T> inline void PassBase<T>::push_constant(const char *name, const int &data)
1422{
1424}
1425
1426template<class T> inline void PassBase<T>::push_constant(const char *name, const int2 &data)
1427{
1429}
1430
1431template<class T> inline void PassBase<T>::push_constant(const char *name, const int3 &data)
1432{
1434}
1435
1436template<class T> inline void PassBase<T>::push_constant(const char *name, const int4 &data)
1437{
1439}
1440
1441template<class T> inline void PassBase<T>::push_constant(const char *name, const bool &data)
1442{
1444}
1445
1446template<class T>
1447inline void PassBase<T>::push_constant(const char *name, const float *data, int array_len)
1448{
1449 create_command(Type::PushConstant).push_constant = {push_constant_offset(name), data, array_len};
1450}
1451
1452template<class T>
1453inline void PassBase<T>::push_constant(const char *name, const float2 *data, int array_len)
1454{
1455 create_command(Type::PushConstant).push_constant = {push_constant_offset(name), data, array_len};
1456}
1457
1458template<class T>
1459inline void PassBase<T>::push_constant(const char *name, const float3 *data, int array_len)
1460{
1461 create_command(Type::PushConstant).push_constant = {push_constant_offset(name), data, array_len};
1462}
1463
1464template<class T>
1465inline void PassBase<T>::push_constant(const char *name, const float4 *data, int array_len)
1466{
1467 create_command(Type::PushConstant).push_constant = {push_constant_offset(name), data, array_len};
1468}
1469
1470template<class T>
1471inline void PassBase<T>::push_constant(const char *name, const int *data, int array_len)
1472{
1473 create_command(Type::PushConstant).push_constant = {push_constant_offset(name), data, array_len};
1474}
1475
1476template<class T>
1477inline void PassBase<T>::push_constant(const char *name, const int2 *data, int array_len)
1478{
1479 create_command(Type::PushConstant).push_constant = {push_constant_offset(name), data, array_len};
1480}
1481
1482template<class T>
1483inline void PassBase<T>::push_constant(const char *name, const int3 *data, int array_len)
1484{
1485 create_command(Type::PushConstant).push_constant = {push_constant_offset(name), data, array_len};
1486}
1487
1488template<class T>
1489inline void PassBase<T>::push_constant(const char *name, const int4 *data, int array_len)
1490{
1491 create_command(Type::PushConstant).push_constant = {push_constant_offset(name), data, array_len};
1492}
1493
1494template<class T> inline void PassBase<T>::push_constant(const char *name, const float4x4 *data)
1495{
1497}
1498
1499template<class T> inline void PassBase<T>::push_constant(const char *name, const float4x4 &data)
1500{
1501 /* WORKAROUND: Push 3 consecutive commands to hold the 64 bytes of the float4x4.
1502 * This assumes that all commands are always stored in flat array of memory. */
1503 Undetermined commands[3];
1504
1505 PushConstant &cmd = commands[0].push_constant;
1506 cmd.location = push_constant_offset(name);
1507 cmd.array_len = 1;
1508 cmd.comp_len = 16;
1510 /* Copy overrides the next 2 commands. We append them as Type::None to not evaluate them. */
1511 *reinterpret_cast<float4x4 *>(&cmd.float4_value) = data;
1512
1513 create_command(Type::PushConstant) = commands[0];
1514 create_command(Type::None) = commands[1];
1515 create_command(Type::None) = commands[2];
1516}
1517
1519
1520/* -------------------------------------------------------------------- */
1523
1524template<class T>
1525inline void PassBase<T>::specialize_constant(GPUShader *shader,
1526 const char *constant_name,
1527 const int &constant_value)
1528{
1529 create_command(Type::SpecializeConstant).specialize_constant = {
1530 shader, GPU_shader_get_constant(shader, constant_name), constant_value};
1531}
1532
1533template<class T>
1534inline void PassBase<T>::specialize_constant(GPUShader *shader,
1535 const char *constant_name,
1536 const uint &constant_value)
1537{
1538 create_command(Type::SpecializeConstant).specialize_constant = {
1539 shader, GPU_shader_get_constant(shader, constant_name), constant_value};
1540}
1541
1542template<class T>
1543inline void PassBase<T>::specialize_constant(GPUShader *shader,
1544 const char *constant_name,
1545 const float &constant_value)
1546{
1547 create_command(Type::SpecializeConstant).specialize_constant = {
1548 shader, GPU_shader_get_constant(shader, constant_name), constant_value};
1549}
1550
1551template<class T>
1552inline void PassBase<T>::specialize_constant(GPUShader *shader,
1553 const char *constant_name,
1554 const bool &constant_value)
1555{
1556 create_command(Type::SpecializeConstant).specialize_constant = {
1557 shader, GPU_shader_get_constant(shader, constant_name), constant_value};
1558}
1559
1560template<class T>
1561inline void PassBase<T>::specialize_constant(GPUShader *shader,
1562 const char *constant_name,
1563 const int *constant_value)
1564{
1565 create_command(Type::SpecializeConstant).specialize_constant = {
1566 shader, GPU_shader_get_constant(shader, constant_name), constant_value};
1567}
1568
1569template<class T>
1570inline void PassBase<T>::specialize_constant(GPUShader *shader,
1571 const char *constant_name,
1572 const uint *constant_value)
1573{
1574 create_command(Type::SpecializeConstant).specialize_constant = {
1575 shader, GPU_shader_get_constant(shader, constant_name), constant_value};
1576}
1577
1578template<class T>
1579inline void PassBase<T>::specialize_constant(GPUShader *shader,
1580 const char *constant_name,
1581 const float *constant_value)
1582{
1583 create_command(Type::SpecializeConstant).specialize_constant = {
1584 shader, GPU_shader_get_constant(shader, constant_name), constant_value};
1585}
1586
1587template<class T>
1588inline void PassBase<T>::specialize_constant(GPUShader *shader,
1589 const char *constant_name,
1590 const bool *constant_value)
1591{
1592 create_command(Type::SpecializeConstant).specialize_constant = {
1593 shader, GPU_shader_get_constant(shader, constant_name), constant_value};
1594}
1595
1597
1598} // namespace detail
1599
1600} // namespace blender::draw
ImageGPUTextures BKE_image_get_gpu_material_texture_try(Image *image, ImageUser *iuser, const bool use_tile_mapping)
Definition image_gpu.cc:503
ImageGPUTextures BKE_image_get_gpu_material_texture(Image *image, ImageUser *iuser, const bool use_tile_mapping)
Definition image_gpu.cc:496
#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:548
blender::gpu::Batch * GPU_batch_procedural_lines_get()
Definition gpu_batch.cc:538
blender::gpu::Batch * GPU_batch_procedural_points_get()
Definition gpu_batch.cc:533
blender::gpu::Batch * GPU_batch_procedural_triangles_get()
Definition gpu_batch.cc:543
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
eGPUFrameBufferBits
@ GPU_DEPTH_BIT
@ GPU_STENCIL_BIT
@ GPU_COLOR_BIT
GPUPass * GPU_material_get_pass(GPUMaterial *material)
ListBase GPU_material_textures(GPUMaterial *material)
GPUUniformBuf * GPU_material_uniform_buffer_get(GPUMaterial *material)
GPUShader * GPU_pass_shader_get(GPUPass *pass)
Definition gpu_pass.cc:173
GPUPrimType
@ GPU_PRIM_NONE
@ GPU_PRIM_LINES
@ GPU_PRIM_POINTS
@ GPU_PRIM_TRI_STRIP
@ GPU_PRIM_TRIS
int GPU_shader_get_sampler_binding(GPUShader *shader, const char *name)
int GPU_shader_get_uniform(GPUShader *shader, const char *name)
int GPU_shader_get_ubo_binding(GPUShader *shader, const char *name)
int GPU_shader_get_ssbo_binding(GPUShader *shader, const char *name)
int GPU_shader_get_constant(GPUShader *shader, const char *name)
eGPUBarrier
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(GPUTexture *texture)
std::string serialize(std::string line_prefix="") const
Definition draw_pass.hh:576
PassSortable(const char *name_)
Definition draw_pass.hh:550
PassMain::Sub & sub(const char *name, float sorting_value)
Definition draw_pass.hh:559
void clear_multi(Span< float4 > colors)
Definition draw_pass.hh:657
void bind_texture(const char *name, GPUTexture *texture, GPUSamplerState state=sampler_auto)
void bind_resources(U &resources)
Definition draw_pass.hh:440
void draw_procedural_indirect(GPUPrimType primitive, StorageBuffer< DrawCommand, true > &indirect_buffer, ResourceHandle handle={0})
Definition draw_pass.hh:980
void bind_image(const char *name, GPUTexture *image)
friend std::ostream & operator<<(std::ostream &stream, const PassBase &pass)
Definition draw_pass.hh:450
Vector< command::Header, 0 > headers_
Definition draw_pass.hh:134
void specialize_constant(GPUShader *shader, const char *name, const float &data)
void clear_stencil(uint8_t stencil)
void clear_color(float4 color)
void warm_shader_specialization(command::RecordingState &state) const
Definition draw_pass.hh:690
void draw(gpu::Batch *batch, uint instance_len=-1, uint vertex_len=-1, uint vertex_first=-1, ResourceHandleRange handle={0}, uint custom_id=0)
Definition draw_pass.hh:884
void subpass_transition(GPUAttachmentState depth_attachment, Span< GPUAttachmentState > color_attachments)
void clear_depth_stencil(float depth, uint8_t stencil)
SubPassVector< PassBase< DrawCommandBufType > > & sub_passes_
Definition draw_pass.hh:140
PassBase(const char *name, DrawCommandBufType &draw_command_buf, SubPassVector< PassBase< DrawCommandBufType > > &sub_passes, GPUShader *shader=nullptr)
Definition draw_pass.hh:154
command::Undetermined & create_command(command::Type type)
Definition draw_pass.hh:625
PassBase< DrawCommandBufType > & sub(const char *name)
Definition draw_pass.hh:681
void dispatch(int group_len)
Definition draw_pass.hh:994
int push_constant_offset(const char *name)
void submit(command::RecordingState &state) const
Definition draw_pass.hh:744
void barrier(eGPUBarrier type)
void state_set(DRWState state, int clip_plane_count=0)
void draw_indirect(gpu::Batch *batch, StorageBuffer< DrawCommand, true > &indirect_buffer, ResourceHandle handle={0})
Definition draw_pass.hh:971
void draw_expand(gpu::Batch *batch, GPUPrimType primitive_type, uint primitive_len, uint instance_len, uint vertex_len=-1, uint vertex_first=-1, ResourceHandleRange handle={0}, uint custom_id=0)
Definition draw_pass.hh:915
void bind_ubo(const char *name, GPUUniformBuf *buffer)
void clear(eGPUFrameBufferBits planes, float4 color, float depth, uint8_t stencil)
Definition draw_pass.hh:649
void framebuffer_set(GPUFrameBuffer **framebuffer)
Vector< command::Undetermined, 0 > commands_
Definition draw_pass.hh:136
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 material_set(Manager &manager, GPUMaterial *material, bool deferred_texture_loading=false)
std::string serialize(std::string line_prefix="") const
Definition draw_pass.hh:814
void push_constant(const char *name, const float &data)
void draw_procedural(GPUPrimType primitive, uint instance_len, uint vertex_len, uint vertex_first=-1, ResourceHandleRange handle={0}, uint custom_id=0)
Definition draw_pass.hh:953
gpu::Batch * procedural_batch_get(GPUPrimType primitive)
Definition draw_pass.hh:663
DrawCommandBufType & draw_commands_buf_
Definition draw_pass.hh:138
void bind_ssbo(const char *name, GPUStorageBuf *buffer)
void shader_set(GPUShader *shader)
detail::PassBase< command::DrawCommandBuf > Sub
Definition draw_pass.hh:490
Pass(const char *name)
Definition draw_pass.hh:499
const T & operator[](int64_t index) const
Definition draw_pass.hh:113
int64_t append_and_get_index(T &&elem)
Definition draw_pass.hh:98
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 @064345207361167251075330302113175271221317160336::@113254110077376341056327177062323111323010325277 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
static Image * as_image(GPUTexture *tex)
detail::Pass< command::DrawMultiBuf > PassMain
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
static constexpr GPUSamplerState internal_sampler()
GPUTexture ** texture
Definition BKE_image.hh:607
GPUTexture ** tile_mapping
Definition BKE_image.hh:608
enum blender::draw::command::PushConstant::Type type
i
Definition text_draw.cc:230