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