xref: /aosp_15_r20/external/mesa3d/src/vulkan/runtime/vk_meta.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2022 Collabora Ltd
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include "vk_meta_object_list.h"
25 #include "vk_meta_private.h"
26 
27 #include "vk_buffer.h"
28 #include "vk_command_buffer.h"
29 #include "vk_device.h"
30 #include "vk_pipeline.h"
31 #include "vk_util.h"
32 
33 #include "util/hash_table.h"
34 
35 #include <string.h>
36 
37 struct cache_key {
38    VkObjectType obj_type;
39    uint32_t key_size;
40    const void *key_data;
41 };
42 
43 static struct cache_key *
cache_key_create(VkObjectType obj_type,const void * key_data,size_t key_size)44 cache_key_create(VkObjectType obj_type, const void *key_data, size_t key_size)
45 {
46    assert(key_size <= UINT32_MAX);
47 
48    struct cache_key *key = malloc(sizeof(*key) + key_size);
49    *key = (struct cache_key) {
50       .obj_type = obj_type,
51       .key_size = key_size,
52       .key_data = key + 1,
53    };
54    memcpy(key + 1, key_data, key_size);
55 
56    return key;
57 }
58 
59 static uint32_t
cache_key_hash(const void * _key)60 cache_key_hash(const void *_key)
61 {
62    const struct cache_key *key = _key;
63 
64    assert(sizeof(key->obj_type) == 4);
65    uint32_t hash = _mesa_hash_u32(&key->obj_type);
66    return _mesa_hash_data_with_seed(key->key_data, key->key_size, hash);
67 }
68 
69 static bool
cache_key_equal(const void * _a,const void * _b)70 cache_key_equal(const void *_a, const void *_b)
71 {
72    const struct cache_key *a = _a, *b = _b;
73    if (a->obj_type != b->obj_type || a->key_size != b->key_size)
74       return false;
75 
76    return memcmp(a->key_data, b->key_data, a->key_size) == 0;
77 }
78 
79 VkResult
vk_meta_device_init(struct vk_device * device,struct vk_meta_device * meta)80 vk_meta_device_init(struct vk_device *device,
81                     struct vk_meta_device *meta)
82 {
83    memset(meta, 0, sizeof(*meta));
84 
85    meta->cache = _mesa_hash_table_create(NULL, cache_key_hash,
86                                                cache_key_equal);
87    simple_mtx_init(&meta->cache_mtx, mtx_plain);
88 
89    meta->cmd_draw_rects = vk_meta_draw_rects;
90    meta->cmd_draw_volume = vk_meta_draw_volume;
91 
92    return VK_SUCCESS;
93 }
94 
95 void
vk_meta_device_finish(struct vk_device * device,struct vk_meta_device * meta)96 vk_meta_device_finish(struct vk_device *device,
97                       struct vk_meta_device *meta)
98 {
99    hash_table_foreach(meta->cache, entry) {
100       free((void *)entry->key);
101       vk_meta_destroy_object(device, entry->data);
102    }
103    _mesa_hash_table_destroy(meta->cache, NULL);
104    simple_mtx_destroy(&meta->cache_mtx);
105 }
106 
107 uint64_t
vk_meta_lookup_object(struct vk_meta_device * meta,VkObjectType obj_type,const void * key_data,size_t key_size)108 vk_meta_lookup_object(struct vk_meta_device *meta,
109                       VkObjectType obj_type,
110                       const void *key_data, size_t key_size)
111 {
112    assert(key_size >= sizeof(enum vk_meta_object_key_type));
113    assert(*(enum vk_meta_object_key_type *)key_data !=
114           VK_META_OBJECT_KEY_TYPE_INVALID);
115 
116    struct cache_key key = {
117       .obj_type = obj_type,
118       .key_size = key_size,
119       .key_data = key_data,
120    };
121 
122    uint32_t hash = cache_key_hash(&key);
123 
124    simple_mtx_lock(&meta->cache_mtx);
125    struct hash_entry *entry =
126       _mesa_hash_table_search_pre_hashed(meta->cache, hash, &key);
127    simple_mtx_unlock(&meta->cache_mtx);
128 
129    if (entry == NULL)
130       return 0;
131 
132    struct vk_object_base *obj = entry->data;
133    assert(obj->type == obj_type);
134 
135    return (uint64_t)(uintptr_t)obj;
136 }
137 
138 uint64_t
vk_meta_cache_object(struct vk_device * device,struct vk_meta_device * meta,const void * key_data,size_t key_size,VkObjectType obj_type,uint64_t handle)139 vk_meta_cache_object(struct vk_device *device,
140                      struct vk_meta_device *meta,
141                      const void *key_data, size_t key_size,
142                      VkObjectType obj_type,
143                      uint64_t handle)
144 {
145    assert(key_size >= sizeof(enum vk_meta_object_key_type));
146    assert(*(enum vk_meta_object_key_type *)key_data !=
147           VK_META_OBJECT_KEY_TYPE_INVALID);
148 
149    struct cache_key *key = cache_key_create(obj_type, key_data, key_size);
150    struct vk_object_base *obj =
151       vk_object_base_from_u64_handle(handle, obj_type);
152 
153    uint32_t hash = cache_key_hash(key);
154 
155    simple_mtx_lock(&meta->cache_mtx);
156    struct hash_entry *entry =
157       _mesa_hash_table_search_pre_hashed(meta->cache, hash, key);
158    if (entry == NULL)
159       _mesa_hash_table_insert_pre_hashed(meta->cache, hash, key, obj);
160    simple_mtx_unlock(&meta->cache_mtx);
161 
162    if (entry != NULL) {
163       /* We raced and found that object already in the cache */
164       free(key);
165       vk_meta_destroy_object(device, obj);
166       return (uint64_t)(uintptr_t)entry->data;
167    } else {
168       /* Return the newly inserted object */
169       return (uint64_t)(uintptr_t)obj;
170    }
171 }
172 
173 VkResult
vk_meta_create_sampler(struct vk_device * device,struct vk_meta_device * meta,const VkSamplerCreateInfo * info,const void * key_data,size_t key_size,VkSampler * sampler_out)174 vk_meta_create_sampler(struct vk_device *device,
175                        struct vk_meta_device *meta,
176                        const VkSamplerCreateInfo *info,
177                        const void *key_data, size_t key_size,
178                        VkSampler *sampler_out)
179 {
180    const struct vk_device_dispatch_table *disp = &device->dispatch_table;
181    VkDevice _device = vk_device_to_handle(device);
182 
183    VkSampler sampler;
184    VkResult result = disp->CreateSampler(_device, info, NULL, &sampler);
185    if (result != VK_SUCCESS)
186       return result;
187 
188    *sampler_out = (VkSampler)
189       vk_meta_cache_object(device, meta, key_data, key_size,
190                            VK_OBJECT_TYPE_SAMPLER,
191                            (uint64_t)sampler);
192    return VK_SUCCESS;
193 }
194 
195 VkResult
vk_meta_create_descriptor_set_layout(struct vk_device * device,struct vk_meta_device * meta,const VkDescriptorSetLayoutCreateInfo * info,const void * key_data,size_t key_size,VkDescriptorSetLayout * layout_out)196 vk_meta_create_descriptor_set_layout(struct vk_device *device,
197                                      struct vk_meta_device *meta,
198                                      const VkDescriptorSetLayoutCreateInfo *info,
199                                      const void *key_data, size_t key_size,
200                                      VkDescriptorSetLayout *layout_out)
201 {
202    const struct vk_device_dispatch_table *disp = &device->dispatch_table;
203    VkDevice _device = vk_device_to_handle(device);
204 
205    VkDescriptorSetLayout layout;
206    VkResult result = disp->CreateDescriptorSetLayout(_device, info,
207                                                      NULL, &layout);
208    if (result != VK_SUCCESS)
209       return result;
210 
211    *layout_out = (VkDescriptorSetLayout)
212       vk_meta_cache_object(device, meta, key_data, key_size,
213                            VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT,
214                            (uint64_t)layout);
215    return VK_SUCCESS;
216 }
217 
218 static VkResult
vk_meta_get_descriptor_set_layout(struct vk_device * device,struct vk_meta_device * meta,const VkDescriptorSetLayoutCreateInfo * info,const void * key_data,size_t key_size,VkDescriptorSetLayout * layout_out)219 vk_meta_get_descriptor_set_layout(struct vk_device *device,
220                                   struct vk_meta_device *meta,
221                                   const VkDescriptorSetLayoutCreateInfo *info,
222                                   const void *key_data, size_t key_size,
223                                   VkDescriptorSetLayout *layout_out)
224 {
225    VkDescriptorSetLayout cached =
226       vk_meta_lookup_descriptor_set_layout(meta, key_data, key_size);
227    if (cached != VK_NULL_HANDLE) {
228       *layout_out = cached;
229       return VK_SUCCESS;
230    }
231 
232    return vk_meta_create_descriptor_set_layout(device, meta, info,
233                                                key_data, key_size,
234                                                layout_out);
235 }
236 
237 VkResult
vk_meta_create_pipeline_layout(struct vk_device * device,struct vk_meta_device * meta,const VkPipelineLayoutCreateInfo * info,const void * key_data,size_t key_size,VkPipelineLayout * layout_out)238 vk_meta_create_pipeline_layout(struct vk_device *device,
239                                struct vk_meta_device *meta,
240                                const VkPipelineLayoutCreateInfo *info,
241                                const void *key_data, size_t key_size,
242                                VkPipelineLayout *layout_out)
243 {
244    const struct vk_device_dispatch_table *disp = &device->dispatch_table;
245    VkDevice _device = vk_device_to_handle(device);
246 
247    VkPipelineLayout layout;
248    VkResult result = disp->CreatePipelineLayout(_device, info, NULL, &layout);
249    if (result != VK_SUCCESS)
250       return result;
251 
252    *layout_out = (VkPipelineLayout)
253       vk_meta_cache_object(device, meta, key_data, key_size,
254                            VK_OBJECT_TYPE_PIPELINE_LAYOUT,
255                            (uint64_t)layout);
256    return VK_SUCCESS;
257 }
258 
259 VkResult
vk_meta_get_pipeline_layout(struct vk_device * device,struct vk_meta_device * meta,const VkDescriptorSetLayoutCreateInfo * desc_info,const VkPushConstantRange * push_range,const void * key_data,size_t key_size,VkPipelineLayout * layout_out)260 vk_meta_get_pipeline_layout(struct vk_device *device,
261                             struct vk_meta_device *meta,
262                             const VkDescriptorSetLayoutCreateInfo *desc_info,
263                             const VkPushConstantRange *push_range,
264                             const void *key_data, size_t key_size,
265                             VkPipelineLayout *layout_out)
266 {
267    VkPipelineLayout cached =
268       vk_meta_lookup_pipeline_layout(meta, key_data, key_size);
269    if (cached != VK_NULL_HANDLE) {
270       *layout_out = cached;
271       return VK_SUCCESS;
272    }
273 
274    VkDescriptorSetLayout set_layout = VK_NULL_HANDLE;
275    if (desc_info != NULL) {
276       VkResult result =
277          vk_meta_get_descriptor_set_layout(device, meta, desc_info,
278                                            key_data, key_size, &set_layout);
279       if (result != VK_SUCCESS)
280          return result;
281    }
282 
283    const VkPipelineLayoutCreateInfo layout_info = {
284       .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
285       .setLayoutCount = set_layout != VK_NULL_HANDLE ? 1 : 0,
286       .pSetLayouts = &set_layout,
287       .pushConstantRangeCount = push_range != NULL ? 1 : 0,
288       .pPushConstantRanges = push_range,
289    };
290 
291    return vk_meta_create_pipeline_layout(device, meta, &layout_info,
292                                          key_data, key_size, layout_out);
293 }
294 
295 static VkResult
create_rect_list_pipeline(struct vk_device * device,struct vk_meta_device * meta,const VkGraphicsPipelineCreateInfo * info,VkPipeline * pipeline_out)296 create_rect_list_pipeline(struct vk_device *device,
297                           struct vk_meta_device *meta,
298                           const VkGraphicsPipelineCreateInfo *info,
299                           VkPipeline *pipeline_out)
300 {
301    const struct vk_device_dispatch_table *disp = &device->dispatch_table;
302    VkDevice _device = vk_device_to_handle(device);
303 
304    VkGraphicsPipelineCreateInfo info_local = *info;
305 
306    /* We always configure for layered rendering for now */
307    bool use_gs = meta->use_gs_for_layer;
308 
309    STACK_ARRAY(VkPipelineShaderStageCreateInfo, stages,
310                info->stageCount + 1 + use_gs);
311    uint32_t stage_count = 0;
312 
313    VkPipelineShaderStageNirCreateInfoMESA vs_nir_info = {
314       .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_NIR_CREATE_INFO_MESA,
315       .nir = vk_meta_draw_rects_vs_nir(meta, use_gs),
316    };
317    stages[stage_count++] = (VkPipelineShaderStageCreateInfo) {
318       .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
319       .pNext = &vs_nir_info,
320       .stage = VK_SHADER_STAGE_VERTEX_BIT,
321       .pName = "main",
322    };
323 
324    VkPipelineShaderStageNirCreateInfoMESA gs_nir_info;
325    if (use_gs) {
326       gs_nir_info = (VkPipelineShaderStageNirCreateInfoMESA) {
327          .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_NIR_CREATE_INFO_MESA,
328          .nir = vk_meta_draw_rects_gs_nir(meta),
329       };
330       stages[stage_count++] = (VkPipelineShaderStageCreateInfo) {
331          .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
332          .pNext = &gs_nir_info,
333          .stage = VK_SHADER_STAGE_GEOMETRY_BIT,
334          .pName = "main",
335       };
336    }
337 
338    for (uint32_t i = 0; i < info->stageCount; i++) {
339       assert(info->pStages[i].stage != VK_SHADER_STAGE_VERTEX_BIT);
340       if (use_gs)
341          assert(info->pStages[i].stage != VK_SHADER_STAGE_GEOMETRY_BIT);
342       stages[stage_count++] = info->pStages[i];
343    }
344 
345    info_local.stageCount = stage_count;
346    info_local.pStages = stages;
347    info_local.pVertexInputState = &vk_meta_draw_rects_vi_state;
348    info_local.pViewportState = &vk_meta_draw_rects_vs_state;
349 
350    uint32_t dyn_count = info->pDynamicState != NULL ?
351                         info->pDynamicState->dynamicStateCount : 0;
352 
353    STACK_ARRAY(VkDynamicState, dyn_state, dyn_count + 2);
354    for (uint32_t i = 0; i < dyn_count; i++)
355       dyn_state[i] = info->pDynamicState->pDynamicStates[i];
356 
357    dyn_state[dyn_count + 0] = VK_DYNAMIC_STATE_VIEWPORT;
358    dyn_state[dyn_count + 1] = VK_DYNAMIC_STATE_SCISSOR;
359 
360    const VkPipelineDynamicStateCreateInfo dyn_info = {
361       .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
362       .dynamicStateCount = dyn_count + 2,
363       .pDynamicStates = dyn_state,
364    };
365 
366    info_local.pDynamicState = &dyn_info;
367 
368    VkResult result = disp->CreateGraphicsPipelines(_device, VK_NULL_HANDLE,
369                                                    1, &info_local, NULL,
370                                                    pipeline_out);
371 
372    STACK_ARRAY_FINISH(dyn_state);
373    STACK_ARRAY_FINISH(stages);
374 
375    return result;
376 }
377 
378 static const VkPipelineRasterizationStateCreateInfo default_rs_info = {
379    .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
380    .depthClampEnable = false,
381    .depthBiasEnable = false,
382    .polygonMode = VK_POLYGON_MODE_FILL,
383    .cullMode = VK_CULL_MODE_NONE,
384    .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
385 };
386 
387 static const VkPipelineDepthStencilStateCreateInfo default_ds_info = {
388    .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
389    .depthTestEnable = false,
390    .depthBoundsTestEnable = false,
391    .stencilTestEnable = false,
392 };
393 
394 VkResult
vk_meta_create_graphics_pipeline(struct vk_device * device,struct vk_meta_device * meta,const VkGraphicsPipelineCreateInfo * info,const struct vk_meta_rendering_info * render,const void * key_data,size_t key_size,VkPipeline * pipeline_out)395 vk_meta_create_graphics_pipeline(struct vk_device *device,
396                                  struct vk_meta_device *meta,
397                                  const VkGraphicsPipelineCreateInfo *info,
398                                  const struct vk_meta_rendering_info *render,
399                                  const void *key_data, size_t key_size,
400                                  VkPipeline *pipeline_out)
401 {
402    const struct vk_device_dispatch_table *disp = &device->dispatch_table;
403    VkDevice _device = vk_device_to_handle(device);
404    VkResult result;
405 
406    VkGraphicsPipelineCreateInfo info_local = *info;
407 
408    /* Add in the rendering info */
409    VkPipelineRenderingCreateInfo r_info = {
410       .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
411       .viewMask = render->view_mask,
412       .colorAttachmentCount = render->color_attachment_count,
413       .pColorAttachmentFormats = render->color_attachment_formats,
414       .depthAttachmentFormat = render->depth_attachment_format,
415       .stencilAttachmentFormat = render->stencil_attachment_format,
416    };
417    __vk_append_struct(&info_local, &r_info);
418 
419    /* Assume rectangle pipelines */
420    if (info_local.pInputAssemblyState == NULL)
421    info_local.pInputAssemblyState = &vk_meta_draw_rects_ia_state;
422 
423    if (info_local.pRasterizationState == NULL)
424       info_local.pRasterizationState = &default_rs_info;
425 
426    VkPipelineMultisampleStateCreateInfo ms_info;
427    if (info_local.pMultisampleState == NULL) {
428       ms_info = (VkPipelineMultisampleStateCreateInfo) {
429          .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
430          .rasterizationSamples = render->samples,
431       };
432       info_local.pMultisampleState = &ms_info;
433    }
434 
435    if (info_local.pDepthStencilState == NULL)
436       info_local.pDepthStencilState = &default_ds_info;
437 
438    VkPipelineColorBlendStateCreateInfo cb_info;
439    VkPipelineColorBlendAttachmentState cb_att[MESA_VK_MAX_COLOR_ATTACHMENTS];
440    if (info_local.pColorBlendState == NULL) {
441       for (uint32_t i = 0; i < render->color_attachment_count; i++) {
442          cb_att[i] = (VkPipelineColorBlendAttachmentState) {
443             .blendEnable = false,
444             .colorWriteMask = render->color_attachment_write_masks[i],
445          };
446       }
447       cb_info = (VkPipelineColorBlendStateCreateInfo) {
448          .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
449          .attachmentCount = render->color_attachment_count,
450          .pAttachments = cb_att,
451       };
452       info_local.pColorBlendState = &cb_info;
453    }
454 
455    VkPipeline pipeline;
456    if (info_local.pInputAssemblyState->topology ==
457        VK_PRIMITIVE_TOPOLOGY_META_RECT_LIST_MESA) {
458       result = create_rect_list_pipeline(device, meta,
459                                          &info_local,
460                                          &pipeline);
461    } else {
462       result = disp->CreateGraphicsPipelines(_device, VK_NULL_HANDLE,
463                                              1, &info_local,
464                                              NULL, &pipeline);
465    }
466    if (unlikely(result != VK_SUCCESS))
467       return result;
468 
469    *pipeline_out = (VkPipeline)vk_meta_cache_object(device, meta,
470                                                     key_data, key_size,
471                                                     VK_OBJECT_TYPE_PIPELINE,
472                                                     (uint64_t)pipeline);
473    return VK_SUCCESS;
474 }
475 
476 VkResult
vk_meta_create_compute_pipeline(struct vk_device * device,struct vk_meta_device * meta,const VkComputePipelineCreateInfo * info,const void * key_data,size_t key_size,VkPipeline * pipeline_out)477 vk_meta_create_compute_pipeline(struct vk_device *device,
478                                 struct vk_meta_device *meta,
479                                 const VkComputePipelineCreateInfo *info,
480                                 const void *key_data, size_t key_size,
481                                 VkPipeline *pipeline_out)
482 {
483    const struct vk_device_dispatch_table *disp = &device->dispatch_table;
484    VkDevice _device = vk_device_to_handle(device);
485 
486    VkPipeline pipeline;
487    VkResult result = disp->CreateComputePipelines(_device, VK_NULL_HANDLE,
488                                                   1, info, NULL, &pipeline);
489    if (result != VK_SUCCESS)
490       return result;
491 
492    *pipeline_out = (VkPipeline)vk_meta_cache_object(device, meta,
493                                                     key_data, key_size,
494                                                     VK_OBJECT_TYPE_PIPELINE,
495                                                     (uint64_t)pipeline);
496    return VK_SUCCESS;
497 }
498 
499 VkResult
vk_meta_create_buffer(struct vk_command_buffer * cmd,struct vk_meta_device * meta,const VkBufferCreateInfo * info,VkBuffer * buffer_out)500 vk_meta_create_buffer(struct vk_command_buffer *cmd,
501                       struct vk_meta_device *meta,
502                       const VkBufferCreateInfo *info,
503                       VkBuffer *buffer_out)
504 {
505    struct vk_device *device = cmd->base.device;
506    const struct vk_device_dispatch_table *disp = &device->dispatch_table;
507    VkDevice _device = vk_device_to_handle(device);
508 
509    VkResult result = disp->CreateBuffer(_device, info, NULL, buffer_out);
510    if (unlikely(result != VK_SUCCESS))
511       return result;
512 
513    vk_meta_object_list_add_handle(&cmd->meta_objects,
514                                   VK_OBJECT_TYPE_BUFFER,
515                                   (uint64_t)*buffer_out);
516    return VK_SUCCESS;
517 }
518 
519 VkResult
vk_meta_create_image_view(struct vk_command_buffer * cmd,struct vk_meta_device * meta,const VkImageViewCreateInfo * info,VkImageView * image_view_out)520 vk_meta_create_image_view(struct vk_command_buffer *cmd,
521                           struct vk_meta_device *meta,
522                           const VkImageViewCreateInfo *info,
523                           VkImageView *image_view_out)
524 {
525    struct vk_device *device = cmd->base.device;
526    const struct vk_device_dispatch_table *disp = &device->dispatch_table;
527    VkDevice _device = vk_device_to_handle(device);
528 
529    VkResult result = disp->CreateImageView(_device, info, NULL, image_view_out);
530    if (unlikely(result != VK_SUCCESS))
531       return result;
532 
533    vk_meta_object_list_add_handle(&cmd->meta_objects,
534                                   VK_OBJECT_TYPE_IMAGE_VIEW,
535                                   (uint64_t)*image_view_out);
536    return VK_SUCCESS;
537 }
538 
539 VkResult
vk_meta_create_buffer_view(struct vk_command_buffer * cmd,struct vk_meta_device * meta,const VkBufferViewCreateInfo * info,VkBufferView * buffer_view_out)540 vk_meta_create_buffer_view(struct vk_command_buffer *cmd,
541                            struct vk_meta_device *meta,
542                            const VkBufferViewCreateInfo *info,
543                            VkBufferView *buffer_view_out)
544 {
545    struct vk_device *device = cmd->base.device;
546    const struct vk_device_dispatch_table *disp = &device->dispatch_table;
547    VkDevice _device = vk_device_to_handle(device);
548 
549    VkResult result = disp->CreateBufferView(_device, info, NULL, buffer_view_out);
550    if (unlikely(result != VK_SUCCESS))
551       return result;
552 
553    vk_meta_object_list_add_handle(&cmd->meta_objects,
554                                   VK_OBJECT_TYPE_BUFFER_VIEW,
555                                   (uint64_t)*buffer_view_out);
556    return VK_SUCCESS;
557 }
558 
559 VkDeviceAddress
vk_meta_buffer_address(struct vk_device * device,VkBuffer buffer,uint64_t offset,uint64_t range)560 vk_meta_buffer_address(struct vk_device *device, VkBuffer buffer,
561                        uint64_t offset, uint64_t range)
562 {
563    const VkBufferDeviceAddressInfo info = {
564       .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
565       .buffer = buffer,
566    };
567    VkDeviceAddress base = device->dispatch_table.GetBufferDeviceAddress(
568       vk_device_to_handle(device), &info);
569 
570    /* Only called for the assert()s in vk_buffer_range(), we don't care about
571     * the result.
572     */
573    vk_buffer_range(vk_buffer_from_handle(buffer), offset, range);
574 
575    return base + offset;
576 }
577