Blender V5.0
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 */
61{
62 /* NOTE: Compilation errors are logged to console. */
64 "gpu_shader_cycles_display_fallback");
65 return shader;
66}
67
72
74{
76
77 if (!shader_program_) {
78 return nullptr;
79 }
80
81 /* Bind shader now to enable uniform assignment. */
83 const int slot = 0;
85 float size[2];
86 size[0] = width;
87 size[1] = height;
89 return shader_program_;
90}
91
96
101
103{
105 return;
106 }
107
109
111 if (!shader_program_) {
112 LOG_ERROR << "Failed to compile fallback shader";
113 return;
114 }
115
117 if (image_texture_location_ < 0) {
118 LOG_ERROR << "Shader doesn't contain the 'image_texture' uniform.";
120 return;
121 }
122
124 if (fullscreen_location_ < 0) {
125 LOG_ERROR << "Shader doesn't contain the 'fullscreen' uniform.";
127 return;
128 }
129}
130
138
139/* --------------------------------------------------------------------
140 * BlenderDisplaySpaceShader.
141 */
142
144 BL::Scene &b_scene)
145 : b_engine_(b_engine), b_scene_(b_scene)
146{
147 DCHECK(b_engine_.support_display_space_shader(b_scene_));
148}
149
151{
152 b_engine_.bind_display_space_shader(b_scene_);
153 return GPU_shader_get_bound();
154}
155
157{
158 b_engine_.unbind_display_space_shader();
159}
160
162{
163 if (!shader_program_) {
165 }
166 if (!shader_program_) {
167 LOG_ERROR << "Error retrieving shader program for display space shader.";
168 }
169
170 return shader_program_;
171}
172
173/* --------------------------------------------------------------------
174 * DrawTile.
175 */
176
177/* Higher level representation of a texture from the graphics library. */
179 public:
180 /* Global counter for all allocated GPUTextures used by instances of this class. */
181 static inline std::atomic<int> num_used = 0;
182
183 DisplayGPUTexture() = default;
184
186 {
187 assert(gpu_texture == nullptr);
188 }
189
190 DisplayGPUTexture(const DisplayGPUTexture &other) = delete;
192
194 : gpu_texture(other.gpu_texture), width(other.width), height(other.height)
195 {
196 other.reset();
197 }
198
200 {
201 if (this == &other) {
202 return *this;
203 }
204
205 gpu_texture = other.gpu_texture;
206 width = other.width;
207 height = other.height;
208
209 other.reset();
210
211 return *this;
212 }
213
214 bool gpu_resources_ensure(const uint texture_width, const uint texture_height)
215 {
216 if (width != texture_width || height != texture_height) {
218 }
219
220 if (gpu_texture) {
221 return true;
222 }
223
224 width = texture_width;
225 height = texture_height;
226
227 /* Texture must have a minimum size of 1x1. */
228 gpu_texture = GPU_texture_create_2d("CyclesBlitTexture",
229 max(width, 1),
230 max(height, 1),
231 1,
232 blender::gpu::TextureFormat::SFLOAT_16_16_16_16,
234 nullptr);
235
236 if (!gpu_texture) {
237 LOG_ERROR << "Error creating texture.";
238 return false;
239 }
240
243
244 ++num_used;
245
246 return true;
247 }
248
250 {
251 if (gpu_texture == nullptr) {
252 return;
253 }
254
256
257 reset();
258
259 --num_used;
260 }
261
262 /* Texture resource allocated by the GPU module.
263 *
264 * NOTE: Allocated on the render engine's context. */
266
267 /* Dimensions of the texture in pixels. */
268 int width = 0;
269 int height = 0;
270
271 protected:
272 void reset()
273 {
274 gpu_texture = nullptr;
275 width = 0;
276 height = 0;
277 }
278};
279
280/* Higher level representation of a Pixel Buffer Object (PBO) from the graphics library. */
282 public:
283 /* Global counter for all allocated GPU module PBOs used by instances of this class. */
284 static inline std::atomic<int> num_used = 0;
285
287
289 {
290 assert(gpu_pixel_buffer == nullptr);
291 }
292
295
297 : gpu_pixel_buffer(other.gpu_pixel_buffer), width(other.width), height(other.height)
298 {
299 other.reset();
300 }
301
303 {
304 if (this == &other) {
305 return *this;
306 }
307
308 gpu_pixel_buffer = other.gpu_pixel_buffer;
309 width = other.width;
310 height = other.height;
311
312 other.reset();
313
314 return *this;
315 }
316
317 bool gpu_resources_ensure(const uint new_width, const uint new_height, bool &buffer_recreated)
318 {
319 buffer_recreated = false;
320
321 const size_t required_size = sizeof(half4) * new_width * new_height;
322
323 /* Try to re-use the existing PBO if it has usable size. */
324 if (gpu_pixel_buffer) {
325 if (new_width != width || new_height != height ||
327 {
328 buffer_recreated = true;
330 }
331 }
332
333 /* Update size. */
334 width = new_width;
335 height = new_height;
336
337 /* Create pixel buffer if not already created. */
338 if (!gpu_pixel_buffer) {
340 buffer_recreated = true;
341 }
342
343 if (gpu_pixel_buffer == nullptr) {
344 LOG_ERROR << "Error creating texture pixel buffer object.";
345 return false;
346 }
347
348 ++num_used;
349
350 return true;
351 }
352
354 {
355 if (!gpu_pixel_buffer) {
356 return;
357 }
358
360 gpu_pixel_buffer = nullptr;
361
362 reset();
363
364 --num_used;
365 }
366
367 /* Pixel Buffer Object allocated by the GPU module.
368 *
369 * NOTE: Allocated on the render engine's context. */
370 GPUPixelBuffer *gpu_pixel_buffer = nullptr;
371
372 /* Dimensions of the PBO. */
373 int width = 0;
374 int height = 0;
375
376 protected:
377 void reset()
378 {
379 gpu_pixel_buffer = nullptr;
380 width = 0;
381 height = 0;
382 }
383};
384
385class DrawTile {
386 public:
387 DrawTile() = default;
388 ~DrawTile() = default;
389
390 DrawTile(const DrawTile &other) = delete;
391 DrawTile &operator=(const DrawTile &other) = delete;
392
393 DrawTile(DrawTile &&other) noexcept = default;
394
395 DrawTile &operator=(DrawTile &&other) = default;
396
398 {
399 texture.gpu_resources_destroy();
400 }
401
402 bool ready_to_draw() const
403 {
404 return texture.gpu_texture != nullptr;
405 }
406
407 /* Texture which contains pixels of the tile. */
409
410 /* Display parameters the texture of this tile has been updated for. */
412};
413
415 public:
417 {
418 tile.gpu_resources_destroy();
419 buffer_object.gpu_resources_destroy();
420 }
421
425};
426
427/* --------------------------------------------------------------------
428 * BlenderDisplayDriver.
429 */
430
432 /* Resources of a tile which is being currently rendered. */
434
435 /* All tiles which rendering is finished and which content will not be changed. */
436 struct {
438
439 void gl_resources_destroy_and_clear()
440 {
441 for (DrawTile &tile : tiles) {
442 tile.gpu_resources_destroy();
443 }
444
445 tiles.clear();
446 }
448};
449
451 BL::Scene &b_scene,
452 const bool background)
453 : b_engine_(b_engine),
454 background_(background),
455 display_shader_(BlenderDisplayShader::create(b_engine, b_scene)),
456 tiles_(make_unique<Tiles>())
457{
458 /* Create context while on the main thread. */
460}
461
466
467/* --------------------------------------------------------------------
468 * Update procedure.
469 */
470
472{
473 if (!tiles_->current_tile.tile.ready_to_draw()) {
475 << "Unexpectedly moving to the next tile without any data provided for current tile.";
476 return;
477 }
478
479 /* Moving to the next tile without giving render data for the current tile is not an expected
480 * situation. */
482 /* Texture should have been updated from the PBO at this point. */
483 DCHECK(!tiles_->current_tile.need_update_texture_pixels);
484
485 tiles_->finished_tiles.tiles.emplace_back(std::move(tiles_->current_tile.tile));
486}
487
489 const int texture_width,
490 const int texture_height)
491{
492 /* Note that it's the responsibility of BlenderDisplayDriver to ensure updating and drawing
493 * the texture does not happen at the same time. This is achieved indirectly.
494 *
495 * When enabling the OpenGL/GPU context, it uses an internal mutex lock DST.gpu_context_lock.
496 * This same lock is also held when do_draw() is called, which together ensure mutual
497 * exclusion.
498 *
499 * This locking is not performed on the Cycles side, because that would cause lock inversion. */
500 if (!gpu_context_enable()) {
501 return false;
502 }
503
505
506 DrawTile &current_tile = tiles_->current_tile.tile;
507 DisplayGPUPixelBuffer &current_tile_buffer_object = tiles_->current_tile.buffer_object;
508
509 /* Clear storage of all finished tiles when display clear is requested.
510 * Do it when new tile data is provided to handle the display clear flag in a single place.
511 * It also makes the logic reliable from the whether drawing did happen or not point of view. */
512 if (need_zero_) {
513 tiles_->finished_tiles.gl_resources_destroy_and_clear();
514 need_zero_ = false;
515 }
516
517 /* Update PBO dimensions if needed.
518 *
519 * NOTE: Allocate the PBO for the size which will fit the final render resolution (as in,
520 * at a resolution divider 1. This was we don't need to recreate graphics interoperability
521 * objects which are costly and which are tied to the specific underlying buffer size.
522 * The downside of this approach is that when graphics interoperability is not used we are
523 * sending too much data to GPU when resolution divider is not 1. */
524 /* TODO(sergey): Investigate whether keeping the PBO exact size of the texture makes non-interop
525 * mode faster. */
526 const int buffer_width = params.size.x;
527 const int buffer_height = params.size.y;
528 bool interop_recreated = false;
529
530 if (!current_tile_buffer_object.gpu_resources_ensure(
531 buffer_width, buffer_height, interop_recreated) ||
532 !current_tile.texture.gpu_resources_ensure(texture_width, texture_height))
533 {
535 tiles_->current_tile.gpu_resources_destroy();
537 return false;
538 }
539
540 if (interop_recreated) {
542 }
543
544 /* Store an updated parameters of the current tile.
545 * In theory it is only needed once per update of the tile, but doing it on every update is
546 * the easiest and is not expensive. */
547 tiles_->current_tile.tile.params = params;
548
549 return true;
550}
551
553{
554 const DisplayGPUTexture &texture = tile.tile.texture;
555
556 if (!DCHECK_NOTNULL(tile.buffer_object.gpu_pixel_buffer)) {
557 LOG_ERROR << "Display driver tile pixel buffer unavailable.";
558 return;
559 }
562 tile.buffer_object.gpu_pixel_buffer,
563 0,
564 0,
565 0,
566 texture.width,
567 texture.height,
568 0);
569}
570
572{
573 /* Unpack the PBO into the texture as soon as the new content is provided.
574 *
575 * This allows to ensure that the unpacking happens while resources like graphics interop (which
576 * lifetime is outside of control of the display driver) are still valid, as well as allows to
577 * move the tile from being current to finished immediately after this call.
578 *
579 * One concern with this approach is that if the update happens more often than drawing then
580 * doing the unpack here occupies GPU transfer for no good reason. However, the render scheduler
581 * takes care of ensuring updates don't happen that often. In regular applications redraw will
582 * happen much more often than this update.
583 *
584 * On some older GPUs on macOS, there is a driver crash when updating the texture for viewport
585 * renders while Blender is drawing. As a workaround update texture during draw, under assumption
586 * that there is no graphics interop on macOS and viewport render has a single tile. */
587 if (!background_ &&
589 {
590 tiles_->current_tile.need_update_texture_pixels = true;
591 }
592 else {
593 update_tile_texture_pixels(tiles_->current_tile);
594 }
595
596 /* Ensure GPU fence exists to synchronize upload. */
598
599 GPU_flush();
600
602}
603
604/* --------------------------------------------------------------------
605 * Texture buffer mapping.
606 */
607
609{
610 /* With multi device rendering, Cycles can switch between using graphics interop
611 * and not. For the denoised image it may be able to use graphics interop as that
612 * buffer is written to by one device, while the noisy renders can not use it.
613 *
614 * We need to clear the graphics interop buffer on that switch, as GPU_pixel_buffer_map
615 * may recreate the buffer or handle. */
617
618 GPUPixelBuffer *pix_buf = tiles_->current_tile.buffer_object.gpu_pixel_buffer;
619 if (!DCHECK_NOTNULL(pix_buf)) {
620 LOG_ERROR << "Display driver tile pixel buffer unavailable.";
621 return nullptr;
622 }
623 half4 *mapped_rgba_pixels = reinterpret_cast<half4 *>(GPU_pixel_buffer_map(pix_buf));
624 if (!mapped_rgba_pixels) {
625 LOG_ERROR << "Error mapping BlenderDisplayDriver pixel buffer object.";
626 }
627 return mapped_rgba_pixels;
628}
629
631{
632 GPUPixelBuffer *pix_buf = tiles_->current_tile.buffer_object.gpu_pixel_buffer;
633 if (!DCHECK_NOTNULL(pix_buf)) {
634 LOG_ERROR << "Display driver tile pixel buffer unavailable.";
635 return;
636 }
637 GPU_pixel_buffer_unmap(pix_buf);
638}
639
640/* --------------------------------------------------------------------
641 * Graphics interoperability.
642 */
643
645{
646 GraphicsInteropDevice interop_device;
647
648 switch (GPU_backend_get_type()) {
650 interop_device.type = GraphicsInteropDevice::OPENGL;
651 break;
653 interop_device.type = GraphicsInteropDevice::VULKAN;
654 break;
656 interop_device.type = GraphicsInteropDevice::METAL;
657 break;
658 case GPU_BACKEND_NONE:
659 case GPU_BACKEND_ANY:
660 interop_device.type = GraphicsInteropDevice::NONE;
661 break;
662 }
663
665 interop_device.uuid.resize(uuid.size());
666 std::copy_n(uuid.data(), uuid.size(), interop_device.uuid.data());
667
668 return interop_device;
669}
670
672{
673 if (graphics_interop_buffer_.is_empty()) {
675 switch (GPU_backend_get_type()) {
678 break;
681 break;
684 break;
685 case GPU_BACKEND_NONE:
686 case GPU_BACKEND_ANY:
687 break;
688 }
689
691 tiles_->current_tile.buffer_object.gpu_pixel_buffer);
692 graphics_interop_buffer_.assign(type, handle.handle, handle.size);
693 }
694}
695
700
705
706/* --------------------------------------------------------------------
707 * Drawing.
708 */
709
711{
712 need_zero_ = true;
713}
714
715void BlenderDisplayDriver::set_zoom(const float zoom_x, const float zoom_y)
716{
717 zoom_ = make_float2(zoom_x, zoom_y);
718}
719
720/* Update vertex buffer with new coordinates of vertex positions and texture coordinates.
721 * This buffer is used to render texture in the viewport.
722 *
723 * NOTE: The buffer needs to be bound. */
725 const int texcoord_attribute,
726 const int position_attribute)
727{
728 const int x = params.full_offset.x;
729 const int y = params.full_offset.y;
730
731 const int width = params.size.x;
732 const int height = params.size.y;
733
735
736 immAttr2f(texcoord_attribute, 1.0f, 0.0f);
737 immVertex2f(position_attribute, x + width, y);
738
739 immAttr2f(texcoord_attribute, 1.0f, 1.0f);
740 immVertex2f(position_attribute, x + width, y + height);
741
742 immAttr2f(texcoord_attribute, 0.0f, 0.0f);
743 immVertex2f(position_attribute, x, y);
744
745 immAttr2f(texcoord_attribute, 0.0f, 1.0f);
746 immVertex2f(position_attribute, x, y + height);
747
748 immEnd();
749}
750
751static void draw_tile(const float2 &zoom,
752 const int texcoord_attribute,
753 const int position_attribute,
754 const DrawTile &draw_tile)
755{
756 if (!draw_tile.ready_to_draw()) {
757 return;
758 }
759
760 const DisplayGPUTexture &texture = draw_tile.texture;
761
762 if (!DCHECK_NOTNULL(texture.gpu_texture)) {
763 LOG_ERROR << "Display driver tile GPU texture resource unavailable.";
764 return;
765 }
766
767 /* Trick to keep sharp rendering without jagged edges on all GPUs.
768 *
769 * The idea here is to enforce driver to use linear interpolation when the image is zoomed out.
770 * For the render result with a resolution divider in effect we always use nearest interpolation.
771 *
772 * Use explicit MIN assignment to make sure the driver does not have an undefined behavior at
773 * the zoom level 1. The MAG filter is always NEAREST. */
774 const float zoomed_width = draw_tile.params.size.x * zoom.x;
775 const float zoomed_height = draw_tile.params.size.y * zoom.y;
776 if (texture.width != draw_tile.params.size.x || texture.height != draw_tile.params.size.y) {
777 /* Resolution divider is different from 1, force nearest interpolation. */
779 }
780 else if (zoomed_width - draw_tile.params.size.x > -0.5f ||
781 zoomed_height - draw_tile.params.size.y > -0.5f)
782 {
784 }
785 else {
786 GPU_texture_bind_ex(texture.gpu_texture, {GPU_SAMPLER_FILTERING_LINEAR}, 0);
787 }
788
789 /* Draw at the parameters for which the texture has been updated for. This allows to always draw
790 * texture during bordered-rendered camera view without flickering. The validness of the display
791 * parameters for a texture is guaranteed by the initial "clear" state which makes drawing to
792 * have an early output.
793 *
794 * Such approach can cause some extra "jelly" effect during panning, but it is not more jelly
795 * than overlay of selected objects. Also, it's possible to redraw texture at an intersection of
796 * the texture draw parameters and the latest updated draw parameters (although, complexity of
797 * doing it might not worth it. */
798 vertex_draw(draw_tile.params, texcoord_attribute, position_attribute);
799}
800
802{
803 /* This is called from the render thread that also calls update_begin/end, right before ending
804 * the render loop. We wait for any queued PBO and render commands to be done, before destroying
805 * the render thread and activating the context in the main thread to destroy resources.
806 *
807 * If we don't do this, the NVIDIA driver hangs for a few seconds for when ending 3D viewport
808 * rendering, for unknown reasons. This was found with NVIDIA driver version 470.73 and a Quadro
809 * RTX 6000 on Linux. */
810 if (!gpu_context_enable()) {
811 return;
812 }
813
816
818}
819
821{
823
824 if (need_zero_) {
825 /* Texture is requested to be cleared and was not yet cleared.
826 *
827 * Do early return which should be equivalent of drawing all-zero texture.
828 * Watch out for the lock though so that the clear happening during update is properly
829 * synchronized here. */
831 return;
832 }
833
836
837 blender::gpu::Shader *active_shader = display_shader_->bind(params.full_size.x,
838 params.full_size.y);
839
841 const int texcoord_attribute = GPU_vertformat_attr_add(
842 format,
843 ccl::BlenderDisplayShader::tex_coord_attribute_name,
844 blender::gpu::VertAttrType::SFLOAT_32_32);
845 const int position_attribute = GPU_vertformat_attr_add(
846 format,
847 ccl::BlenderDisplayShader::position_attribute_name,
848 blender::gpu::VertAttrType::SFLOAT_32_32);
849
850 /* NOTE: Shader is bound again through IMM to register this shader with the IMM module
851 * and perform required setup for IMM rendering. This is required as the IMM module
852 * needs to be aware of which shader is bound, and the main display shader
853 * is bound externally. */
854 immBindShader(active_shader);
855
856 if (tiles_->current_tile.need_update_texture_pixels) {
857 update_tile_texture_pixels(tiles_->current_tile);
858 tiles_->current_tile.need_update_texture_pixels = false;
859 }
860
861 draw_tile(zoom_, texcoord_attribute, position_attribute, tiles_->current_tile.tile);
862
863 for (const DrawTile &tile : tiles_->finished_tiles.tiles) {
864 draw_tile(zoom_, texcoord_attribute, position_attribute, tile);
865 }
866
867 /* Reset IMM shader bind state. */
869
870 display_shader_->unbind();
871
873
875 GPU_flush();
876
878
879 LOG_TRACE << "Display driver number of textures: " << DisplayGPUTexture::num_used;
880 LOG_TRACE << "Display driver number of PBOs: " << DisplayGPUPixelBuffer::num_used;
881}
882
884{
885 if (!RE_engine_gpu_context_create(reinterpret_cast<RenderEngine *>(b_engine_.ptr.data))) {
886 LOG_ERROR << "Error creating GPU context.";
887 return;
888 }
889
890 /* Create global GPU resources for display driver. */
891 if (!gpu_resources_create()) {
892 LOG_ERROR << "Error creating GPU resources for Display Driver.";
893 return;
894 }
895}
896
898{
899 return RE_engine_gpu_context_enable(reinterpret_cast<RenderEngine *>(b_engine_.ptr.data));
900}
901
906
911
916
921
923{
924 /* Ensure context is active for resource creation. */
925 if (!gpu_context_enable()) {
926 LOG_ERROR << "Error enabling GPU context.";
927 return false;
928 }
929
932
934 LOG_ERROR << "Error creating GPU synchronization primitives.";
935 assert(0);
936 return false;
937 }
938
940 return true;
941}
942
944{
946
947 display_shader_.reset();
948
950
951 tiles_->current_tile.gpu_resources_destroy();
952 tiles_->finished_tiles.gl_resources_destroy_and_clear();
953
954 /* Fences. */
955 if (gpu_render_sync_) {
957 gpu_render_sync_ = nullptr;
958 }
959 if (gpu_upload_sync_) {
961 gpu_upload_sync_ = nullptr;
962 }
963
965
967}
968
unsigned int uint
GPUBackendType GPU_backend_get_type()
void immEnd()
void immUnbindProgram()
void immBindShader(blender::gpu::Shader *shader)
void immVertex2f(uint attr_id, float x, float y)
GPUVertFormat * immVertexFormat()
void immAttr2f(uint attr_id, float x, float y)
void immBegin(GPUPrimType, uint vertex_len)
@ GPU_DEVICE_NVIDIA
blender::Span< uint8_t > GPU_platform_uuid()
@ GPU_DRIVER_ANY
@ GPU_OS_MAC
bool GPU_type_matches_ex(GPUDeviceType device, GPUOSType os, GPUDriverType driver, GPUBackendType backend)
@ GPU_PRIM_TRI_STRIP
void GPU_shader_free(blender::gpu::Shader *shader)
void GPU_shader_bind(blender::gpu::Shader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
blender::gpu::Shader * GPU_shader_get_bound()
void GPU_shader_uniform_int_ex(blender::gpu::Shader *shader, int location, int length, int array_size, const int *value)
int GPU_shader_get_attribute(const blender::gpu::Shader *shader, const char *name)
blender::gpu::Shader * GPU_shader_create_from_info_name(const char *info_name)
int GPU_shader_get_uniform(blender::gpu::Shader *shader, const char *name)
void GPU_shader_unbind()
void GPU_shader_uniform_float_ex(blender::gpu::Shader *shader, int location, int length, int array_size, const float *value)
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(GPUBlend blend)
Definition gpu_state.cc:42
GPUFence * GPU_fence_create()
Definition gpu_state.cc:331
void GPU_fence_wait(GPUFence *fence)
Definition gpu_state.cc:347
void GPU_fence_signal(GPUFence *fence)
Definition gpu_state.cc:342
void GPU_fence_free(GPUFence *fence)
Definition gpu_state.cc:337
void GPU_pixel_buffer_unmap(GPUPixelBuffer *pixel_buf)
void GPU_texture_update_sub_from_pixel_buffer(blender::gpu::Texture *texture, eGPUDataFormat data_format, GPUPixelBuffer *pixel_buf, int offset_x, int offset_y, int offset_z, int width, int height, int depth)
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)
@ GPU_DATA_HALF_FLOAT
void GPU_texture_bind_ex(blender::gpu::Texture *texture, GPUSamplerState state, int unit)
void GPU_texture_extend_mode(blender::gpu::Texture *texture, GPUSamplerExtendMode extend_mode)
@ GPU_TEXTURE_USAGE_GENERAL
@ GPU_SAMPLER_EXTEND_MODE_EXTEND
#define GPU_TEXTURE_FREE_SAFE(texture)
blender::gpu::Texture * GPU_texture_create_2d(const char *name, int width, int height, int mip_len, blender::gpu::TextureFormat format, eGPUTextureUsage usage, const float *data)
void GPU_texture_filter_mode(blender::gpu::Texture *texture, bool use_filter)
GPUPixelBuffer * GPU_pixel_buffer_create(size_t byte_size)
uint GPU_vertformat_attr_add(GPUVertFormat *format, blender::StringRef name, blender::gpu::VertAttrType type)
static void update_tile_texture_pixels(const DrawTileAndPBO &tile)
static blender::gpu::Shader * 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 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 blender::gpu::Shader * get_shader_program()=0
virtual int get_tex_coord_attrib_location()
blender::gpu::Shader * shader_program_
blender::gpu::Shader * bind(const int width, const int height) override
blender::gpu::Shader * get_shader_program() override
BlenderDisplaySpaceShader(BL::RenderEngine &b_engine, BL::Scene &b_scene)
blender::gpu::Shader * get_shader_program() override
blender::gpu::Shader * bind(const int width, const int height) override
blender::gpu::Shader * shader_program_
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
blender::gpu::Texture * gpu_texture
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
#define assert(assertion)
TEX_TEMPLATE DataVec texture(T, FltCoord, float=0.0f) RET
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:135
#define DCHECK_NOTNULL(expression)
Definition log.h:137
#define LOG_ERROR
Definition log.h:101
#define LOG_TRACE
Definition log.h:108
#define make_float2
struct BlenderDisplayDriver::Tiles::@220260256064215041160000166140037002343373066044 finished_tiles
static constexpr GPUSamplerState default_sampler()
float x
float y
Definition half.h:60
max
Definition text_draw.cc:251