Blender V4.3
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_shader.hh"
8#include "GPU_state.hh"
9#include "GPU_texture.hh"
10
11#include "RE_engine.h"
12
14
15#include "device/device.h"
16#include "util/log.h"
17#include "util/math.h"
18
20
21/* --------------------------------------------------------------------
22 * BlenderDisplayShader.
23 */
24
25unique_ptr<BlenderDisplayShader> BlenderDisplayShader::create(BL::RenderEngine &b_engine,
26 BL::Scene &b_scene)
27{
28 if (b_engine.support_display_space_shader(b_scene)) {
29 return make_unique<BlenderDisplaySpaceShader>(b_engine, b_scene);
30 }
31
32 return make_unique<BlenderFallbackDisplayShader>();
33}
34
44
54
55/* --------------------------------------------------------------------
56 * BlenderFallbackDisplayShader.
57 */
59{
60 /* NOTE: Compilation errors are logged to console. */
61 GPUShader *shader = GPU_shader_create_from_info_name("gpu_shader_cycles_display_fallback");
62 return shader;
63}
64
66{
68
69 if (!shader_program_) {
70 return nullptr;
71 }
72
73 /* Bind shader now to enable uniform assignment. */
75 int slot = 0;
77 float size[2];
78 size[0] = width;
79 size[1] = height;
81 return shader_program_;
82}
83
88
93
95{
97 return;
98 }
99
101
103 if (!shader_program_) {
104 LOG(ERROR) << "Failed to compile fallback shader";
105 return;
106 }
107
109 if (image_texture_location_ < 0) {
110 LOG(ERROR) << "Shader doesn't contain the 'image_texture' uniform.";
112 return;
113 }
114
116 if (fullscreen_location_ < 0) {
117 LOG(ERROR) << "Shader doesn't contain the 'fullscreen' uniform.";
119 return;
120 }
121}
122
130
131/* --------------------------------------------------------------------
132 * BlenderDisplaySpaceShader.
133 */
134
136 BL::Scene &b_scene)
137 : b_engine_(b_engine), b_scene_(b_scene)
138{
139 DCHECK(b_engine_.support_display_space_shader(b_scene_));
140}
141
142GPUShader *BlenderDisplaySpaceShader::bind(int /*width*/, int /*height*/)
143{
144 b_engine_.bind_display_space_shader(b_scene_);
145 return GPU_shader_get_bound();
146}
147
149{
150 b_engine_.unbind_display_space_shader();
151}
152
154{
155 if (!shader_program_) {
157 }
158 if (!shader_program_) {
159 LOG(ERROR) << "Error retrieving shader program for display space shader.";
160 }
161
162 return shader_program_;
163}
164
165/* --------------------------------------------------------------------
166 * DrawTile.
167 */
168
169/* Higher level representation of a texture from the graphics library. */
171 public:
172 /* Global counter for all allocated GPUTextures used by instances of this class. */
173 static inline std::atomic<int> num_used = 0;
174
175 DisplayGPUTexture() = default;
176
178 {
179 assert(gpu_texture == nullptr);
180 }
181
182 DisplayGPUTexture(const DisplayGPUTexture &other) = delete;
184
186 : gpu_texture(other.gpu_texture), width(other.width), height(other.height)
187 {
188 other.reset();
189 }
190
192 {
193 if (this == &other) {
194 return *this;
195 }
196
197 gpu_texture = other.gpu_texture;
198 width = other.width;
199 height = other.height;
200
201 other.reset();
202
203 return *this;
204 }
205
206 bool gpu_resources_ensure(const uint texture_width, const uint texture_height)
207 {
208 if (width != texture_width || height != texture_height) {
210 }
211
212 if (gpu_texture) {
213 return true;
214 }
215
216 width = texture_width;
217 height = texture_height;
218
219 /* Texture must have a minimum size of 1x1. */
220 gpu_texture = GPU_texture_create_2d("CyclesBlitTexture",
221 max(width, 1),
222 max(height, 1),
223 1,
226 nullptr);
227
228 if (!gpu_texture) {
229 LOG(ERROR) << "Error creating texture.";
230 return false;
231 }
232
235
236 ++num_used;
237
238 return true;
239 }
240
242 {
243 if (gpu_texture == nullptr) {
244 return;
245 }
246
248
249 reset();
250
251 --num_used;
252 }
253
254 /* Texture resource allocated by the GPU module.
255 *
256 * NOTE: Allocated on the render engine's context. */
257 GPUTexture *gpu_texture = nullptr;
258
259 /* Dimensions of the texture in pixels. */
260 int width = 0;
261 int height = 0;
262
263 protected:
264 void reset()
265 {
266 gpu_texture = nullptr;
267 width = 0;
268 height = 0;
269 }
270};
271
272/* Higher level representation of a Pixel Buffer Object (PBO) from the graphics library. */
274 public:
275 /* Global counter for all allocated GPU module PBOs used by instances of this class. */
276 static inline std::atomic<int> num_used = 0;
277
279
281 {
282 assert(gpu_pixel_buffer == nullptr);
283 }
284
287
289 : gpu_pixel_buffer(other.gpu_pixel_buffer), width(other.width), height(other.height)
290 {
291 other.reset();
292 }
293
295 {
296 if (this == &other) {
297 return *this;
298 }
299
301 width = other.width;
302 height = other.height;
303
304 other.reset();
305
306 return *this;
307 }
308
309 bool gpu_resources_ensure(const uint new_width, const uint new_height)
310 {
311 const size_t required_size = sizeof(half4) * new_width * new_height * 4;
312
313 /* Try to re-use the existing PBO if it has usable size. */
314 if (gpu_pixel_buffer) {
315 if (new_width != width || new_height != height ||
317 {
319 }
320 }
321
322 /* Update size. */
323 width = new_width;
324 height = new_height;
325
326 /* Create pixel buffer if not already created. */
327 if (!gpu_pixel_buffer) {
329 }
330
331 if (gpu_pixel_buffer == nullptr) {
332 LOG(ERROR) << "Error creating texture pixel buffer object.";
333 return false;
334 }
335
336 ++num_used;
337
338 return true;
339 }
340
342 {
343 if (!gpu_pixel_buffer) {
344 return;
345 }
346
348 gpu_pixel_buffer = nullptr;
349
350 reset();
351
352 --num_used;
353 }
354
355 /* Pixel Buffer Object allocated by the GPU module.
356 *
357 * NOTE: Allocated on the render engine's context. */
358 GPUPixelBuffer *gpu_pixel_buffer = nullptr;
359
360 /* Dimensions of the PBO. */
361 int width = 0;
362 int height = 0;
363
364 protected:
365 void reset()
366 {
368 width = 0;
369 height = 0;
370 }
371};
372
373class DrawTile {
374 public:
375 DrawTile() = default;
376 ~DrawTile() = default;
377
378 DrawTile(const DrawTile &other) = delete;
379 DrawTile &operator=(const DrawTile &other) = delete;
380
381 DrawTile(DrawTile &&other) noexcept = default;
382
383 DrawTile &operator=(DrawTile &&other) = default;
384
386 {
387 texture.gpu_resources_destroy();
388 }
389
390 inline bool ready_to_draw() const
391 {
392 return texture.gpu_texture != 0;
393 }
394
395 /* Texture which contains pixels of the tile. */
397
398 /* Display parameters the texture of this tile has been updated for. */
400};
401
414
415/* --------------------------------------------------------------------
416 * BlenderDisplayDriver.
417 */
418
420 /* Resources of a tile which is being currently rendered. */
422
423 /* All tiles which rendering is finished and which content will not be changed. */
424 struct {
426
427 void gl_resources_destroy_and_clear()
428 {
429 for (DrawTile &tile : tiles) {
430 tile.gpu_resources_destroy();
431 }
432
433 tiles.clear();
434 }
436};
437
439 BL::Scene &b_scene,
440 const bool background)
441 : b_engine_(b_engine),
442 background_(background),
443 display_shader_(BlenderDisplayShader::create(b_engine, b_scene)),
444 tiles_(make_unique<Tiles>())
445{
446 /* Create context while on the main thread. */
448}
449
454
455/* --------------------------------------------------------------------
456 * Update procedure.
457 */
458
460{
461 if (!tiles_->current_tile.tile.ready_to_draw()) {
462 LOG(ERROR)
463 << "Unexpectedly moving to the next tile without any data provided for current tile.";
464 return;
465 }
466
467 /* Moving to the next tile without giving render data for the current tile is not an expected
468 * situation. */
470 /* Texture should have been updated from the PBO at this point. */
471 DCHECK(!tiles_->current_tile.need_update_texture_pixels);
472
473 tiles_->finished_tiles.tiles.emplace_back(std::move(tiles_->current_tile.tile));
474}
475
477 int texture_width,
478 int texture_height)
479{
480 /* Note that it's the responsibility of BlenderDisplayDriver to ensure updating and drawing
481 * the texture does not happen at the same time. This is achieved indirectly.
482 *
483 * When enabling the OpenGL/GPU context, it uses an internal mutex lock DST.gpu_context_lock.
484 * This same lock is also held when do_draw() is called, which together ensure mutual
485 * exclusion.
486 *
487 * This locking is not performed on the Cycles side, because that would cause lock inversion. */
488 if (!gpu_context_enable()) {
489 return false;
490 }
491
493
494 DrawTile &current_tile = tiles_->current_tile.tile;
495 DisplayGPUPixelBuffer &current_tile_buffer_object = tiles_->current_tile.buffer_object;
496
497 /* Clear storage of all finished tiles when display clear is requested.
498 * Do it when new tile data is provided to handle the display clear flag in a single place.
499 * It also makes the logic reliable from the whether drawing did happen or not point of view. */
500 if (need_clear_) {
501 tiles_->finished_tiles.gl_resources_destroy_and_clear();
502 need_clear_ = false;
503 }
504
505 /* Update PBO dimensions if needed.
506 *
507 * NOTE: Allocate the PBO for the size which will fit the final render resolution (as in,
508 * at a resolution divider 1. This was we don't need to recreate graphics interoperability
509 * objects which are costly and which are tied to the specific underlying buffer size.
510 * The downside of this approach is that when graphics interoperability is not used we are
511 * sending too much data to GPU when resolution divider is not 1. */
512 /* TODO(sergey): Investigate whether keeping the PBO exact size of the texture makes non-interop
513 * mode faster. */
514 const int buffer_width = params.size.x;
515 const int buffer_height = params.size.y;
516
517 if (!current_tile_buffer_object.gpu_resources_ensure(buffer_width, buffer_height) ||
518 !current_tile.texture.gpu_resources_ensure(texture_width, texture_height))
519 {
520 tiles_->current_tile.gpu_resources_destroy();
522 return false;
523 }
524
525 /* Store an updated parameters of the current tile.
526 * In theory it is only needed once per update of the tile, but doing it on every update is
527 * the easiest and is not expensive. */
528 tiles_->current_tile.tile.params = params;
529
530 return true;
531}
532
534{
535 const DisplayGPUTexture &texture = tile.tile.texture;
536
537 if (!DCHECK_NOTNULL(tile.buffer_object.gpu_pixel_buffer)) {
538 LOG(ERROR) << "Display driver tile pixel buffer unavailable.";
539 return;
540 }
543 tile.buffer_object.gpu_pixel_buffer,
544 0,
545 0,
546 0,
547 texture.width,
548 texture.height,
549 0);
550}
551
553{
554 /* Unpack the PBO into the texture as soon as the new content is provided.
555 *
556 * This allows to ensure that the unpacking happens while resources like graphics interop (which
557 * lifetime is outside of control of the display driver) are still valid, as well as allows to
558 * move the tile from being current to finished immediately after this call.
559 *
560 * One concern with this approach is that if the update happens more often than drawing then
561 * doing the unpack here occupies GPU transfer for no good reason. However, the render scheduler
562 * takes care of ensuring updates don't happen that often. In regular applications redraw will
563 * happen much more often than this update.
564 *
565 * On some older GPUs on macOS, there is a driver crash when updating the texture for viewport
566 * renders while Blender is drawing. As a workaround update texture during draw, under assumption
567 * that there is no graphics interop on macOS and viewport render has a single tile. */
568 if (!background_ &&
570 {
571 tiles_->current_tile.need_update_texture_pixels = true;
572 }
573 else {
574 update_tile_texture_pixels(tiles_->current_tile);
575 }
576
577 /* Ensure GPU fence exists to synchronize upload. */
579
580 GPU_flush();
581
583}
584
585/* --------------------------------------------------------------------
586 * Texture buffer mapping.
587 */
588
590{
591 GPUPixelBuffer *pix_buf = tiles_->current_tile.buffer_object.gpu_pixel_buffer;
592 if (!DCHECK_NOTNULL(pix_buf)) {
593 LOG(ERROR) << "Display driver tile pixel buffer unavailable.";
594 return nullptr;
595 }
596 half4 *mapped_rgba_pixels = reinterpret_cast<half4 *>(GPU_pixel_buffer_map(pix_buf));
597 if (!mapped_rgba_pixels) {
598 LOG(ERROR) << "Error mapping BlenderDisplayDriver pixel buffer object.";
599 }
600 return mapped_rgba_pixels;
601}
602
604{
605 GPUPixelBuffer *pix_buf = tiles_->current_tile.buffer_object.gpu_pixel_buffer;
606 if (!DCHECK_NOTNULL(pix_buf)) {
607 LOG(ERROR) << "Display driver tile pixel buffer unavailable.";
608 return;
609 }
610 GPU_pixel_buffer_unmap(pix_buf);
611}
612
613/* --------------------------------------------------------------------
614 * Graphics interoperability.
615 */
616
618{
619 GraphicsInterop interop_dst;
620
621 interop_dst.buffer_width = tiles_->current_tile.buffer_object.width;
622 interop_dst.buffer_height = tiles_->current_tile.buffer_object.height;
624 tiles_->current_tile.buffer_object.gpu_pixel_buffer);
625
626 return interop_dst;
627}
628
633
638
639/* --------------------------------------------------------------------
640 * Drawing.
641 */
642
644{
645 need_clear_ = true;
646}
647
648void BlenderDisplayDriver::set_zoom(float zoom_x, float zoom_y)
649{
650 zoom_ = make_float2(zoom_x, zoom_y);
651}
652
653/* Update vertex buffer with new coordinates of vertex positions and texture coordinates.
654 * This buffer is used to render texture in the viewport.
655 *
656 * NOTE: The buffer needs to be bound. */
658 int texcoord_attribute,
659 int position_attribute)
660{
661 const int x = params.full_offset.x;
662 const int y = params.full_offset.y;
663
664 const int width = params.size.x;
665 const int height = params.size.y;
666
668
669 immAttr2f(texcoord_attribute, 1.0f, 0.0f);
670 immVertex2f(position_attribute, x + width, y);
671
672 immAttr2f(texcoord_attribute, 1.0f, 1.0f);
673 immVertex2f(position_attribute, x + width, y + height);
674
675 immAttr2f(texcoord_attribute, 0.0f, 0.0f);
676 immVertex2f(position_attribute, x, y);
677
678 immAttr2f(texcoord_attribute, 0.0f, 1.0f);
679 immVertex2f(position_attribute, x, y + height);
680
681 immEnd();
682}
683
684static void draw_tile(const float2 &zoom,
685 const int texcoord_attribute,
686 const int position_attribute,
687 const DrawTile &draw_tile)
688{
689 if (!draw_tile.ready_to_draw()) {
690 return;
691 }
692
693 const DisplayGPUTexture &texture = draw_tile.texture;
694
695 if (!DCHECK_NOTNULL(texture.gpu_texture)) {
696 LOG(ERROR) << "Display driver tile GPU texture resource unavailable.";
697 return;
698 }
699
700 /* Trick to keep sharp rendering without jagged edges on all GPUs.
701 *
702 * The idea here is to enforce driver to use linear interpolation when the image is zoomed out.
703 * For the render result with a resolution divider in effect we always use nearest interpolation.
704 *
705 * Use explicit MIN assignment to make sure the driver does not have an undefined behavior at
706 * the zoom level 1. The MAG filter is always NEAREST. */
707 const float zoomed_width = draw_tile.params.size.x * zoom.x;
708 const float zoomed_height = draw_tile.params.size.y * zoom.y;
709 if (texture.width != draw_tile.params.size.x || texture.height != draw_tile.params.size.y) {
710 /* Resolution divider is different from 1, force nearest interpolation. */
711 GPU_texture_bind_ex(texture.gpu_texture, GPUSamplerState::default_sampler(), 0);
712 }
713 else if (zoomed_width - draw_tile.params.size.x > -0.5f ||
714 zoomed_height - draw_tile.params.size.y > -0.5f)
715 {
716 GPU_texture_bind_ex(texture.gpu_texture, GPUSamplerState::default_sampler(), 0);
717 }
718 else {
719 GPU_texture_bind_ex(texture.gpu_texture, {GPU_SAMPLER_FILTERING_LINEAR}, 0);
720 }
721
722 /* Draw at the parameters for which the texture has been updated for. This allows to always draw
723 * texture during bordered-rendered camera view without flickering. The validness of the display
724 * parameters for a texture is guaranteed by the initial "clear" state which makes drawing to
725 * have an early output.
726 *
727 * Such approach can cause some extra "jelly" effect during panning, but it is not more jelly
728 * than overlay of selected objects. Also, it's possible to redraw texture at an intersection of
729 * the texture draw parameters and the latest updated draw parameters (although, complexity of
730 * doing it might not worth it. */
731 vertex_draw(draw_tile.params, texcoord_attribute, position_attribute);
732}
733
735{
736 /* This is called from the render thread that also calls update_begin/end, right before ending
737 * the render loop. We wait for any queued PBO and render commands to be done, before destroying
738 * the render thread and activating the context in the main thread to destroy resources.
739 *
740 * If we don't do this, the NVIDIA driver hangs for a few seconds for when ending 3D viewport
741 * rendering, for unknown reasons. This was found with NVIDIA driver version 470.73 and a Quadro
742 * RTX 6000 on Linux. */
743 if (!gpu_context_enable()) {
744 return;
745 }
746
749
751}
752
754{
756
757 if (need_clear_) {
758 /* Texture is requested to be cleared and was not yet cleared.
759 *
760 * Do early return which should be equivalent of drawing all-zero texture.
761 * Watch out for the lock though so that the clear happening during update is properly
762 * synchronized here. */
764 return;
765 }
766
769
770 GPUShader *active_shader = display_shader_->bind(params.full_size.x, params.full_size.y);
771
773 const int texcoord_attribute = GPU_vertformat_attr_add(
774 format, display_shader_->tex_coord_attribute_name, GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
775 const int position_attribute = GPU_vertformat_attr_add(
776 format, display_shader_->position_attribute_name, GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
777
778 /* NOTE: Shader is bound again through IMM to register this shader with the IMM module
779 * and perform required setup for IMM rendering. This is required as the IMM module
780 * needs to be aware of which shader is bound, and the main display shader
781 * is bound externally. */
782 immBindShader(active_shader);
783
784 if (tiles_->current_tile.need_update_texture_pixels) {
785 update_tile_texture_pixels(tiles_->current_tile);
786 tiles_->current_tile.need_update_texture_pixels = false;
787 }
788
789 draw_tile(zoom_, texcoord_attribute, position_attribute, tiles_->current_tile.tile);
790
791 for (const DrawTile &tile : tiles_->finished_tiles.tiles) {
792 draw_tile(zoom_, texcoord_attribute, position_attribute, tile);
793 }
794
795 /* Reset IMM shader bind state. */
797
798 display_shader_->unbind();
799
801
803 GPU_flush();
804
806
807 VLOG_DEVICE_STATS << "Display driver number of textures: " << DisplayGPUTexture::num_used;
808 VLOG_DEVICE_STATS << "Display driver number of PBOs: " << DisplayGPUPixelBuffer::num_used;
809}
810
812{
813 if (!RE_engine_gpu_context_create(reinterpret_cast<RenderEngine *>(b_engine_.ptr.data))) {
814 LOG(ERROR) << "Error creating GPU context.";
815 return;
816 }
817
818 /* Create global GPU resources for display driver. */
819 if (!gpu_resources_create()) {
820 LOG(ERROR) << "Error creating GPU resources for Cycles Display Driver.";
821 return;
822 }
823}
824
826{
827 return RE_engine_gpu_context_enable(reinterpret_cast<RenderEngine *>(b_engine_.ptr.data));
828}
829
834
839
844
849
851{
852 /* Ensure context is active for resource creation. */
853 if (!gpu_context_enable()) {
854 LOG(ERROR) << "Error enabling GPU context.";
855 return false;
856 }
857
860
862 LOG(ERROR) << "Error creating GPU synchronization primitives.";
863 assert(0);
864 return false;
865 }
866
868 return true;
869}
870
872{
874
875 tiles_->current_tile.gpu_resources_destroy();
876 tiles_->finished_tiles.gl_resources_destroy_and_clear();
877
878 /* Fences. */
879 if (gpu_render_sync_) {
881 gpu_render_sync_ = nullptr;
882 }
883 if (gpu_upload_sync_) {
885 gpu_upload_sync_ = nullptr;
886 }
887
889
891}
892
unsigned int uint
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)
@ 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)
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_bind(GPUShader *shader)
void GPU_shader_free(GPUShader *shader)
void GPU_shader_unbind()
GPUShader * GPU_shader_get_bound()
void GPU_flush()
Definition gpu_state.cc:294
@ 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:379
void GPU_fence_wait(GPUFence *fence)
Definition gpu_state.cc:395
void GPU_fence_signal(GPUFence *fence)
Definition gpu_state.cc:390
void GPU_fence_free(GPUFence *fence)
Definition gpu_state.cc:385
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)
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)
int64_t GPU_pixel_buffer_get_native_handle(GPUPixelBuffer *pixel_buf)
@ 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)
GPUPixelBuffer * GPU_pixel_buffer_create(size_t byte_size)
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
static void update_tile_texture_pixels(const DrawTileAndPBO &tile)
static GPUShader * compile_fallback_shader(void)
static void vertex_draw(const DisplayDriver::Params &params, int texcoord_attribute, int position_attribute)
static void draw_tile(const float2 &zoom, const int texcoord_attribute, const int position_attribute, const DrawTile &draw_tile)
struct GPUShader GPUShader
virtual half4 * map_texture_buffer() override
virtual void unmap_texture_buffer() override
virtual void clear() override
virtual bool update_begin(const Params &params, int texture_width, int texture_height) override
std::atomic< bool > need_clear_
virtual void graphics_interop_activate() override
virtual GraphicsInterop graphics_interop_get() override
virtual void draw(const Params &params) override
void set_zoom(float zoom_x, float zoom_y)
virtual void flush() override
virtual void update_end() override
unique_ptr< BlenderDisplayShader > display_shader_
virtual void graphics_interop_deactivate() override
virtual void next_tile_begin() override
BlenderDisplayDriver(BL::RenderEngine &b_engine, BL::Scene &b_scene, const bool background)
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()
virtual GPUShader * get_shader_program() override
BlenderDisplaySpaceShader(BL::RenderEngine &b_engine, BL::Scene &b_scene)
virtual GPUShader * bind(int width, int height) override
virtual GPUShader * bind(int width, int height) override
virtual GPUShader * get_shader_program() override
DisplayGPUPixelBuffer()=default
static std::atomic< int > num_used
DisplayGPUPixelBuffer(const DisplayGPUPixelBuffer &other)=delete
DisplayGPUPixelBuffer & operator=(DisplayGPUPixelBuffer &other)=delete
bool gpu_resources_ensure(const uint new_width, const uint new_height)
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
#define CCL_NAMESPACE_END
ccl_device_forceinline float2 make_float2(const float x, const float y)
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)
ccl_global const KernelWorkTile * tile
format
#define DCHECK(expression)
Definition log.h:51
#define DCHECK_NOTNULL(expression)
Definition log.h:53
#define VLOG_DEVICE_STATS
Definition log.h:78
#define LOG(severity)
Definition log.h:33
struct BlenderDisplayDriver::Tiles::@1413 finished_tiles
static constexpr GPUSamplerState default_sampler()
float x
float y
Definition half.h:61
float max