Blender V5.0
vk_update_mipmaps_node.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#pragma once
10
11#include "BLI_math_vector.hh"
12
13#include "vk_node_info.hh"
14
16
21 VkImage vk_image;
22 VkImageAspectFlags vk_image_aspect;
26};
27
31class VKUpdateMipmapsNode : public VKNodeInfo<VKNodeType::UPDATE_MIPMAPS,
32 VKUpdateMipmapsData,
33 VKUpdateMipmapsData,
34 VK_PIPELINE_STAGE_TRANSFER_BIT,
35 VKResourceType::IMAGE> {
36 public:
44 template<typename Node, typename Storage>
45 void set_node_data(Node &node, Storage & /*storage*/, const CreateInfo &create_info)
46 {
47 node.update_mipmaps = create_info;
48 }
49
54 VKRenderGraphNodeLinks &node_links,
55 const CreateInfo &create_info) override
56 {
58 node_links.outputs.append({resource,
59 VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT,
60 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
61 create_info.vk_image_aspect});
62 }
63
68 Data &data,
69 VKBoundPipelines & /*r_bound_pipelines*/) override
70 {
71 VkImageMemoryBarrier image_memory_barrier = {};
72 image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
73 image_memory_barrier.pNext = nullptr;
74 image_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
75 image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
76 image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
77 image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
78 image_memory_barrier.image = data.vk_image;
79 image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
80 image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
81 image_memory_barrier.subresourceRange.aspectMask = data.vk_image_aspect;
82 image_memory_barrier.subresourceRange.baseArrayLayer = 0;
83 image_memory_barrier.subresourceRange.layerCount = data.layer_count;
84 image_memory_barrier.subresourceRange.baseMipLevel = 0;
85 image_memory_barrier.subresourceRange.levelCount = 1;
86
87 VkImageBlit image_blit = {};
88 image_blit.srcSubresource.aspectMask = data.vk_image_aspect;
89 image_blit.srcSubresource.layerCount = data.layer_count;
90 image_blit.srcSubresource.mipLevel = 1;
91 image_blit.dstSubresource.aspectMask = data.vk_image_aspect;
92 image_blit.dstSubresource.layerCount = data.layer_count;
93 image_blit.dstSubresource.mipLevel = 1;
94
95 int3 dst_size = data.l0_size;
96 for (int src_mipmap : IndexRange(data.mipmaps - 1)) {
97 int dst_mipmap = src_mipmap + 1;
98 int3 src_size = dst_size;
99 dst_size = math::max(src_size / 2, int3(1));
100
101 /* Update the source mipmap level to be in src optimal layout. */
102 image_memory_barrier.subresourceRange.baseMipLevel = src_mipmap;
103 command_buffer.pipeline_barrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
104 VK_PIPELINE_STAGE_TRANSFER_BIT,
105 VK_DEPENDENCY_BY_REGION_BIT,
106 0,
107 nullptr,
108 0,
109 nullptr,
110 1,
111 &image_memory_barrier);
112
113 /* Blit the source mipmap level into the destination mipmap level. */
114 image_blit.srcSubresource.mipLevel = src_mipmap;
115 image_blit.srcOffsets[1] = {src_size.x, src_size.y, src_size.z};
116 image_blit.dstSubresource.mipLevel = dst_mipmap;
117 image_blit.dstOffsets[1] = {dst_size.x, dst_size.y, dst_size.z};
118 command_buffer.blit_image(data.vk_image,
119 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
120 data.vk_image,
121 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
122 1,
123 &image_blit,
124 VK_FILTER_LINEAR);
125 }
126
127 /* Ensure that all mipmap levels are in the VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL layout.
128 * This is the last known layout that the render graph knows about. */
129 image_memory_barrier.subresourceRange.baseMipLevel = 0;
130 image_memory_barrier.subresourceRange.levelCount = data.mipmaps - 1;
131 image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
132 image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
133 command_buffer.pipeline_barrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
134 VK_PIPELINE_STAGE_TRANSFER_BIT,
135 VK_DEPENDENCY_BY_REGION_BIT,
136 0,
137 nullptr,
138 0,
139 nullptr,
140 1,
141 &image_memory_barrier);
142 }
143};
144
145} // namespace blender::gpu::render_graph
BMesh const char void * data
virtual void blit_image(VkImage src_image, VkImageLayout src_image_layout, VkImage dst_image, VkImageLayout dst_image_layout, uint32_t region_count, const VkImageBlit *p_regions, VkFilter filter)=0
virtual void pipeline_barrier(VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask, VkDependencyFlags dependency_flags, uint32_t memory_barrier_count, const VkMemoryBarrier *p_memory_barriers, uint32_t buffer_memory_barrier_count, const VkBufferMemoryBarrier *p_buffer_memory_barriers, uint32_t image_memory_barrier_count, const VkImageMemoryBarrier *p_image_memory_barriers)=0
ResourceWithStamp get_image_and_increase_stamp(VkImage vk_image)
void build_commands(VKCommandBufferInterface &command_buffer, Data &data, VKBoundPipelines &) override
void set_node_data(Node &node, Storage &, const CreateInfo &create_info)
void build_links(VKResourceStateTracker &resources, VKRenderGraphNodeLinks &node_links, const CreateInfo &create_info) override
#define resource
T max(const T &a, const T &b)
VecBase< int32_t, 3 > int3