Blender V5.0
vk_framebuffer.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2022 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "vk_framebuffer.hh"
10#include "vk_backend.hh"
11#include "vk_context.hh"
12#include "vk_state_manager.hh"
13#include "vk_texture.hh"
14
15namespace blender::gpu {
16
21{
22 return {GPU_LOADACTION_LOAD, GPU_STOREACTION_STORE, {0.0f, 0.0f, 0.0f, 0.0f}};
23}
24
25/* -------------------------------------------------------------------- */
28
33{
34 size_set(1, 1);
35 srgb_ = false;
36 enabled_srgb_ = false;
37}
38
40{
41 VKContext *context = VKContext::get();
42 if (context && context->active_framebuffer_get() == this) {
43 context->deactivate_framebuffer();
44 }
45}
46
48
49void VKFrameBuffer::bind(bool enabled_srgb)
50{
51 VKContext &context = *VKContext::get();
52 /* Updating attachments can issue pipeline barriers, this should be done outside the render pass.
53 * When done inside a render pass there should be a self-dependency between sub-passes on the
54 * active render pass. As the active render pass isn't aware of the new render pass (and should
55 * not) it is better to deactivate it before updating the attachments. For more information check
56 * `VkSubpassDependency`. */
57 if (context.has_active_framebuffer()) {
58 context.deactivate_framebuffer();
59 }
60
61 context.activate_framebuffer(*this);
65
66 enabled_srgb_ = enabled_srgb;
67 Shader::set_framebuffer_srgb_target(enabled_srgb && srgb_);
68 load_stores.fill(default_load_store());
69 attachment_states_.fill(GPU_ATTACHMENT_WRITE);
70}
71
73{
74 BLI_assert(r_viewports.is_empty());
75 for (int64_t index : IndexRange(this->multi_viewport_ ? GPU_MAX_VIEWPORTS : 1)) {
76 VkViewport viewport;
77 viewport.x = viewport_[index][0];
78 viewport.y = viewport_[index][1];
79 viewport.width = viewport_[index][2];
80 viewport.height = viewport_[index][3];
81 viewport.minDepth = 0.0f;
82 viewport.maxDepth = 1.0f;
83 r_viewports.append(viewport);
84 }
85}
86
87void VKFrameBuffer::render_area_update(VkRect2D &render_area) const
88{
89 if (scissor_test_get()) {
90 int scissor_rect[4];
91 scissor_get(scissor_rect);
92 render_area.offset.x = clamp_i(scissor_rect[0], 0, width_);
93 render_area.offset.y = clamp_i(scissor_rect[1], 0, height_);
94 render_area.extent.width = clamp_i(scissor_rect[2], 1, width_ - scissor_rect[0]);
95 render_area.extent.height = clamp_i(scissor_rect[3], 1, height_ - scissor_rect[1]);
96 }
97 else {
98 render_area.offset.x = 0;
99 render_area.offset.y = 0;
100 render_area.extent.width = width_;
101 render_area.extent.height = height_;
102 }
103
104#ifndef NDEBUG
105 const VKDevice &device = VKBackend::get().device;
106 BLI_assert(render_area.offset.x + render_area.extent.width <=
107 device.physical_device_properties_get().limits.maxFramebufferWidth);
108 BLI_assert(render_area.offset.y + render_area.extent.height <=
109 device.physical_device_properties_get().limits.maxFramebufferHeight);
110#endif
111}
112
114{
115 BLI_assert(r_render_areas.is_empty());
116 VkRect2D render_area;
117 render_area_update(render_area);
118 r_render_areas.append_n_times(render_area, this->multi_viewport_ ? GPU_MAX_VIEWPORTS : 1);
119}
120
121bool VKFrameBuffer::check(char /*err_out*/[256])
122{
123 return true;
124}
125
126void VKFrameBuffer::build_clear_attachments_depth_stencil(
128 float clear_depth,
129 uint32_t clear_stencil,
131{
132 VkImageAspectFlags aspect_mask = (buffers & GPU_DEPTH_BIT ? VK_IMAGE_ASPECT_DEPTH_BIT : 0) |
133 (buffers & GPU_STENCIL_BIT ? VK_IMAGE_ASPECT_STENCIL_BIT : 0);
134
135 VkClearAttachment &clear_attachment =
136 clear_attachments.attachments[clear_attachments.attachment_count++];
137 clear_attachment.aspectMask = aspect_mask;
138 clear_attachment.clearValue.depthStencil.depth = clear_depth;
139 clear_attachment.clearValue.depthStencil.stencil = clear_stencil;
140 clear_attachment.colorAttachment = 0;
141}
142
143void VKFrameBuffer::build_clear_attachments_color(
144 const float (*clear_colors)[4],
145 const bool multi_clear_colors,
147{
148 int color_index = 0;
149 for (int color_slot = 0; color_slot < GPU_FB_MAX_COLOR_ATTACHMENT; color_slot++) {
150 const GPUAttachment &attachment = attachments_[GPU_FB_COLOR_ATTACHMENT0 + color_slot];
151 if (attachment.tex == nullptr) {
152 continue;
153 }
154 VkClearAttachment &clear_attachment =
155 clear_attachments.attachments[clear_attachments.attachment_count++];
156 clear_attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
157 clear_attachment.colorAttachment = color_slot;
159 clear_attachment.clearValue.color = to_vk_clear_color_value(data_format,
160 &clear_colors[color_index]);
161
162 color_index += multi_clear_colors ? 1 : 0;
163 }
164}
165
166/* -------------------------------------------------------------------- */
169
171{
172 VKContext &context = *VKContext::get();
173 rendering_ensure(context);
174 context.render_graph().add_node(clear_attachments);
175}
176
178 const float clear_color[4],
179 float clear_depth,
180 uint clear_stencil)
181{
183 render_area_update(clear_attachments.vk_clear_rect.rect);
184 clear_attachments.vk_clear_rect.baseArrayLayer = 0;
185 clear_attachments.vk_clear_rect.layerCount = 1;
186
188 VKContext &context = *VKContext::get();
189 GPUWriteMask needed_mask = GPU_WRITE_NONE;
190 if (buffers & GPU_DEPTH_BIT) {
191 needed_mask |= GPU_WRITE_DEPTH;
192 }
193 if (buffers & GPU_STENCIL_BIT) {
194 needed_mask |= GPU_WRITE_STENCIL;
195 }
196
197 /* Clearing depth via #vkCmdClearAttachments requires a render pass with write depth or stencil
198 * enabled. When not enabled, clearing should be done via texture directly. */
199 /* WORKAROUND: Clearing depth attachment when using dynamic rendering are not working on AMD
200 * official drivers.
201 * See #129265 */
202 if ((context.state_manager_get().state.write_mask & needed_mask) == needed_mask &&
204 {
205 build_clear_attachments_depth_stencil(
206 buffers, clear_depth, clear_stencil, clear_attachments);
207 }
208 else {
209 const GPUAttachment &attachment = depth_attachment();
210 VKTexture *depth_texture = unwrap(unwrap(attachment.tex));
211 if (depth_texture != nullptr) {
212 depth_texture->clear_depth_stencil(
213 buffers,
214 clear_depth,
215 clear_stencil,
216 attachment.layer == -1 ? std::nullopt : std::make_optional(attachment.layer));
217 }
218 }
219 }
220 if (buffers & GPU_COLOR_BIT) {
221 float clear_color_single[4];
222 copy_v4_v4(clear_color_single, clear_color);
223 build_clear_attachments_color(&clear_color_single, false, clear_attachments);
224 }
225
226 if (clear_attachments.attachment_count) {
227 clear(clear_attachments);
228 }
229}
230
231void VKFrameBuffer::clear_multi(const float (*clear_color)[4])
232{
234 render_area_update(clear_attachments.vk_clear_rect.rect);
235 clear_attachments.vk_clear_rect.baseArrayLayer = 0;
236 clear_attachments.vk_clear_rect.layerCount = 1;
237
238 build_clear_attachments_color(clear_color, true, clear_attachments);
239 if (clear_attachments.attachment_count) {
240 clear(clear_attachments);
241 }
242}
243
245 eGPUDataFormat /*data_format*/,
246 const void * /*clear_value*/)
247{
248 /* Clearing of a single attachment was added to implement `clear_multi` in OpenGL. As
249 * `clear_multi` is supported in Vulkan it isn't needed to implement this method.
250 */
252}
253
255
256/* -------------------------------------------------------------------- */
259
261{
262 load_stores[type] = ls;
263}
264
265static VkAttachmentLoadOp to_vk_attachment_load_op(GPULoadOp load_op)
266{
267 switch (load_op) {
269 return VK_ATTACHMENT_LOAD_OP_DONT_CARE;
271 return VK_ATTACHMENT_LOAD_OP_CLEAR;
273 return VK_ATTACHMENT_LOAD_OP_LOAD;
274 }
276 return VK_ATTACHMENT_LOAD_OP_LOAD;
277}
278
279static VkAttachmentStoreOp to_vk_attachment_store_op(GPUStoreOp store_op)
280{
281 switch (store_op) {
283 return VK_ATTACHMENT_STORE_OP_DONT_CARE;
285 return VK_ATTACHMENT_STORE_OP_STORE;
286 }
288 return VK_ATTACHMENT_STORE_OP_STORE;
289}
290
291static void set_load_store(VkRenderingAttachmentInfo &r_rendering_attachment,
292 const GPULoadStore &ls)
293{
294 copy_v4_v4(r_rendering_attachment.clearValue.color.float32, ls.clear_value);
295 r_rendering_attachment.loadOp = to_vk_attachment_load_op(ls.load_action);
296 r_rendering_attachment.storeOp = to_vk_attachment_store_op(ls.store_action);
297}
298
300
301/* -------------------------------------------------------------------- */
304
306 Span<GPUAttachmentState> color_attachment_states)
307{
308 const VKDevice &device = VKBackend::get().device;
309 const bool supports_local_read = device.extensions_get().dynamic_rendering_local_read;
310
311 attachment_states_[GPU_FB_DEPTH_ATTACHMENT] = depth_attachment_state;
312 attachment_states_.as_mutable_span()
313 .slice(GPU_FB_COLOR_ATTACHMENT0, color_attachment_states.size())
314 .copy_from(color_attachment_states);
315
316 if (supports_local_read) {
317 VKContext &context = *VKContext::get();
318
319 for (int index : IndexRange(color_attachment_states.size())) {
320 if (color_attachment_states[index] == GPU_ATTACHMENT_READ) {
322 if (texture) {
323 context.state_manager_get().image_bind(texture, index);
324 }
325 }
326 }
327 if (is_rendering_) {
328 is_rendering_ = false;
329 load_stores.fill(default_load_store());
330 }
331 }
332 else {
333 VKContext &context = *VKContext::get();
334 if (is_rendering_) {
335 rendering_end(context);
336
337 /* TODO: this might need a better implementation:
338 * READ -> DONTCARE
339 * WRITE -> LOAD, STORE based on previous value.
340 * IGNORE -> DONTCARE -> IGNORE */
341 load_stores.fill(default_load_store());
342 }
343
344 for (int index : IndexRange(color_attachment_states.size())) {
345 if (color_attachment_states[index] == GPU_ATTACHMENT_READ) {
347 if (texture) {
348 context.state_manager_get().texture_bind(
350 }
351 }
352 }
353 }
354}
355
357
358/* -------------------------------------------------------------------- */
361
364 const int area[4],
365 int /*channel_len*/,
366 int slot,
367 void *r_data)
368{
369 GPUAttachment *attachment = nullptr;
370 switch (plane) {
371 case GPU_COLOR_BIT:
372 attachment = &attachments_[GPU_FB_COLOR_ATTACHMENT0 + slot];
373 break;
374
375 case GPU_DEPTH_BIT:
376 attachment = attachments_[GPU_FB_DEPTH_ATTACHMENT].tex ?
379 break;
380
381 default:
383 return;
384 }
385
386 VKTexture *texture = unwrap(unwrap(attachment->tex));
388 "Trying to read back texture from framebuffer, but no texture is available in "
389 "requested slot.");
390 if (texture == nullptr) {
391 return;
392 }
393 const int region[6] = {area[0], area[1], 0, area[0] + area[2], area[1] + area[3], 1};
394 IndexRange layers(max_ii(attachment->layer, 0), 1);
395 texture->read_sub(0, format, region, layers, r_data);
396}
397
399
400/* -------------------------------------------------------------------- */
403
404static void blit_aspect(VKContext &context,
405 VKTexture &dst_texture,
406 VKTexture &src_texture,
407 int dst_offset_x,
408 int dst_offset_y,
409 VkImageAspectFlags image_aspect)
410{
411 /* Prefer texture copy, as some platforms don't support using D32_SFLOAT_S8_UINT to be used as
412 * a blit destination. */
413 if (dst_offset_x == 0 && dst_offset_y == 0 &&
414 dst_texture.device_format_get() == src_texture.device_format_get() &&
415 src_texture.width_get() == dst_texture.width_get() &&
416 src_texture.height_get() == dst_texture.height_get())
417 {
418 src_texture.copy_to(dst_texture, image_aspect);
419 return;
420 }
421
423
424 blit_image.src_image = src_texture.vk_image_handle();
425 blit_image.dst_image = dst_texture.vk_image_handle();
426 blit_image.filter = VK_FILTER_NEAREST;
427
428 VkImageBlit &region = blit_image.region;
429 region.srcSubresource.aspectMask = image_aspect;
430 region.srcSubresource.mipLevel = 0;
431 region.srcSubresource.baseArrayLayer = 0;
432 region.srcSubresource.layerCount = 1;
433 region.srcOffsets[0].x = 0;
434 region.srcOffsets[0].y = 0;
435 region.srcOffsets[0].z = 0;
436 region.srcOffsets[1].x = src_texture.width_get();
437 region.srcOffsets[1].y = src_texture.height_get();
438 region.srcOffsets[1].z = 1;
439
440 region.dstSubresource.aspectMask = image_aspect;
441 region.dstSubresource.mipLevel = 0;
442 region.dstSubresource.baseArrayLayer = 0;
443 region.dstSubresource.layerCount = 1;
444 region.dstOffsets[0].x = clamp_i(dst_offset_x, 0, dst_texture.width_get());
445 region.dstOffsets[0].y = clamp_i(dst_offset_y, 0, dst_texture.height_get());
446 region.dstOffsets[0].z = 0;
447 region.dstOffsets[1].x = clamp_i(
448 dst_offset_x + src_texture.width_get(), 0, dst_texture.width_get());
449 region.dstOffsets[1].y = clamp_i(
450 dst_offset_y + src_texture.height_get(), 0, dst_texture.height_get());
451 region.dstOffsets[1].z = 1;
452
453 context.render_graph().add_node(blit_image);
454}
455
457 int src_slot,
458 FrameBuffer *dst,
459 int dst_slot,
460 int dst_offset_x,
461 int dst_offset_y)
462{
463 BLI_assert(dst);
465 "VKFrameBuffer::blit_to only supports a single color or depth aspect.");
466 UNUSED_VARS_NDEBUG(planes);
467
468 VKContext &context = *VKContext::get();
469 if (!context.has_active_framebuffer()) {
471 return;
472 }
473
474 VKFrameBuffer &dst_framebuffer = *unwrap(dst);
475 if (planes & GPU_COLOR_BIT) {
476 const GPUAttachment &src_attachment = attachments_[GPU_FB_COLOR_ATTACHMENT0 + src_slot];
477 const GPUAttachment &dst_attachment =
478 dst_framebuffer.attachments_[GPU_FB_COLOR_ATTACHMENT0 + dst_slot];
479 if (src_attachment.tex && dst_attachment.tex) {
480 VKTexture &src_texture = *unwrap(unwrap(src_attachment.tex));
481 VKTexture &dst_texture = *unwrap(unwrap(dst_attachment.tex));
482 blit_aspect(context,
483 dst_texture,
484 src_texture,
485 dst_offset_x,
486 dst_offset_y,
487 VK_IMAGE_ASPECT_COLOR_BIT);
488 }
489 }
490
491 if (planes & GPU_DEPTH_BIT) {
492 /* Retrieve source texture. */
493 const GPUAttachment &src_attachment = attachments_[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex ?
496 const GPUAttachment &dst_attachment =
499 dst_framebuffer.attachments_[GPU_FB_DEPTH_ATTACHMENT];
500 if (src_attachment.tex && dst_attachment.tex) {
501 VKTexture &src_texture = *unwrap(unwrap(src_attachment.tex));
502 VKTexture &dst_texture = *unwrap(unwrap(dst_attachment.tex));
503 blit_aspect(context,
504 dst_texture,
505 src_texture,
506 dst_offset_x,
507 dst_offset_y,
508 VK_IMAGE_ASPECT_DEPTH_BIT);
509 }
510 }
511}
512
514
515/* -------------------------------------------------------------------- */
518
520{
521 if (!dirty_attachments_) {
522 return;
523 }
524
525 for (int i = 0; i < GPU_FB_MAX_ATTACHMENT; i++) {
526 GPUAttachment &attachment = attachments_[i];
527 if (attachment.tex) {
528 int size[3];
529 GPU_texture_get_mipmap_size(attachment.tex, attachment.mip, size);
530 size_set(size[0], size[1]);
531 return;
532 }
533 }
534}
535
537{
540 if (texture) {
541 srgb_ = (texture->format_flag_get() & GPU_FORMAT_SRGB) != 0;
542 return;
543 }
544 }
545}
546
548{
549 int size = 0;
550 for (int color_slot : IndexRange(GPU_FB_MAX_COLOR_ATTACHMENT)) {
551 if (color_tex(color_slot) != nullptr) {
552 size = max_ii(color_slot + 1, size);
553 }
554 }
555 return size;
556}
557
559
561{
562 is_rendering_ = false;
563}
564
566 const VKExtensions &extensions)
567{
568 const VKDevice &device = VKBackend::get().device;
569 const bool supports_local_read = device.extensions_get().dynamic_rendering_local_read;
570
571 depth_attachment_format_ = VK_FORMAT_UNDEFINED;
572 stencil_attachment_format_ = VK_FORMAT_UNDEFINED;
573
575 render_graph::VKBeginRenderingNode::CreateInfo begin_rendering(access_info);
576 begin_rendering.node_data.vk_rendering_info.sType = VK_STRUCTURE_TYPE_RENDERING_INFO;
577 begin_rendering.node_data.vk_rendering_info.layerCount = 1;
578 render_area_update(begin_rendering.node_data.vk_rendering_info.renderArea);
579
580 color_attachment_formats_.clear();
581 int32_t max_filled_slot_index = -1;
582 for (int color_attachment_index :
584 {
585 const GPUAttachment &attachment = attachments_[color_attachment_index];
586 if (attachment.tex == nullptr) {
587 color_attachment_formats_.append(VK_FORMAT_UNDEFINED);
588 VkRenderingAttachmentInfo &attachment_info =
589 begin_rendering.node_data.color_attachments[begin_rendering.node_data.vk_rendering_info
590 .colorAttachmentCount++];
591 attachment_info = {VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
592 nullptr,
593 VK_NULL_HANDLE,
594 VK_IMAGE_LAYOUT_UNDEFINED,
595 VK_RESOLVE_MODE_NONE,
596 VK_NULL_HANDLE,
597 VK_IMAGE_LAYOUT_UNDEFINED,
598 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
599 VK_ATTACHMENT_STORE_OP_DONT_CARE};
600 continue;
601 }
602 max_filled_slot_index = color_attachment_index - GPU_FB_COLOR_ATTACHMENT0;
603
604 VKTexture &color_texture = *unwrap(unwrap(attachment.tex));
606 "Texture is used as an attachment, but doesn't have the "
607 "GPU_TEXTURE_USAGE_ATTACHMENT flag.");
608 /* To support `gpu_Layer` we need to set the layerCount to the number of layers it can
609 * access.
610 */
611 int layer_count = color_texture.layer_count();
612 if (attachment.layer == -1 && layer_count != 1) {
613 begin_rendering.node_data.vk_rendering_info.layerCount = max_ii(
614 begin_rendering.node_data.vk_rendering_info.layerCount, layer_count);
615 }
616
617 VkRenderingAttachmentInfo &attachment_info =
618 begin_rendering.node_data
619 .color_attachments[begin_rendering.node_data.vk_rendering_info.colorAttachmentCount++];
620 attachment_info.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
621
622 VkImageView vk_image_view = VK_NULL_HANDLE;
623 uint32_t layer_base = max_ii(attachment.layer, 0);
624 GPUAttachmentState attachment_state = attachment_states_[color_attachment_index];
625 VkFormat vk_format = to_vk_format(color_texture.device_format_get());
626 if (attachment_state == GPU_ATTACHMENT_WRITE) {
627 VKImageViewInfo image_view_info = {
629 IndexRange(layer_base,
630 layer_count != 1 ? max_ii(layer_count - layer_base, 1) : layer_count),
631 IndexRange(attachment.mip, 1),
632 {{'r', 'g', 'b', 'a'}},
633 false,
634 srgb_ && enabled_srgb_,
636 const VKImageView &image_view = color_texture.image_view_get(image_view_info);
637 vk_image_view = image_view.vk_handle();
638 vk_format = image_view.vk_format();
639 }
640 attachment_info.imageView = vk_image_view;
641 attachment_info.imageLayout = supports_local_read ? VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR :
642 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
643 set_load_store(attachment_info, load_stores[color_attachment_index]);
644
645 access_info.images.append(
646 {color_texture.vk_image_handle(),
647 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
648 VK_IMAGE_ASPECT_COLOR_BIT,
649 {0, VK_REMAINING_MIP_LEVELS, layer_base, VK_REMAINING_ARRAY_LAYERS}});
650 color_attachment_formats_.append(
651 (!extensions.dynamic_rendering_unused_attachments && vk_image_view == VK_NULL_HANDLE) ?
652 VK_FORMAT_UNDEFINED :
653 vk_format);
654 }
655 color_attachment_size = uint32_t(max_filled_slot_index + 1);
656 begin_rendering.node_data.vk_rendering_info.colorAttachmentCount = color_attachment_size;
657 begin_rendering.node_data.vk_rendering_info.pColorAttachments =
658 begin_rendering.node_data.color_attachments;
659
660 for (int depth_attachment_index : IndexRange(GPU_FB_DEPTH_ATTACHMENT, 2)) {
661 const GPUAttachment &attachment = attachments_[depth_attachment_index];
662
663 if (attachment.tex == nullptr) {
664 continue;
665 }
666 bool is_stencil_attachment = depth_attachment_index == GPU_FB_DEPTH_STENCIL_ATTACHMENT;
667 VKTexture &depth_texture = *unwrap(unwrap(attachment.tex));
669 "Texture is used as an attachment, but doesn't have the "
670 "GPU_TEXTURE_USAGE_ATTACHMENT flag.");
671 bool is_depth_stencil_attachment = to_vk_image_aspect_flag_bits(
672 depth_texture.device_format_get()) &
673 VK_IMAGE_ASPECT_STENCIL_BIT;
674 VkImageLayout vk_image_layout = is_depth_stencil_attachment ?
675 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL :
676 VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
677 GPUAttachmentState attachment_state = attachment_states_[GPU_FB_DEPTH_ATTACHMENT];
678 VkImageView depth_image_view = VK_NULL_HANDLE;
679 if (attachment_state == GPU_ATTACHMENT_WRITE) {
681 IndexRange(max_ii(attachment.layer, 0), 1),
682 IndexRange(attachment.mip, 1),
683 {{'r', 'g', 'b', 'a'}},
684 is_stencil_attachment,
685 false,
687 depth_image_view = depth_texture.image_view_get(image_view_info).vk_handle();
688 }
689 VkFormat vk_format = (!extensions.dynamic_rendering_unused_attachments &&
690 depth_image_view == VK_NULL_HANDLE) ?
691 VK_FORMAT_UNDEFINED :
692 to_vk_format(depth_texture.device_format_get());
693
694 /* TODO: we should be able to use a single attachment info and only set the
695 * #pDepthAttachment/#pStencilAttachment to the same struct.
696 * But perhaps the stencil clear op might be different. */
697 {
698 VkRenderingAttachmentInfo &attachment_info = begin_rendering.node_data.depth_attachment;
699 attachment_info.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
700 attachment_info.imageView = depth_image_view;
701 attachment_info.imageLayout = vk_image_layout;
702
703 set_load_store(attachment_info, load_stores[depth_attachment_index]);
704 depth_attachment_format_ = vk_format;
705 begin_rendering.node_data.vk_rendering_info.pDepthAttachment =
706 &begin_rendering.node_data.depth_attachment;
707 }
708
709 if (is_stencil_attachment) {
710 VkRenderingAttachmentInfo &attachment_info = begin_rendering.node_data.stencil_attachment;
711 attachment_info.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
712 attachment_info.imageView = depth_image_view;
713 attachment_info.imageLayout = vk_image_layout;
714
715 set_load_store(attachment_info, load_stores[depth_attachment_index]);
716 stencil_attachment_format_ = vk_format;
717 begin_rendering.node_data.vk_rendering_info.pStencilAttachment =
718 &begin_rendering.node_data.stencil_attachment;
719 }
720
721 access_info.images.append({depth_texture.vk_image_handle(),
722 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
723 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
724 is_stencil_attachment ?
725 static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_DEPTH_BIT |
726 VK_IMAGE_ASPECT_STENCIL_BIT) :
727 static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_DEPTH_BIT),
728 {}});
729 break;
730 }
731
732 context.render_graph().add_node(begin_rendering);
733}
734
736{
737 if (!dirty_state_ && is_rendering_) {
738 return;
739 }
740
741 if (is_rendering_) {
742 rendering_end(context);
743 }
744
745 const VKExtensions &extensions = VKBackend::get().device.extensions_get();
746 is_rendering_ = true;
747 rendering_ensure_dynamic_rendering(context, extensions);
748 dirty_attachments_ = false;
749 dirty_state_ = false;
750}
751
753{
754 return depth_attachment_format_;
755}
757{
758 return stencil_attachment_format_;
759};
761{
762 return color_attachment_formats_;
763}
764
766{
767 if (!is_rendering_ && use_explicit_load_store_) {
768 rendering_ensure(context);
769 }
770
771 if (is_rendering_) {
773 context.render_graph().add_node(end_rendering);
774 is_rendering_ = false;
775 }
776}
777
778} // namespace blender::gpu
#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
MINLINE int max_ii(int a, int b)
MINLINE int clamp_i(int value, int min, int max)
MINLINE void copy_v4_v4(float r[4], const float a[4])
unsigned int uint
#define UNUSED_VARS_NDEBUG(...)
#define ELEM(...)
@ GPU_LOADACTION_LOAD
@ GPU_LOADACTION_DONT_CARE
@ GPU_LOADACTION_CLEAR
@ GPU_STOREACTION_STORE
@ GPU_STOREACTION_DONT_CARE
GPUAttachmentState
@ GPU_ATTACHMENT_WRITE
@ GPU_ATTACHMENT_READ
GPUFrameBufferBits
@ GPU_DEPTH_BIT
@ GPU_STENCIL_BIT
@ GPU_COLOR_BIT
static constexpr int GPU_MAX_VIEWPORTS
@ GPU_DEVICE_ATI
bool GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver)
@ GPU_DRIVER_OFFICIAL
@ GPU_OS_ANY
GPUWriteMask
Definition GPU_state.hh:16
@ GPU_WRITE_STENCIL
Definition GPU_state.hh:23
@ GPU_WRITE_NONE
Definition GPU_state.hh:17
@ GPU_WRITE_DEPTH
Definition GPU_state.hh:22
void GPU_texture_get_mipmap_size(blender::gpu::Texture *texture, int mip_level, int *r_size)
blender::gpu::TextureFormat GPU_texture_format(const blender::gpu::Texture *texture)
eGPUDataFormat
@ GPU_TEXTURE_USAGE_ATTACHMENT
long long int int64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
constexpr int64_t size() const
Definition BLI_span.hh:252
void append(const T &value)
bool is_empty() const
void append_n_times(const T &value, const int64_t n)
void size_set(int width, int height)
const GPUAttachment & depth_attachment() const
void scissor_get(int r_scissor[4]) const
blender::gpu::Texture * color_tex(int slot) const
FrameBuffer(const char *name)
GPUAttachment attachments_[GPU_FB_MAX_ATTACHMENT]
int viewport_[GPU_MAX_VIEWPORTS][4]
static void set_framebuffer_srgb_target(int use_srgb_to_linear)
eGPUTextureUsage usage_get() const
static VKBackend & get()
Definition vk_backend.hh:91
static VKContext * get()
const VKExtensions & extensions_get() const
Definition vk_device.hh:371
const VkPhysicalDeviceProperties & physical_device_properties_get() const
Definition vk_device.hh:269
void rendering_ensure_dynamic_rendering(VKContext &context, const VKExtensions &extensions)
void rendering_ensure(VKContext &context)
VKFrameBuffer(const char *name)
void clear(GPUFrameBufferBits buffers, const float clear_color[4], float clear_depth, uint clear_stencil) override
void clear_multi(const float(*clear_color)[4]) override
void vk_render_areas_append(Vector< VkRect2D > &r_render_areas) const
VkFormat stencil_attachment_format_get() const
void subpass_transition_impl(const GPUAttachmentState depth_attachment_state, Span< GPUAttachmentState > color_attachment_states) override
void read(GPUFrameBufferBits planes, eGPUDataFormat format, const int area[4], int channel_len, int slot, void *r_data) override
void render_area_update(VkRect2D &render_area) const
void bind(bool enabled_srgb) override
VkFormat depth_attachment_format_get() const
void blit_to(GPUFrameBufferBits planes, int src_slot, FrameBuffer *dst, int dst_slot, int dst_offset_x, int dst_offset_y) override
void rendering_end(VKContext &context)
bool check(char err_out[256]) override
void attachment_set_loadstore_op(GPUAttachmentType type, GPULoadStore) override
int color_attachments_resource_size() const
void clear_attachment(GPUAttachmentType type, eGPUDataFormat data_format, const void *clear_value) override
void vk_viewports_append(Vector< VkViewport > &r_viewports) const
Span< VkFormat > color_attachment_formats_get() const
VkFormat vk_format() const
VkImageView vk_handle() const
void clear_depth_stencil(const GPUFrameBufferBits buffer, float clear_depth, uint clear_stencil, std::optional< int > layer)
void copy_to(Texture *tex) override
TextureFormat device_format_get() const
VkImage vk_image_handle() const
const VKImageView & image_view_get(const VKImageViewInfo &info)
@ GPU_FB_DEPTH_STENCIL_ATTACHMENT
@ GPU_FB_MAX_ATTACHMENT
@ GPU_FB_COLOR_ATTACHMENT0
@ GPU_FB_DEPTH_ATTACHMENT
#define GPU_FB_MAX_COLOR_ATTACHMENT
TEX_TEMPLATE DataVec texture(T, FltCoord, float=0.0f) RET
format
int context(const bContext *C, const char *member, bContextDataResult *result)
constexpr GPULoadStore default_load_store()
static VkAttachmentLoadOp to_vk_attachment_load_op(GPULoadOp load_op)
static Context * unwrap(GPUContext *ctx)
VkFormat to_vk_format(const TextureFormat format)
Definition vk_common.cc:136
eGPUDataFormat to_texture_data_format(TextureFormat tex_format)
static void set_load_store(VkRenderingAttachmentInfo &r_rendering_attachment, const GPULoadStore &ls)
VkClearColorValue to_vk_clear_color_value(const eGPUDataFormat format, const void *data)
Definition vk_common.cc:598
VkImageAspectFlags to_vk_image_aspect_flag_bits(const TextureFormat format)
Definition vk_common.cc:14
static void blit_aspect(VKContext &context, VKTexture &dst_texture, VKTexture &src_texture, int dst_offset_x, int dst_offset_y, VkImageAspectFlags image_aspect)
static VkAttachmentStoreOp to_vk_attachment_store_op(GPUStoreOp store_op)
const char * name
blender::gpu::Texture * tex
GPUStoreOp store_action
GPULoadOp load_action
static constexpr GPUSamplerState default_sampler()
i
Definition text_draw.cc:230
char * buffers[2]