Blender V4.3
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
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> void set_node_data(Node &node, const CreateInfo &create_info)
45 {
46 node.update_mipmaps = create_info;
47 }
48
53 VKRenderGraphNodeLinks &node_links,
54 const CreateInfo &create_info) override
55 {
56 ResourceWithStamp resource = resources.get_image_and_increase_stamp(create_info.vk_image);
57 node_links.outputs.append({resource,
58 VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT,
59 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
60 create_info.vk_image_aspect});
61 }
62
67 Data &data,
68 VKBoundPipelines & /*r_bound_pipelines*/) override
69 {
70 VkImageMemoryBarrier image_memory_barrier = {};
71 image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
72 image_memory_barrier.pNext = nullptr;
73 image_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
74 image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
75 image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
76 image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
77 image_memory_barrier.image = data.vk_image;
78 image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
79 image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
80 image_memory_barrier.subresourceRange.aspectMask = data.vk_image_aspect;
81 image_memory_barrier.subresourceRange.baseArrayLayer = 0;
82 image_memory_barrier.subresourceRange.layerCount = data.layer_count;
83 image_memory_barrier.subresourceRange.baseMipLevel = 0;
84 image_memory_barrier.subresourceRange.levelCount = 1;
85
86 VkImageBlit image_blit = {};
87 image_blit.srcSubresource.aspectMask = data.vk_image_aspect;
88 image_blit.srcSubresource.layerCount = data.layer_count;
89 image_blit.srcSubresource.mipLevel = 1;
90 image_blit.dstSubresource.aspectMask = data.vk_image_aspect;
91 image_blit.dstSubresource.layerCount = data.layer_count;
92 image_blit.dstSubresource.mipLevel = 1;
93
94 int3 dst_size = data.l0_size;
95 for (int src_mipmap : IndexRange(data.mipmaps - 1)) {
96 int dst_mipmap = src_mipmap + 1;
97 int3 src_size = dst_size;
98 dst_size = math::max(src_size / 2, int3(1));
99
100 /* Update the source mipmap level to be in src optimal layout. */
101 image_memory_barrier.subresourceRange.baseMipLevel = src_mipmap;
102 command_buffer.pipeline_barrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
103 VK_PIPELINE_STAGE_TRANSFER_BIT,
104 VK_DEPENDENCY_BY_REGION_BIT,
105 0,
106 nullptr,
107 0,
108 nullptr,
109 1,
110 &image_memory_barrier);
111
112 /* Blit the source mipmap level into the destination mipmap level. */
113 image_blit.srcSubresource.mipLevel = src_mipmap;
114 image_blit.srcOffsets[1] = {src_size.x, src_size.y, src_size.z};
115 image_blit.dstSubresource.mipLevel = dst_mipmap;
116 image_blit.dstOffsets[1] = {dst_size.x, dst_size.y, dst_size.z};
117 command_buffer.blit_image(data.vk_image,
118 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
119 data.vk_image,
120 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
121 1,
122 &image_blit,
123 VK_FILTER_LINEAR);
124 }
125
126 /* Ensure that all mipmap levels are in the VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL layout.
127 * This is the last known layout that the render graph knows about. */
128 image_memory_barrier.subresourceRange.baseMipLevel = 0;
129 image_memory_barrier.subresourceRange.levelCount = data.mipmaps - 1;
130 image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
131 image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
132 command_buffer.pipeline_barrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
133 VK_PIPELINE_STAGE_TRANSFER_BIT,
134 VK_DEPENDENCY_BY_REGION_BIT,
135 0,
136 nullptr,
137 0,
138 nullptr,
139 1,
140 &image_memory_barrier);
141 }
142};
143
144} // namespace blender::gpu::render_graph
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, const CreateInfo &create_info)
void build_links(VKResourceStateTracker &resources, VKRenderGraphNodeLinks &node_links, const CreateInfo &create_info) override
T max(const T &a, const T &b)
VecBase< int32_t, 3 > int3