Blender V4.3
vk_descriptor_set.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10#include "vk_index_buffer.hh"
11#include "vk_shader.hh"
13#include "vk_state_manager.hh"
14#include "vk_storage_buffer.hh"
15#include "vk_texture.hh"
16#include "vk_vertex_buffer.hh"
17
18namespace blender::gpu {
19
20void VKDescriptorSetTracker::bind_buffer(VkDescriptorType vk_descriptor_type,
21 VkBuffer vk_buffer,
22 VkDeviceSize size_in_bytes,
23 VKDescriptorSet::Location location)
24{
25 vk_descriptor_buffer_infos_.append({vk_buffer, 0, size_in_bytes});
26 vk_write_descriptor_sets_.append({VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
27 nullptr,
29 location,
30 0,
31 1,
32 vk_descriptor_type,
33 nullptr,
34 nullptr,
35 nullptr});
36}
37
38void VKDescriptorSetTracker::bind_texel_buffer(VkBufferView vk_buffer_view,
39 const VKDescriptorSet::Location location)
40{
41 vk_buffer_views_.append(vk_buffer_view);
42 vk_write_descriptor_sets_.append({VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
43 nullptr,
45 location,
46 0,
47 1,
48 VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
49 nullptr,
50 nullptr,
51 nullptr});
52}
53
54void VKDescriptorSetTracker::bind_image(VkDescriptorType vk_descriptor_type,
55 VkSampler vk_sampler,
56 VkImageView vk_image_view,
57 VkImageLayout vk_image_layout,
58 VKDescriptorSet::Location location)
59{
60 vk_descriptor_image_infos_.append({vk_sampler, vk_image_view, vk_image_layout});
61 vk_write_descriptor_sets_.append({VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
62 nullptr,
64 location,
65 0,
66 1,
67 vk_descriptor_type,
68 nullptr,
69 nullptr,
70 nullptr});
71}
72
73void VKDescriptorSetTracker::bind_image_resource(const VKStateManager &state_manager,
74 const VKResourceBinding &resource_binding,
75 render_graph::VKResourceAccessInfo &access_info)
76{
77 VKTexture &texture = *state_manager.images_.get(resource_binding.binding);
78 bind_image(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
79 VK_NULL_HANDLE,
80 texture.image_view_get(resource_binding.arrayed).vk_handle(),
81 VK_IMAGE_LAYOUT_GENERAL,
82 resource_binding.location);
83 /* Update access info. */
84 uint32_t layer_base = 0;
85 uint32_t layer_count = VK_REMAINING_ARRAY_LAYERS;
86 if (resource_binding.arrayed == VKImageViewArrayed::ARRAYED && texture.is_texture_view()) {
87 IndexRange layer_range = texture.layer_range();
88 layer_base = layer_range.start();
89 layer_count = layer_range.size();
90 }
91 access_info.images.append({texture.vk_image_handle(),
92 resource_binding.access_mask,
93 to_vk_image_aspect_flag_bits(texture.device_format_get()),
94 layer_base,
95 layer_count});
96}
97
98void VKDescriptorSetTracker::bind_texture_resource(const VKDevice &device,
99 const VKStateManager &state_manager,
100 const VKResourceBinding &resource_binding,
101 render_graph::VKResourceAccessInfo &access_info)
102{
103 const BindSpaceTextures::Elem &elem = state_manager.textures_.get(resource_binding.binding);
104 switch (elem.resource_type) {
106 VKVertexBuffer *vertex_buffer = static_cast<VKVertexBuffer *>(elem.resource);
107 vertex_buffer->ensure_updated();
108 vertex_buffer->ensure_buffer_view();
109 bind_texel_buffer(vertex_buffer->vk_buffer_view_get(), resource_binding.location);
110 access_info.buffers.append({vertex_buffer->vk_handle(), resource_binding.access_mask});
111 break;
112 }
114 VKTexture *texture = static_cast<VKTexture *>(elem.resource);
115 if (texture->type_ != GPU_TEXTURE_BUFFER) {
116 const VKSampler &sampler = device.samplers().get(elem.sampler);
117 bind_image(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
118 sampler.vk_handle(),
119 texture->image_view_get(resource_binding.arrayed).vk_handle(),
120 VK_IMAGE_LAYOUT_GENERAL,
121 resource_binding.location);
122 access_info.images.append({texture->vk_image_handle(),
123 resource_binding.access_mask,
124 to_vk_image_aspect_flag_bits(texture->device_format_get()),
125 0,
126 VK_REMAINING_ARRAY_LAYERS});
127 }
128 else {
129 /* Texture buffers are no textures, but wrap around vertex buffers and need to be
130 * bound as texel buffers. */
131 /* TODO: Investigate if this can be improved in the API. */
132 VKVertexBuffer *vertex_buffer = texture->source_buffer_;
133 vertex_buffer->ensure_updated();
134 vertex_buffer->ensure_buffer_view();
135 bind_texel_buffer(vertex_buffer->vk_buffer_view_get(), resource_binding.location);
136 access_info.buffers.append({vertex_buffer->vk_handle(), resource_binding.access_mask});
137 }
138 break;
139 }
142 }
143 }
144}
145
146void VKDescriptorSetTracker::bind_storage_buffer_resource(
147 const VKStateManager &state_manager,
148 const VKResourceBinding &resource_binding,
149 render_graph::VKResourceAccessInfo &access_info)
150{
151 const BindSpaceStorageBuffers::Elem &elem = state_manager.storage_buffers_.get(
152 resource_binding.binding);
153 VkBuffer vk_buffer = VK_NULL_HANDLE;
154 VkDeviceSize vk_device_size = 0;
155 switch (elem.resource_type) {
157 VKIndexBuffer *index_buffer = static_cast<VKIndexBuffer *>(elem.resource);
158 index_buffer->ensure_updated();
159 vk_buffer = index_buffer->vk_handle();
160 vk_device_size = index_buffer->size_get();
161 break;
162 }
164 VKVertexBuffer *vertex_buffer = static_cast<VKVertexBuffer *>(elem.resource);
165 vertex_buffer->ensure_updated();
166 vk_buffer = vertex_buffer->vk_handle();
167 vk_device_size = vertex_buffer->size_used_get();
168 break;
169 }
171 VKUniformBuffer *uniform_buffer = static_cast<VKUniformBuffer *>(elem.resource);
172 uniform_buffer->ensure_updated();
173 vk_buffer = uniform_buffer->vk_handle();
174 vk_device_size = uniform_buffer->size_in_bytes();
175 break;
176 }
178 VKStorageBuffer *storage_buffer = static_cast<VKStorageBuffer *>(elem.resource);
179 storage_buffer->ensure_allocated();
180 vk_buffer = storage_buffer->vk_handle();
181 vk_device_size = storage_buffer->size_in_bytes();
182 break;
183 }
186 }
187 }
188
189 bind_buffer(
190 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk_buffer, vk_device_size, resource_binding.location);
191 access_info.buffers.append({vk_buffer, resource_binding.access_mask});
192}
193
194void VKDescriptorSetTracker::bind_uniform_buffer_resource(
195 const VKStateManager &state_manager,
196 const VKResourceBinding &resource_binding,
197 render_graph::VKResourceAccessInfo &access_info)
198{
199 VKUniformBuffer &uniform_buffer = *state_manager.uniform_buffers_.get(resource_binding.binding);
200 uniform_buffer.ensure_updated();
201 bind_buffer(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
202 uniform_buffer.vk_handle(),
203 uniform_buffer.size_in_bytes(),
204 resource_binding.location);
205 access_info.buffers.append({uniform_buffer.vk_handle(), resource_binding.access_mask});
206}
207
208void VKDescriptorSetTracker::bind_push_constants(VKPushConstants &push_constants,
209 render_graph::VKResourceAccessInfo &access_info)
210{
211 if (push_constants.layout_get().storage_type_get() !=
213 {
214 return;
215 }
216 push_constants.update_uniform_buffer();
217 const VKUniformBuffer &uniform_buffer = *push_constants.uniform_buffer_get().get();
218 bind_buffer(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
219 uniform_buffer.vk_handle(),
220 uniform_buffer.size_in_bytes(),
221 push_constants.layout_get().descriptor_set_location_get());
222 access_info.buffers.append({uniform_buffer.vk_handle(), VK_ACCESS_UNIFORM_READ_BIT});
223}
224
225void VKDescriptorSetTracker::bind_shader_resources(const VKDevice &device,
226 const VKStateManager &state_manager,
227 VKShader &shader,
228 render_graph::VKResourceAccessInfo &access_info)
229{
230 const VKShaderInterface &shader_interface = shader.interface_get();
231 for (const VKResourceBinding &resource_binding : shader_interface.resource_bindings_get()) {
232 if (resource_binding.binding == -1) {
233 continue;
234 }
235
236 switch (resource_binding.bind_type) {
238 bind_image_resource(state_manager, resource_binding, access_info);
239 break;
240
242 bind_texture_resource(device, state_manager, resource_binding, access_info);
243 break;
244
246 bind_storage_buffer_resource(state_manager, resource_binding, access_info);
247 break;
248
250 bind_uniform_buffer_resource(state_manager, resource_binding, access_info);
251 break;
252 }
253 }
254
255 /* Bind uniform push constants to descriptor set. */
256 bind_push_constants(shader.push_constants, access_info);
257}
258
261{
262 VKShader &shader = *unwrap(context.shader);
263 VKStateManager &state_manager = context.state_manager_get();
264
265 /* Can we reuse previous descriptor set. */
266 if (!state_manager.is_dirty &&
267 !assign_if_different(vk_descriptor_set_layout_, shader.vk_descriptor_set_layout_get()) &&
268 shader.push_constants.layout_get().storage_type_get() !=
270 {
271 return;
272 }
273 state_manager.is_dirty = false;
274
275 /* Allocate a new descriptor set. */
276 VkDescriptorSetLayout vk_descriptor_set_layout = shader.vk_descriptor_set_layout_get();
277 vk_descriptor_set = context.descriptor_pools_get().allocate(vk_descriptor_set_layout);
278 BLI_assert(vk_descriptor_set != VK_NULL_HANDLE);
279 debug::object_label(vk_descriptor_set, shader.name_get());
280 const VKDevice &device = VKBackend::get().device;
281 bind_shader_resources(device, state_manager, shader, access_info);
282}
283
285{
286 if (vk_write_descriptor_sets_.is_empty()) {
287 return;
288 }
289
290 /* Finalize pointers that could have changed due to reallocations. */
291 int buffer_index = 0;
292 int buffer_view_index = 0;
293 int image_index = 0;
294 for (int write_index : vk_write_descriptor_sets_.index_range()) {
295 VkWriteDescriptorSet &vk_write_descriptor_set = vk_write_descriptor_sets_[write_index++];
296 switch (vk_write_descriptor_set.descriptorType) {
297 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
298 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
299 vk_write_descriptor_set.pImageInfo = &vk_descriptor_image_infos_[image_index++];
300 break;
301
302 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
303 vk_write_descriptor_set.pTexelBufferView = &vk_buffer_views_[buffer_view_index++];
304 break;
305
306 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
307 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
308 vk_write_descriptor_set.pBufferInfo = &vk_descriptor_buffer_infos_[buffer_index++];
309 break;
310
311 default:
313 break;
314 }
315 }
316
317 /* Update the descriptor set on the device. */
318 const VKDevice &device = VKBackend::get().device;
319 vkUpdateDescriptorSets(device.vk_handle(),
320 vk_write_descriptor_sets_.size(),
321 vk_write_descriptor_sets_.data(),
322 0,
323 nullptr);
324
325 vk_descriptor_image_infos_.clear();
326 vk_descriptor_buffer_infos_.clear();
327 vk_buffer_views_.clear();
328 vk_write_descriptor_sets_.clear();
329}
330
331} // namespace blender::gpu
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
int64_t size() const
void append(const T &value)
bool is_empty() const
IndexRange index_range() const
static VKBackend & get()
Definition vk_backend.hh:92
void update_descriptor_set(VKContext &context, render_graph::VKResourceAccessInfo &resource_access_info)
VkDevice vk_handle() const
Definition vk_device.hh:224
local_group_size(16, 16) .push_constant(Type local_group_size(16, 16) .push_constant(Type input_tx sampler(1, ImageType::FLOAT_2D, "matte_tx") .image(0
void object_label(GLenum type, GLuint object, const char *name)
Definition gl_debug.cc:344
static Context * unwrap(GPUContext *ctx)
VkImageAspectFlags to_vk_image_aspect_flag_bits(const eGPUTextureFormat format)
Definition vk_common.cc:14
bool assign_if_different(T &old_value, T new_value)
unsigned int uint32_t
Definition stdint.h:80