Blender V4.5
blender/display_driver.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2021-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include "GPU_context.hh"
6#include "GPU_immediate.hh"
7#include "GPU_platform.hh"
9#include "GPU_shader.hh"
10#include "GPU_state.hh"
11#include "GPU_texture.hh"
12
13#include "RE_engine.h"
14
16
17#include "util/log.h"
18#include "util/math.h"
19#include "util/vector.h"
20
22
23/* --------------------------------------------------------------------
24 * BlenderDisplayShader.
25 */
26
28 BL::Scene &b_scene)
29{
30 if (b_engine.support_display_space_shader(b_scene)) {
31 return make_unique<BlenderDisplaySpaceShader>(b_engine, b_scene);
32 }
33
34 return make_unique<BlenderFallbackDisplayShader>();
35}
36
46
56
57/* --------------------------------------------------------------------
58 * BlenderFallbackDisplayShader.
59 */
60static GPUShader *compile_fallback_shader()
61{
62 /* NOTE: Compilation errors are logged to console. */
63 GPUShader *shader = GPU_shader_create_from_info_name("gpu_shader_cycles_display_fallback");
64 return shader;
65}
66
71
72GPUShader *BlenderFallbackDisplayShader::bind(const int width, const int height)
73{
75
76 if (!shader_program_) {
77 return nullptr;
78 }
79
80 /* Bind shader now to enable uniform assignment. */
82 const int slot = 0;
84 float size[2];
85 size[0] = width;
86 size[1] = height;
88 return shader_program_;
89}
90
95
100
102{
104 return;
105 }
106
108
110 if (!shader_program_) {
111 LOG(ERROR) << "Failed to compile fallback shader";
112 return;
113 }
114
116 if (image_texture_location_ < 0) {
117 LOG(ERROR) << "Shader doesn't contain the 'image_texture' uniform.";
119 return;
120 }
121
123 if (fullscreen_location_ < 0) {
124 LOG(ERROR) << "Shader doesn't contain the 'fullscreen' uniform.";
126 return;
127 }
128}
129
137
138/* --------------------------------------------------------------------
139 * BlenderDisplaySpaceShader.
140 */
141
143 BL::Scene &b_scene)
144 : b_engine_(b_engine), b_scene_(b_scene)
145{
146 DCHECK(b_engine_.support_display_space_shader(b_scene_));
147}
148
149GPUShader *BlenderDisplaySpaceShader::bind(int /*width*/, int /*height*/)
150{
151 b_engine_.bind_display_space_shader(b_scene_);
152 return GPU_shader_get_bound();
153}
154
156{
157 b_engine_.unbind_display_space_shader();
158}
159
161{
162 if (!shader_program_) {
164 }
165 if (!shader_program_) {
166 LOG(ERROR) << "Error retrieving shader program for display space shader.";
167 }
168
169 return shader_program_;
170}
171
172/* --------------------------------------------------------------------
173 * DrawTile.
174 */
175
176/* Higher level representation of a texture from the graphics library. */
178 public:
179 /* Global counter for all allocated GPUTextures used by instances of this class. */
180 static inline std::atomic<int> num_used = 0;
181
182 DisplayGPUTexture() = default;
183
185 {
186 assert(gpu_texture == nullptr);
187 }
188
189 DisplayGPUTexture(const DisplayGPUTexture &other) = delete;
191
193 : gpu_texture(other.gpu_texture), width(other.width), height(other.height)
194 {
195 other.reset();
196 }
197
199 {
200 if (this == &other) {
201 return *this;
202 }
203
204 gpu_texture = other.gpu_texture;
205 width = other.width;
206 height = other.height;
207
208 other.reset();
209
210 return *this;
211 }
212
213 bool gpu_resources_ensure(const uint texture_width, const uint texture_height)
214 {
215 if (width != texture_width || height != texture_height) {
217 }
218
219 if (gpu_texture) {
220 return true;
221 }
222
223 width = texture_width;
224 height = texture_height;
225
226 /* Texture must have a minimum size of 1x1. */
227 gpu_texture = GPU_texture_create_2d("CyclesBlitTexture",
228 max(width, 1),
229 max(height, 1),
230 1,
233 nullptr);
234
235 if (!gpu_texture) {
236 LOG(ERROR) << "Error creating texture.";
237 return false;
238 }
239
242
243 ++num_used;
244
245 return true;
246 }
247
249 {
250 if (gpu_texture == nullptr) {
251 return;
252 }
253
255
256 reset();
257
258 --num_used;
259 }
260
261 /* Texture resource allocated by the GPU module.
262 *
263 * NOTE: Allocated on the render engine's context. */
264 GPUTexture *gpu_texture = nullptr;
265
266 /* Dimensions of the texture in pixels. */
267 int width = 0;
268 int height = 0;
269
270 protected:
271 void reset()
272 {
273 gpu_texture = nullptr;
274 width = 0;
275 height = 0;
276 }
277};
278
279/* Higher level representation of a Pixel Buffer Object (PBO) from the graphics library. */
281 public:
282 /* Global counter for all allocated GPU module PBOs used by instances of this class. */
283 static inline std::atomic<int> num_used = 0;
284
286
288 {
289 assert(gpu_pixel_buffer == nullptr);
290 }
291
294
296 : gpu_pixel_buffer(other.gpu_pixel_buffer), width(other.width), height(other.height)
297 {
298 other.reset();
299 }
300
302 {
303 if (this == &other) {
304 return *this;
305 }
306
307 gpu_pixel_buffer = other.gpu_pixel_buffer;
308 width = other.width;
309 height = other.height;
310
311 other.reset();
312
313 return *this;
314 }
315
316 bool gpu_resources_ensure(const uint new_width, const uint new_height, bool &buffer_recreated)
317 {
318 buffer_recreated = false;
319
320 const size_t required_size = sizeof(half4) * new_width * new_height;
321
322 /* Try to re-use the existing PBO if it has usable size. */
323 if (gpu_pixel_buffer) {
324 if (new_width != width || new_height != height ||
326 {
327 buffer_recreated = true;
329 }
330 }
331
332 /* Update size. */
333 width = new_width;
334 height = new_height;
335
336 /* Create pixel buffer if not already created. */
337 if (!gpu_pixel_buffer) {
339 buffer_recreated = true;
340 }
341
342 if (gpu_pixel_buffer == nullptr) {
343 LOG(ERROR) << "Error creating texture pixel buffer object.";
344 return false;
345 }
346
347 ++num_used;
348
349 return true;
350 }
351
353 {
354 if (!gpu_pixel_buffer) {
355 return;
356 }
357
359 gpu_pixel_buffer = nullptr;
360
361 reset();
362
363 --num_used;
364 }
365
366 /* Pixel Buffer Object allocated by the GPU module.
367 *
368 * NOTE: Allocated on the render engine's context. */
369 GPUPixelBuffer *gpu_pixel_buffer = nullptr;
370
371 /* Dimensions of the PBO. */
372 int width = 0;
373 int height = 0;
374
375 protected:
376 void reset()
377 {
378 gpu_pixel_buffer = nullptr;
379 width = 0;
380 height = 0;
381 }
382};
383
384class DrawTile {
385 public:
386 DrawTile() = default;
387 ~DrawTile() = default;
388
389 DrawTile(const DrawTile &other) = delete;
390 DrawTile &operator=(const DrawTile &other) = delete;
391
392 DrawTile(DrawTile &&other) noexcept = default;
393
394 DrawTile &operator=(DrawTile &&other) = default;
395
397 {
398 texture.gpu_resources_destroy();
399 }
400
401 bool ready_to_draw() const
402 {
403 return texture.gpu_texture != nullptr;
404 }
405
406 /* Texture which contains pixels of the tile. */
408
409 /* Display parameters the texture of this tile has been updated for. */
411};
412
414 public:
416 {
417 tile.gpu_resources_destroy();
418 buffer_object.gpu_resources_destroy();
419 }
420
424};
425
426/* --------------------------------------------------------------------
427 * BlenderDisplayDriver.
428 */
429
431 /* Resources of a tile which is being currently rendered. */
433
434 /* All tiles which rendering is finished and which content will not be changed. */
435 struct {
437
438 void gl_resources_destroy_and_clear()
439 {
440 for (DrawTile &tile : tiles) {
441 tile.gpu_resources_destroy();
442 }
443
444 tiles.clear();
445 }
447};
448
450 BL::Scene &b_scene,
451 const bool background)
452 : b_engine_(b_engine),
453 background_(background),
454 display_shader_(BlenderDisplayShader::create(b_engine, b_scene)),
455 tiles_(make_unique<Tiles>())
456{
457 /* Create context while on the main thread. */
459}
460
465
466/* --------------------------------------------------------------------
467 * Update procedure.
468 */
469
471{
472 if (!tiles_->current_tile.tile.ready_to_draw()) {
473 LOG(ERROR)
474 << "Unexpectedly moving to the next tile without any data provided for current tile.";
475 return;
476 }
477
478 /* Moving to the next tile without giving render data for the current tile is not an expected
479 * situation. */
481 /* Texture should have been updated from the PBO at this point. */
482 DCHECK(!tiles_->current_tile.need_update_texture_pixels);
483
484 tiles_->finished_tiles.tiles.emplace_back(std::move(tiles_->current_tile.tile));
485}
486
488 const int texture_width,
489 const int texture_height)
490{
491 /* Note that it's the responsibility of BlenderDisplayDriver to ensure updating and drawing
492 * the texture does not happen at the same time. This is achieved indirectly.
493 *
494 * When enabling the OpenGL/GPU context, it uses an internal mutex lock DST.gpu_context_lock.
495 * This same lock is also held when do_draw() is called, which together ensure mutual
496 * exclusion.
497 *
498 * This locking is not performed on the Cycles side, because that would cause lock inversion. */
499 if (!gpu_context_enable()) {
500 return false;
501 }
502
504
505 DrawTile &current_tile = tiles_->current_tile.tile;
506 DisplayGPUPixelBuffer &current_tile_buffer_object = tiles_->current_tile.buffer_object;
507
508 /* Clear storage of all finished tiles when display clear is requested.
509 * Do it when new tile data is provided to handle the display clear flag in a single place.
510 * It also makes the logic reliable from the whether drawing did happen or not point of view. */
511 if (need_zero_) {
512 tiles_->finished_tiles.gl_resources_destroy_and_clear();
513 need_zero_ = false;
514 }
515
516 /* Update PBO dimensions if needed.
517 *
518 * NOTE: Allocate the PBO for the size which will fit the final render resolution (as in,
519 * at a resolution divider 1. This was we don't need to recreate graphics interoperability
520 * objects which are costly and which are tied to the specific underlying buffer size.
521 * The downside of this approach is that when graphics interoperability is not used we are
522 * sending too much data to GPU when resolution divider is not 1. */
523 /* TODO(sergey): Investigate whether keeping the PBO exact size of the texture makes non-interop
524 * mode faster. */
525 const int buffer_width = params.size.x;
526 const int buffer_height = params.size.y;
527 bool interop_recreated = false;
528
529 if (!current_tile_buffer_object.gpu_resources_ensure(
530 buffer_width, buffer_height, interop_recreated) ||
531 !current_tile.texture.gpu_resources_ensure(texture_width, texture_height))
532 {
534 tiles_->current_tile.gpu_resources_destroy();
536 return false;
537 }
538
539 if (interop_recreated) {
541 }
542
543 /* Store an updated parameters of the current tile.
544 * In theory it is only needed once per update of the tile, but doing it on every update is
545 * the easiest and is not expensive. */
546 tiles_->current_tile.tile.params = params;
547
548 return true;
549}
550
552{
553 const DisplayGPUTexture &texture = tile.tile.texture;
554
555 if (!DCHECK_NOTNULL(tile.buffer_object.gpu_pixel_buffer)) {
556 LOG(ERROR) << "Display driver tile pixel buffer unavailable.";
557 return;
558 }
561 tile.buffer_object.gpu_pixel_buffer,
562 0,
563 0,
564 0,
565 texture.width,
566 texture.height,
567 0);
568}
569
571{
572 /* Unpack the PBO into the texture as soon as the new content is provided.
573 *
574 * This allows to ensure that the unpacking happens while resources like graphics interop (which
575 * lifetime is outside of control of the display driver) are still valid, as well as allows to
576 * move the tile from being current to finished immediately after this call.
577 *
578 * One concern with this approach is that if the update happens more often than drawing then
579 * doing the unpack here occupies GPU transfer for no good reason. However, the render scheduler
580 * takes care of ensuring updates don't happen that often. In regular applications redraw will
581 * happen much more often than this update.
582 *
583 * On some older GPUs on macOS, there is a driver crash when updating the texture for viewport
584 * renders while Blender is drawing. As a workaround update texture during draw, under assumption
585 * that there is no graphics interop on macOS and viewport render has a single tile. */
586 if (!background_ &&
588 {
589 tiles_->current_tile.need_update_texture_pixels = true;
590 }
591 else {
592 update_tile_texture_pixels(tiles_->current_tile);
593 }
594
595 /* Ensure GPU fence exists to synchronize upload. */
597
598 GPU_flush();
599
601}
602
603/* --------------------------------------------------------------------
604 * Texture buffer mapping.
605 */
606
608{
609 /* With multi device rendering, Cycles can switch between using graphics interop
610 * and not. For the denoised image it may be able to use graphics interop as that
611 * buffer is written to by one device, while the noisy renders can not use it.
612 *
613 * We need to clear the graphics interop buffer on that switch, as GPU_pixel_buffer_map
614 * may recreate the buffer or handle. */
616
617 GPUPixelBuffer *pix_buf = tiles_->current_tile.buffer_object.gpu_pixel_buffer;
618 if (!DCHECK_NOTNULL(pix_buf)) {
619 LOG(ERROR) << "Display driver tile pixel buffer unavailable.";
620 return nullptr;
621 }
622 half4 *mapped_rgba_pixels = reinterpret_cast<half4 *>(GPU_pixel_buffer_map(pix_buf));
623 if (!mapped_rgba_pixels) {
624 LOG(ERROR) << "Error mapping BlenderDisplayDriver pixel buffer object.";
625 }
626 return mapped_rgba_pixels;
627}
628
630{
631 GPUPixelBuffer *pix_buf = tiles_->current_tile.buffer_object.gpu_pixel_buffer;
632 if (!DCHECK_NOTNULL(pix_buf)) {
633 LOG(ERROR) << "Display driver tile pixel buffer unavailable.";
634 return;
635 }
636 GPU_pixel_buffer_unmap(pix_buf);
637}
638
639/* --------------------------------------------------------------------
640 * Graphics interoperability.
641 */
642
644{
645 GraphicsInteropDevice interop_device;
646
647 switch (GPU_backend_get_type()) {
649 interop_device.type = GraphicsInteropDevice::OPENGL;
650 break;
652 interop_device.type = GraphicsInteropDevice::VULKAN;
653 break;
655 interop_device.type = GraphicsInteropDevice::METAL;
656 break;
657 case GPU_BACKEND_NONE:
658 case GPU_BACKEND_ANY:
659 interop_device.type = GraphicsInteropDevice::NONE;
660 break;
661 }
662
664 interop_device.uuid.resize(uuid.size());
665 std::copy_n(uuid.data(), uuid.size(), interop_device.uuid.data());
666
667 return interop_device;
668}
669
671{
672 if (graphics_interop_buffer_.is_empty()) {
674 switch (GPU_backend_get_type()) {
677 break;
680 break;
683 break;
684 case GPU_BACKEND_NONE:
685 case GPU_BACKEND_ANY:
686 break;
687 }
688
690 tiles_->current_tile.buffer_object.gpu_pixel_buffer);
691 graphics_interop_buffer_.assign(type, handle.handle, handle.size);
692 }
693}
694
699
704
705/* --------------------------------------------------------------------
706 * Drawing.
707 */
708
710{
711 need_zero_ = true;
712}
713
714void BlenderDisplayDriver::set_zoom(const float zoom_x, const float zoom_y)
715{
716 zoom_ = make_float2(zoom_x, zoom_y);
717}
718
719/* Update vertex buffer with new coordinates of vertex positions and texture coordinates.
720 * This buffer is used to render texture in the viewport.
721 *
722 * NOTE: The buffer needs to be bound. */
724 const int texcoord_attribute,
725 const int position_attribute)
726{
727 const int x = params.full_offset.x;
728 const int y = params.full_offset.y;
729
730 const int width = params.size.x;
731 const int height = params.size.y;
732
734
735 immAttr2f(texcoord_attribute, 1.0f, 0.0f);
736 immVertex2f(position_attribute, x + width, y);
737
738 immAttr2f(texcoord_attribute, 1.0f, 1.0f);
739 immVertex2f(position_attribute, x + width, y + height);
740
741 immAttr2f(texcoord_attribute, 0.0f, 0.0f);
742 immVertex2f(position_attribute, x, y);
743
744 immAttr2f(texcoord_attribute, 0.0f, 1.0f);
745 immVertex2f(position_attribute, x, y + height);
746
747 immEnd();
748}
749
750static void draw_tile(const float2 &zoom,
751 const int texcoord_attribute,
752 const int position_attribute,
753 const DrawTile &draw_tile)
754{
755 if (!draw_tile.ready_to_draw()) {
756 return;
757 }
758
759 const DisplayGPUTexture &texture = draw_tile.texture;
760
761 if (!DCHECK_NOTNULL(texture.gpu_texture)) {
762 LOG(ERROR) << "Display driver tile GPU texture resource unavailable.";
763 return;
764 }
765
766 /* Trick to keep sharp rendering without jagged edges on all GPUs.
767 *
768 * The idea here is to enforce driver to use linear interpolation when the image is zoomed out.
769 * For the render result with a resolution divider in effect we always use nearest interpolation.
770 *
771 * Use explicit MIN assignment to make sure the driver does not have an undefined behavior at
772 * the zoom level 1. The MAG filter is always NEAREST. */
773 const float zoomed_width = draw_tile.params.size.x * zoom.x;
774 const float zoomed_height = draw_tile.params.size.y * zoom.y;
775 if (texture.width != draw_tile.params.size.x || texture.height != draw_tile.params.size.y) {
776 /* Resolution divider is different from 1, force nearest interpolation. */
778 }
779 else if (zoomed_width - draw_tile.params.size.x > -0.5f ||
780 zoomed_height - draw_tile.params.size.y > -0.5f)
781 {
783 }
784 else {
785 GPU_texture_bind_ex(texture.gpu_texture, {GPU_SAMPLER_FILTERING_LINEAR}, 0);
786 }
787
788 /* Draw at the parameters for which the texture has been updated for. This allows to always draw
789 * texture during bordered-rendered camera view without flickering. The validness of the display
790 * parameters for a texture is guaranteed by the initial "clear" state which makes drawing to
791 * have an early output.
792 *
793 * Such approach can cause some extra "jelly" effect during panning, but it is not more jelly
794 * than overlay of selected objects. Also, it's possible to redraw texture at an intersection of
795 * the texture draw parameters and the latest updated draw parameters (although, complexity of
796 * doing it might not worth it. */
797 vertex_draw(draw_tile.params, texcoord_attribute, position_attribute);
798}
799
801{
802 /* This is called from the render thread that also calls update_begin/end, right before ending
803 * the render loop. We wait for any queued PBO and render commands to be done, before destroying
804 * the render thread and activating the context in the main thread to destroy resources.
805 *
806 * If we don't do this, the NVIDIA driver hangs for a few seconds for when ending 3D viewport
807 * rendering, for unknown reasons. This was found with NVIDIA driver version 470.73 and a Quadro
808 * RTX 6000 on Linux. */
809 if (!gpu_context_enable()) {
810 return;
811 }
812
815
817}
818
820{
822
823 if (need_zero_) {
824 /* Texture is requested to be cleared and was not yet cleared.
825 *
826 * Do early return which should be equivalent of drawing all-zero texture.
827 * Watch out for the lock though so that the clear happening during update is properly
828 * synchronized here. */
830 return;
831 }
832
835
836 GPUShader *active_shader = display_shader_->bind(params.full_size.x, params.full_size.y);
837
839 const int texcoord_attribute = GPU_vertformat_attr_add(
840 format,
841 ccl::BlenderDisplayShader::tex_coord_attribute_name,
843 2,
845 const int position_attribute = GPU_vertformat_attr_add(
846 format,
847 ccl::BlenderDisplayShader::position_attribute_name,
849 2,
851
852 /* NOTE: Shader is bound again through IMM to register this shader with the IMM module
853 * and perform required setup for IMM rendering. This is required as the IMM module
854 * needs to be aware of which shader is bound, and the main display shader
855 * is bound externally. */
856 immBindShader(active_shader);
857
858 if (tiles_->current_tile.need_update_texture_pixels) {
859 update_tile_texture_pixels(tiles_->current_tile);
860 tiles_->current_tile.need_update_texture_pixels = false;
861 }
862
863 draw_tile(zoom_, texcoord_attribute, position_attribute, tiles_->current_tile.tile);
864
865 for (const DrawTile &tile : tiles_->finished_tiles.tiles) {
866 draw_tile(zoom_, texcoord_attribute, position_attribute, tile);
867 }
868
869 /* Reset IMM shader bind state. */
871
872 display_shader_->unbind();
873
875
877 GPU_flush();
878
880
881 VLOG_DEVICE_STATS << "Display driver number of textures: " << DisplayGPUTexture::num_used;
882 VLOG_DEVICE_STATS << "Display driver number of PBOs: " << DisplayGPUPixelBuffer::num_used;
883}
884
886{
887 if (!RE_engine_gpu_context_create(reinterpret_cast<RenderEngine *>(b_engine_.ptr.data))) {
888 LOG(ERROR) << "Error creating GPU context.";
889 return;
890 }
891
892 /* Create global GPU resources for display driver. */
893 if (!gpu_resources_create()) {
894 LOG(ERROR) << "Error creating GPU resources for Cycles Display Driver.";
895 return;
896 }
897}
898
900{
901 return RE_engine_gpu_context_enable(reinterpret_cast<RenderEngine *>(b_engine_.ptr.data));
902}
903
908
913
918
923
925{
926 /* Ensure context is active for resource creation. */
927 if (!gpu_context_enable()) {
928 LOG(ERROR) << "Error enabling GPU context.";
929 return false;
930 }
931
934
936 LOG(ERROR) << "Error creating GPU synchronization primitives.";
937 assert(0);
938 return false;
939 }
940
942 return true;
943}
944
946{
948
949 display_shader_.reset();
950
952
953 tiles_->current_tile.gpu_resources_destroy();
954 tiles_->finished_tiles.gl_resources_destroy_and_clear();
955
956 /* Fences. */
957 if (gpu_render_sync_) {
959 gpu_render_sync_ = nullptr;
960 }
961 if (gpu_upload_sync_) {
963 gpu_upload_sync_ = nullptr;
964 }
965
967
969}
970
unsigned int uint
eGPUBackendType GPU_backend_get_type()
void immEnd()
void immUnbindProgram()
void immVertex2f(uint attr_id, float x, float y)
void immBindShader(GPUShader *shader)
GPUVertFormat * immVertexFormat()
void immAttr2f(uint attr_id, float x, float y)
void immBegin(GPUPrimType, uint vertex_len)
blender::Span< uint8_t > GPU_platform_uuid()
@ GPU_DRIVER_ANY
bool GPU_type_matches_ex(eGPUDeviceType device, eGPUOSType os, eGPUDriverType driver, eGPUBackendType backend)
@ GPU_OS_MAC
@ GPU_DEVICE_NVIDIA
@ GPU_PRIM_TRI_STRIP
int GPU_shader_get_uniform(GPUShader *shader, const char *name)
void GPU_shader_uniform_int_ex(GPUShader *shader, int location, int length, int array_size, const int *value)
GPUShader * GPU_shader_create_from_info_name(const char *info_name)
void GPU_shader_bind(GPUShader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
int GPU_shader_get_attribute(const GPUShader *shader, const char *name)
void GPU_shader_uniform_float_ex(GPUShader *shader, int location, int length, int array_size, const float *value)
void GPU_shader_free(GPUShader *shader)
void GPU_shader_unbind()
GPUShader * GPU_shader_get_bound()
void GPU_flush()
Definition gpu_state.cc:305
@ GPU_BLEND_NONE
Definition GPU_state.hh:85
@ GPU_BLEND_ALPHA_PREMULT
Definition GPU_state.hh:88
void GPU_blend(eGPUBlend blend)
Definition gpu_state.cc:42
GPUFence * GPU_fence_create()
Definition gpu_state.cc:390
void GPU_fence_wait(GPUFence *fence)
Definition gpu_state.cc:406
void GPU_fence_signal(GPUFence *fence)
Definition gpu_state.cc:401
void GPU_fence_free(GPUFence *fence)
Definition gpu_state.cc:396
GPUTexture * GPU_texture_create_2d(const char *name, int width, int height, int mip_len, eGPUTextureFormat format, eGPUTextureUsage usage, const float *data)
void GPU_pixel_buffer_unmap(GPUPixelBuffer *pixel_buf)
void GPU_texture_bind_ex(GPUTexture *texture, GPUSamplerState state, int unit)
GPUPixelBufferNativeHandle GPU_pixel_buffer_get_native_handle(GPUPixelBuffer *pixel_buf)
size_t GPU_pixel_buffer_size(GPUPixelBuffer *pixel_buf)
void * GPU_pixel_buffer_map(GPUPixelBuffer *pixel_buf)
void GPU_pixel_buffer_free(GPUPixelBuffer *pixel_buf)
void GPU_texture_update_sub_from_pixel_buffer(GPUTexture *texture, eGPUDataFormat data_format, GPUPixelBuffer *pixel_buf, int offset_x, int offset_y, int offset_z, int width, int height, int depth)
@ GPU_DATA_HALF_FLOAT
void GPU_texture_extend_mode(GPUTexture *texture, GPUSamplerExtendMode extend_mode)
@ GPU_TEXTURE_USAGE_GENERAL
@ GPU_SAMPLER_EXTEND_MODE_EXTEND
void GPU_texture_filter_mode(GPUTexture *texture, bool use_filter)
#define GPU_TEXTURE_FREE_SAFE(texture)
@ GPU_RGBA16F
GPUPixelBuffer * GPU_pixel_buffer_create(size_t byte_size)
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, blender::StringRef name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
static void update_tile_texture_pixels(const DrawTileAndPBO &tile)
static GPUShader * compile_fallback_shader()
static void vertex_draw(const DisplayDriver::Params &params, const int texcoord_attribute, const int position_attribute)
static void draw_tile(const float2 &zoom, const int texcoord_attribute, const int position_attribute, const DrawTile &draw_tile)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
GraphicsInteropDevice graphics_interop_get_device() override
half4 * map_texture_buffer() override
void graphics_interop_activate() override
void draw(const Params &params) override
std::atomic< bool > need_zero_
unique_ptr< BlenderDisplayShader > display_shader_
void graphics_interop_deactivate() override
void graphics_interop_update_buffer() override
BlenderDisplayDriver(BL::RenderEngine &b_engine, BL::Scene &b_scene, const bool background)
bool update_begin(const Params &params, const int texture_width, const int texture_height) override
void set_zoom(const float zoom_x, const float zoom_y)
virtual GPUShader * get_shader_program()=0
virtual int get_position_attrib_location()
static unique_ptr< BlenderDisplayShader > create(BL::RenderEngine &b_engine, BL::Scene &b_scene)
static constexpr const char * tex_coord_attribute_name
static constexpr const char * position_attribute_name
virtual int get_tex_coord_attrib_location()
GPUShader * get_shader_program() override
BlenderDisplaySpaceShader(BL::RenderEngine &b_engine, BL::Scene &b_scene)
GPUShader * bind(const int width, const int height) override
GPUShader * bind(const int width, const int height) override
GPUShader * get_shader_program() override
GraphicsInteropBuffer graphics_interop_buffer_
bool gpu_resources_ensure(const uint new_width, const uint new_height, bool &buffer_recreated)
DisplayGPUPixelBuffer()=default
static std::atomic< int > num_used
DisplayGPUPixelBuffer(const DisplayGPUPixelBuffer &other)=delete
DisplayGPUPixelBuffer & operator=(DisplayGPUPixelBuffer &other)=delete
DisplayGPUPixelBuffer(DisplayGPUPixelBuffer &&other) noexcept
DisplayGPUPixelBuffer & operator=(DisplayGPUPixelBuffer &&other)
bool gpu_resources_ensure(const uint texture_width, const uint texture_height)
DisplayGPUTexture & operator=(DisplayGPUTexture &other)=delete
DisplayGPUTexture(DisplayGPUTexture &&other) noexcept
DisplayGPUTexture & operator=(DisplayGPUTexture &&other)
static std::atomic< int > num_used
DisplayGPUTexture()=default
DisplayGPUTexture(const DisplayGPUTexture &other)=delete
DisplayGPUPixelBuffer buffer_object
DrawTile(const DrawTile &other)=delete
~DrawTile()=default
DrawTile(DrawTile &&other) noexcept=default
bool ready_to_draw() const
DrawTile()=default
BlenderDisplayDriver::Params params
DrawTile & operator=(DrawTile &&other)=default
DrawTile & operator=(const DrawTile &other)=delete
DisplayGPUTexture texture
constexpr const T * data() const
Definition BLI_span.hh:215
constexpr int64_t size() const
Definition BLI_span.hh:252
#define CCL_NAMESPACE_END
ccl_device_forceinline float2 make_float2(const float x, const float y)
TEX_TEMPLATE DataVec texture(T, FltCoord, float=0.0f) RET
#define assert(assertion)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void RE_engine_gpu_context_lock(RenderEngine *engine)
void RE_engine_gpu_context_unlock(RenderEngine *engine)
void RE_engine_gpu_context_destroy(RenderEngine *engine)
bool RE_engine_gpu_context_enable(RenderEngine *engine)
bool RE_engine_gpu_context_create(RenderEngine *engine)
void RE_engine_gpu_context_disable(RenderEngine *engine)
const ccl_global KernelWorkTile * tile
format
#define DCHECK(expression)
Definition log.h:50
#define DCHECK_NOTNULL(expression)
Definition log.h:52
#define VLOG_DEVICE_STATS
Definition log.h:77
#define LOG(severity)
Definition log.h:32
struct BlenderDisplayDriver::Tiles::@006223105356012215047013027375056267334213253135 finished_tiles
static constexpr GPUSamplerState default_sampler()
float x
float y
Definition half.h:60
max
Definition text_draw.cc:251