1 | #define VOLK_IMPLEMENTATION |
2 | |
3 | #include "taichi/rhi/impl_support.h" |
4 | |
5 | #include "taichi/rhi/vulkan/vulkan_api.h" |
6 | #include "taichi/rhi/vulkan/vulkan_loader.h" |
7 | |
8 | namespace vkapi { |
9 | |
10 | DeviceObjVkDescriptorSetLayout::~DeviceObjVkDescriptorSetLayout() { |
11 | vkDestroyDescriptorSetLayout(device, layout, nullptr); |
12 | } |
13 | |
14 | DeviceObjVkDescriptorPool::~DeviceObjVkDescriptorPool() { |
15 | vkDestroyDescriptorPool(device, pool, nullptr); |
16 | } |
17 | |
18 | DeviceObjVkDescriptorSet::~DeviceObjVkDescriptorSet() { |
19 | } |
20 | |
21 | DeviceObjVkCommandPool::~DeviceObjVkCommandPool() { |
22 | vkDestroyCommandPool(device, pool, nullptr); |
23 | } |
24 | |
25 | DeviceObjVkCommandBuffer::~DeviceObjVkCommandBuffer() { |
26 | if (this->level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) { |
27 | ref_pool->free_primary.push(buffer); |
28 | } else { |
29 | ref_pool->free_secondary.push(buffer); |
30 | } |
31 | } |
32 | |
33 | DeviceObjVkRenderPass::~DeviceObjVkRenderPass() { |
34 | vkDestroyRenderPass(device, renderpass, nullptr); |
35 | } |
36 | |
37 | DeviceObjVkPipelineLayout::~DeviceObjVkPipelineLayout() { |
38 | vkDestroyPipelineLayout(device, layout, nullptr); |
39 | } |
40 | |
41 | DeviceObjVkPipeline::~DeviceObjVkPipeline() { |
42 | vkDestroyPipeline(device, pipeline, nullptr); |
43 | } |
44 | |
45 | DeviceObjVkSampler::~DeviceObjVkSampler() { |
46 | vkDestroySampler(device, sampler, nullptr); |
47 | } |
48 | |
49 | DeviceObjVkImage::~DeviceObjVkImage() { |
50 | if (allocation) { |
51 | vmaDestroyImage(allocator, image, allocation); |
52 | } |
53 | } |
54 | |
55 | DeviceObjVkImageView::~DeviceObjVkImageView() { |
56 | vkDestroyImageView(device, view, nullptr); |
57 | } |
58 | |
59 | DeviceObjVkFramebuffer::~DeviceObjVkFramebuffer() { |
60 | vkDestroyFramebuffer(device, framebuffer, nullptr); |
61 | } |
62 | |
63 | DeviceObjVkSemaphore::~DeviceObjVkSemaphore() { |
64 | vkDestroySemaphore(device, semaphore, nullptr); |
65 | } |
66 | |
67 | DeviceObjVkFence::~DeviceObjVkFence() { |
68 | vkDestroyFence(device, fence, nullptr); |
69 | } |
70 | |
71 | DeviceObjVkPipelineCache::~DeviceObjVkPipelineCache() { |
72 | vkDestroyPipelineCache(device, cache, nullptr); |
73 | } |
74 | |
75 | DeviceObjVkBuffer::~DeviceObjVkBuffer() { |
76 | if (allocation) { |
77 | vmaDestroyBuffer(allocator, buffer, allocation); |
78 | } |
79 | } |
80 | |
81 | DeviceObjVkBufferView::~DeviceObjVkBufferView() { |
82 | vkDestroyBufferView(device, view, nullptr); |
83 | } |
84 | |
85 | DeviceObjVkAccelerationStructureKHR::~DeviceObjVkAccelerationStructureKHR() { |
86 | PFN_vkDestroyAccelerationStructureKHR destroy_raytracing_pipeline_khr = |
87 | PFN_vkDestroyAccelerationStructureKHR(vkGetInstanceProcAddr( |
88 | taichi::lang::vulkan::VulkanLoader::instance().get_instance(), |
89 | "vkDestroyAccelerationStructureKHR" )); |
90 | |
91 | destroy_raytracing_pipeline_khr(device, accel, nullptr); |
92 | } |
93 | DeviceObjVkQueryPool::~DeviceObjVkQueryPool() { |
94 | vkDestroyQueryPool(device, query_pool, nullptr); |
95 | } |
96 | |
97 | IDeviceObj create_device_obj(VkDevice device) { |
98 | IDeviceObj obj = std::make_shared<DeviceObj>(); |
99 | obj->device = device; |
100 | return obj; |
101 | } |
102 | |
103 | IVkSemaphore create_semaphore(VkDevice device, |
104 | VkSemaphoreCreateFlags flags, |
105 | void *pnext) { |
106 | IVkSemaphore obj = std::make_shared<DeviceObjVkSemaphore>(); |
107 | obj->device = device; |
108 | |
109 | VkSemaphoreCreateInfo info{}; |
110 | info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; |
111 | info.pNext = pnext; |
112 | info.flags = flags; |
113 | |
114 | VkResult res = vkCreateSemaphore(device, &info, nullptr, &obj->semaphore); |
115 | BAIL_ON_VK_BAD_RESULT_NO_RETURN(res, "failed to create semaphore" ); |
116 | return obj; |
117 | } |
118 | |
119 | IVkFence create_fence(VkDevice device, VkFenceCreateFlags flags, void *pnext) { |
120 | IVkFence obj = std::make_shared<DeviceObjVkFence>(); |
121 | obj->device = device; |
122 | |
123 | VkFenceCreateInfo info{}; |
124 | info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; |
125 | info.pNext = pnext; |
126 | info.flags = flags; |
127 | |
128 | VkResult res = vkCreateFence(device, &info, nullptr, &obj->fence); |
129 | BAIL_ON_VK_BAD_RESULT_NO_RETURN(res, "failed to create fence" ); |
130 | return obj; |
131 | } |
132 | |
133 | IVkDescriptorSetLayout create_descriptor_set_layout( |
134 | VkDevice device, |
135 | VkDescriptorSetLayoutCreateInfo *create_info) { |
136 | IVkDescriptorSetLayout obj = |
137 | std::make_shared<DeviceObjVkDescriptorSetLayout>(); |
138 | obj->device = device; |
139 | VkResult res = |
140 | vkCreateDescriptorSetLayout(device, create_info, nullptr, &obj->layout); |
141 | BAIL_ON_VK_BAD_RESULT_NO_RETURN(res, |
142 | "failed to create descriptor set layout" ); |
143 | return obj; |
144 | } |
145 | |
146 | IVkDescriptorPool create_descriptor_pool( |
147 | VkDevice device, |
148 | VkDescriptorPoolCreateInfo *create_info) { |
149 | IVkDescriptorPool obj = std::make_shared<DeviceObjVkDescriptorPool>(); |
150 | obj->device = device; |
151 | VkResult res = |
152 | vkCreateDescriptorPool(device, create_info, nullptr, &obj->pool); |
153 | if (res != VK_SUCCESS) { |
154 | // All failure condition listed in spec are OOM |
155 | return nullptr; |
156 | } |
157 | return obj; |
158 | } |
159 | |
160 | IVkDescriptorSet allocate_descriptor_sets(IVkDescriptorPool pool, |
161 | IVkDescriptorSetLayout layout, |
162 | void *pnext) { |
163 | IVkDescriptorSet obj = std::make_shared<DeviceObjVkDescriptorSet>(); |
164 | obj->device = pool->device; |
165 | obj->ref_layout = layout; |
166 | obj->ref_pool = pool; |
167 | |
168 | VkDescriptorSetAllocateInfo info{}; |
169 | info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; |
170 | info.pNext = pnext; |
171 | info.descriptorPool = pool->pool; |
172 | info.descriptorSetCount = 1; |
173 | info.pSetLayouts = &layout->layout; |
174 | |
175 | if (vkAllocateDescriptorSets(pool->device, &info, &obj->set) == |
176 | VK_ERROR_OUT_OF_POOL_MEMORY) { |
177 | return nullptr; |
178 | } |
179 | |
180 | return obj; |
181 | } |
182 | |
183 | IVkCommandPool create_command_pool(VkDevice device, |
184 | VkCommandPoolCreateFlags flags, |
185 | uint32_t queue_family_index) { |
186 | IVkCommandPool obj = std::make_shared<DeviceObjVkCommandPool>(); |
187 | obj->device = device; |
188 | obj->queue_family_index = queue_family_index; |
189 | |
190 | VkCommandPoolCreateInfo info{}; |
191 | info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; |
192 | info.pNext = nullptr; |
193 | info.flags = flags; |
194 | info.queueFamilyIndex = queue_family_index; |
195 | |
196 | VkResult res = vkCreateCommandPool(device, &info, nullptr, &obj->pool); |
197 | BAIL_ON_VK_BAD_RESULT_NO_RETURN(res, "failed to create command pool" ); |
198 | |
199 | return obj; |
200 | } |
201 | |
202 | IVkCommandBuffer allocate_command_buffer(IVkCommandPool pool, |
203 | VkCommandBufferLevel level) { |
204 | VkCommandBuffer cmdbuf{VK_NULL_HANDLE}; |
205 | |
206 | if (level == VK_COMMAND_BUFFER_LEVEL_PRIMARY && pool->free_primary.size()) { |
207 | cmdbuf = pool->free_primary.top(); |
208 | pool->free_primary.pop(); |
209 | } else if (level == VK_COMMAND_BUFFER_LEVEL_SECONDARY && |
210 | pool->free_secondary.size()) { |
211 | cmdbuf = pool->free_secondary.top(); |
212 | pool->free_secondary.pop(); |
213 | } else { |
214 | VkCommandBufferAllocateInfo info{}; |
215 | info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; |
216 | info.pNext = nullptr; |
217 | info.commandPool = pool->pool; |
218 | info.level = level; |
219 | info.commandBufferCount = 1; |
220 | |
221 | VkResult res = vkAllocateCommandBuffers(pool->device, &info, &cmdbuf); |
222 | if (res != VK_SUCCESS) { |
223 | return nullptr; |
224 | } |
225 | } |
226 | |
227 | IVkCommandBuffer obj = std::make_shared<DeviceObjVkCommandBuffer>(); |
228 | obj->device = pool->device; |
229 | obj->level = level; |
230 | obj->ref_pool = pool; |
231 | obj->buffer = cmdbuf; |
232 | |
233 | return obj; |
234 | } |
235 | |
236 | IVkRenderPass create_render_pass(VkDevice device, |
237 | VkRenderPassCreateInfo *create_info) { |
238 | IVkRenderPass obj = std::make_shared<DeviceObjVkRenderPass>(); |
239 | obj->device = device; |
240 | VkResult res = |
241 | vkCreateRenderPass(device, create_info, nullptr, &obj->renderpass); |
242 | BAIL_ON_VK_BAD_RESULT_NO_RETURN(res, "failed to create render pass" ); |
243 | return obj; |
244 | } |
245 | |
246 | IVkPipelineLayout create_pipeline_layout( |
247 | VkDevice device, |
248 | std::vector<IVkDescriptorSetLayout> &set_layouts, |
249 | uint32_t push_constant_range_count, |
250 | VkPushConstantRange *push_constant_ranges) { |
251 | IVkPipelineLayout obj = std::make_shared<DeviceObjVkPipelineLayout>(); |
252 | obj->device = device; |
253 | obj->ref_desc_layouts = set_layouts; |
254 | |
255 | std::vector<VkDescriptorSetLayout> layouts; |
256 | layouts.reserve(set_layouts.size()); |
257 | for (auto &l : set_layouts) { |
258 | layouts.push_back(l->layout); |
259 | } |
260 | |
261 | VkPipelineLayoutCreateInfo info{}; |
262 | info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; |
263 | info.pNext = nullptr; |
264 | info.setLayoutCount = uint32_t(layouts.size()); |
265 | info.pSetLayouts = layouts.data(); |
266 | info.pushConstantRangeCount = push_constant_range_count; |
267 | info.pPushConstantRanges = push_constant_ranges; |
268 | |
269 | VkResult res = vkCreatePipelineLayout(device, &info, nullptr, &obj->layout); |
270 | BAIL_ON_VK_BAD_RESULT_NO_RETURN(res, "failed to create pipeline layout" ); |
271 | |
272 | return obj; |
273 | } |
274 | |
275 | IVkPipelineCache create_pipeline_cache(VkDevice device, |
276 | VkPipelineCacheCreateFlags flags, |
277 | size_t initial_size, |
278 | const void *initial_data) { |
279 | IVkPipelineCache obj = std::make_shared<DeviceObjVkPipelineCache>(); |
280 | obj->device = device; |
281 | |
282 | VkPipelineCacheCreateInfo info{}; |
283 | info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; |
284 | info.pNext = nullptr; |
285 | info.flags = flags; |
286 | info.initialDataSize = initial_size; |
287 | info.pInitialData = initial_data; |
288 | |
289 | VkResult res = vkCreatePipelineCache(device, &info, nullptr, &obj->cache); |
290 | BAIL_ON_VK_BAD_RESULT_NO_RETURN(res, "failed to create pipeline cache" ); |
291 | |
292 | return obj; |
293 | } |
294 | |
295 | IVkPipeline create_compute_pipeline(VkDevice device, |
296 | VkPipelineCreateFlags flags, |
297 | VkPipelineShaderStageCreateInfo &stage, |
298 | IVkPipelineLayout layout, |
299 | IVkPipelineCache cache, |
300 | IVkPipeline base_pipeline) { |
301 | IVkPipeline obj = std::make_shared<DeviceObjVkPipeline>(); |
302 | obj->device = device; |
303 | obj->ref_layout = layout; |
304 | obj->ref_cache = cache; |
305 | |
306 | VkComputePipelineCreateInfo info{}; |
307 | info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; |
308 | info.pNext = nullptr; |
309 | info.flags = flags; |
310 | info.stage = stage; |
311 | info.layout = layout->layout; |
312 | if (base_pipeline) { |
313 | info.basePipelineHandle = base_pipeline->pipeline; |
314 | info.basePipelineIndex = -1; |
315 | } else { |
316 | info.basePipelineHandle = VK_NULL_HANDLE; |
317 | info.basePipelineIndex = 0; |
318 | } |
319 | |
320 | VkResult res = |
321 | vkCreateComputePipelines(device, cache ? cache->cache : VK_NULL_HANDLE, 1, |
322 | &info, nullptr, &obj->pipeline); |
323 | RHI_THROW_UNLESS(res == VK_SUCCESS, |
324 | std::runtime_error("vkCreateComputePipelines failed" )); |
325 | |
326 | return obj; |
327 | } |
328 | |
329 | IVkPipeline create_graphics_pipeline(VkDevice device, |
330 | VkGraphicsPipelineCreateInfo *create_info, |
331 | IVkRenderPass renderpass, |
332 | IVkPipelineLayout layout, |
333 | IVkPipelineCache cache, |
334 | IVkPipeline base_pipeline) { |
335 | IVkPipeline obj = std::make_shared<DeviceObjVkPipeline>(); |
336 | obj->device = device; |
337 | obj->ref_layout = layout; |
338 | obj->ref_cache = cache; |
339 | obj->ref_renderpass = renderpass; |
340 | |
341 | create_info->renderPass = renderpass->renderpass; |
342 | create_info->layout = layout->layout; |
343 | |
344 | if (base_pipeline) { |
345 | create_info->basePipelineHandle = base_pipeline->pipeline; |
346 | create_info->basePipelineIndex = -1; |
347 | } else { |
348 | create_info->basePipelineHandle = VK_NULL_HANDLE; |
349 | create_info->basePipelineIndex = 0; |
350 | } |
351 | |
352 | VkResult res = |
353 | vkCreateGraphicsPipelines(device, cache ? cache->cache : VK_NULL_HANDLE, |
354 | 1, create_info, nullptr, &obj->pipeline); |
355 | BAIL_ON_VK_BAD_RESULT_NO_RETURN(res, "failed to create graphics pipeline" ); |
356 | |
357 | return obj; |
358 | } |
359 | |
360 | IVkPipeline create_graphics_pipeline_dynamic( |
361 | VkDevice device, |
362 | VkGraphicsPipelineCreateInfo *create_info, |
363 | VkPipelineRenderingCreateInfoKHR *rendering_info, |
364 | IVkPipelineLayout layout, |
365 | IVkPipelineCache cache, |
366 | IVkPipeline base_pipeline) { |
367 | IVkPipeline obj = std::make_shared<DeviceObjVkPipeline>(); |
368 | obj->device = device; |
369 | obj->ref_layout = layout; |
370 | obj->ref_cache = cache; |
371 | obj->ref_renderpass = nullptr; |
372 | |
373 | create_info->pNext = rendering_info; |
374 | create_info->layout = layout->layout; |
375 | |
376 | if (base_pipeline) { |
377 | create_info->basePipelineHandle = base_pipeline->pipeline; |
378 | create_info->basePipelineIndex = -1; |
379 | } else { |
380 | create_info->basePipelineHandle = VK_NULL_HANDLE; |
381 | create_info->basePipelineIndex = 0; |
382 | } |
383 | |
384 | VkResult res = |
385 | vkCreateGraphicsPipelines(device, cache ? cache->cache : VK_NULL_HANDLE, |
386 | 1, create_info, nullptr, &obj->pipeline); |
387 | BAIL_ON_VK_BAD_RESULT_NO_RETURN(res, "failed to create graphics pipeline" ); |
388 | |
389 | return obj; |
390 | } |
391 | |
392 | IVkPipeline create_raytracing_pipeline( |
393 | VkDevice device, |
394 | VkRayTracingPipelineCreateInfoKHR *create_info, |
395 | IVkPipelineLayout layout, |
396 | std::vector<IVkPipeline> &pipeline_libraries, |
397 | VkDeferredOperationKHR deferredOperation, |
398 | IVkPipelineCache cache, |
399 | IVkPipeline base_pipeline) { |
400 | IVkPipeline obj = std::make_shared<DeviceObjVkPipeline>(); |
401 | obj->device = device; |
402 | obj->ref_layout = layout; |
403 | obj->ref_cache = cache; |
404 | obj->ref_pipeline_libraries = pipeline_libraries; |
405 | |
406 | create_info->layout = layout->layout; |
407 | |
408 | if (base_pipeline) { |
409 | create_info->basePipelineHandle = base_pipeline->pipeline; |
410 | create_info->basePipelineIndex = -1; |
411 | } else { |
412 | create_info->basePipelineHandle = VK_NULL_HANDLE; |
413 | create_info->basePipelineIndex = 0; |
414 | } |
415 | |
416 | PFN_vkCreateRayTracingPipelinesKHR create_raytracing_pipeline_khr = |
417 | PFN_vkCreateRayTracingPipelinesKHR(vkGetInstanceProcAddr( |
418 | taichi::lang::vulkan::VulkanLoader::instance().get_instance(), |
419 | "vkCreateRayTracingPipelinesKHR" )); |
420 | |
421 | VkResult res = create_raytracing_pipeline_khr( |
422 | device, deferredOperation, cache ? cache->cache : VK_NULL_HANDLE, 1, |
423 | create_info, nullptr, &obj->pipeline); |
424 | BAIL_ON_VK_BAD_RESULT_NO_RETURN(res, "failed to create raytracing pipeline" ); |
425 | |
426 | return obj; |
427 | } |
428 | |
429 | IVkSampler create_sampler(VkDevice device, const VkSamplerCreateInfo &info) { |
430 | IVkSampler sampler = std::make_shared<DeviceObjVkSampler>(); |
431 | sampler->device = device; |
432 | |
433 | BAIL_ON_VK_BAD_RESULT_NO_RETURN( |
434 | vkCreateSampler(device, &info, nullptr, &sampler->sampler), |
435 | "failed to create texture sampler!" ); |
436 | |
437 | return sampler; |
438 | } |
439 | |
440 | IVkImage create_image(VkDevice device, |
441 | VmaAllocator allocator, |
442 | VkImageCreateInfo *image_info, |
443 | VmaAllocationCreateInfo *alloc_info) { |
444 | IVkImage image = std::make_shared<DeviceObjVkImage>(); |
445 | image->device = device; |
446 | image->allocator = allocator; |
447 | image->format = image_info->format; |
448 | image->type = image_info->imageType; |
449 | image->width = image_info->extent.width; |
450 | image->height = image_info->extent.height; |
451 | image->depth = image_info->extent.depth; |
452 | image->mip_levels = image_info->mipLevels; |
453 | image->array_layers = image_info->arrayLayers; |
454 | image->usage = image_info->usage; |
455 | |
456 | VkResult res = vmaCreateImage(allocator, image_info, alloc_info, |
457 | &image->image, &image->allocation, nullptr); |
458 | BAIL_ON_VK_BAD_RESULT_NO_RETURN(res, "failed to create image" ); |
459 | |
460 | return image; |
461 | } |
462 | |
463 | IVkImage create_image(VkDevice device, |
464 | VkImage image, |
465 | VkFormat format, |
466 | VkImageType type, |
467 | VkExtent3D extent, |
468 | uint32_t mip_levels, |
469 | uint32_t array_layers, |
470 | VkImageUsageFlags usage) { |
471 | IVkImage obj = std::make_shared<DeviceObjVkImage>(); |
472 | obj->device = device; |
473 | obj->image = image; |
474 | obj->format = format; |
475 | obj->type = type; |
476 | obj->width = extent.width; |
477 | obj->height = extent.height; |
478 | obj->depth = extent.depth; |
479 | obj->mip_levels = mip_levels; |
480 | obj->array_layers = array_layers; |
481 | obj->usage = usage; |
482 | |
483 | return obj; |
484 | } |
485 | |
486 | IVkImageView create_image_view(VkDevice device, |
487 | IVkImage image, |
488 | VkImageViewCreateInfo *create_info) { |
489 | IVkImageView view = std::make_shared<DeviceObjVkImageView>(); |
490 | view->device = device; |
491 | view->ref_image = image; |
492 | view->subresource_range = create_info->subresourceRange; |
493 | view->type = create_info->viewType; |
494 | |
495 | create_info->image = image->image; |
496 | |
497 | VkResult res = vkCreateImageView(device, create_info, nullptr, &view->view); |
498 | BAIL_ON_VK_BAD_RESULT_NO_RETURN(res, "failed to create image view" ); |
499 | |
500 | return view; |
501 | } |
502 | |
503 | IVkFramebuffer create_framebuffer(VkFramebufferCreateFlags flags, |
504 | IVkRenderPass renderpass, |
505 | const std::vector<IVkImageView> &attachments, |
506 | uint32_t width, |
507 | uint32_t height, |
508 | uint32_t layers, |
509 | void *pnext) { |
510 | IVkFramebuffer obj = std::make_shared<DeviceObjVkFramebuffer>(); |
511 | obj->device = renderpass->device; |
512 | obj->ref_attachments = attachments; |
513 | obj->ref_renderpass = renderpass; |
514 | |
515 | std::vector<VkImageView> views(attachments.size()); |
516 | for (int i = 0; i < attachments.size(); i++) { |
517 | views[i] = attachments[i]->view; |
518 | } |
519 | |
520 | VkFramebufferCreateInfo info{}; |
521 | info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; |
522 | info.pNext = pnext; |
523 | info.flags = flags; |
524 | info.renderPass = renderpass->renderpass; |
525 | info.attachmentCount = uint32_t(attachments.size()); |
526 | info.pAttachments = views.data(); |
527 | info.width = width; |
528 | info.height = height; |
529 | info.layers = layers; |
530 | |
531 | VkResult res = vkCreateFramebuffer(renderpass->device, &info, nullptr, |
532 | &obj->framebuffer); |
533 | BAIL_ON_VK_BAD_RESULT_NO_RETURN(res, "failed to create framebuffer" ); |
534 | |
535 | return obj; |
536 | } |
537 | |
538 | IVkBuffer create_buffer(VkDevice device, |
539 | VmaAllocator allocator, |
540 | VkBufferCreateInfo *buffer_info, |
541 | VmaAllocationCreateInfo *alloc_info) { |
542 | IVkBuffer buffer = std::make_shared<DeviceObjVkBuffer>(); |
543 | buffer->device = device; |
544 | buffer->allocator = allocator; |
545 | buffer->usage = buffer_info->usage; |
546 | |
547 | VkResult res = vmaCreateBuffer(allocator, buffer_info, alloc_info, |
548 | &buffer->buffer, &buffer->allocation, nullptr); |
549 | if (res == VK_ERROR_OUT_OF_DEVICE_MEMORY) { |
550 | throw std::bad_alloc(); |
551 | } // FIXME: (damnkk) Should be removed when RHI error codes are ready |
552 | BAIL_ON_VK_BAD_RESULT_NO_RETURN(res, "failed to create buffer" ); |
553 | |
554 | return buffer; |
555 | } |
556 | |
557 | IVkBuffer create_buffer(VkDevice device, |
558 | VkBuffer buffer, |
559 | VkBufferUsageFlags usage) { |
560 | IVkBuffer obj = std::make_shared<DeviceObjVkBuffer>(); |
561 | obj->device = device; |
562 | obj->buffer = buffer; |
563 | obj->usage = usage; |
564 | |
565 | return obj; |
566 | } |
567 | |
568 | IVkBufferView create_buffer_view(IVkBuffer buffer, |
569 | VkBufferViewCreateFlags flags, |
570 | VkFormat format, |
571 | VkDeviceSize offset, |
572 | VkDeviceSize range) { |
573 | IVkBufferView view = std::make_shared<DeviceObjVkBufferView>(); |
574 | view->device = buffer->device; |
575 | view->ref_buffer = buffer; |
576 | view->format = format; |
577 | view->offset = offset; |
578 | view->range = range; |
579 | |
580 | VkBufferViewCreateInfo info{}; |
581 | info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO; |
582 | info.pNext = nullptr; |
583 | info.flags = flags; |
584 | info.buffer = buffer->buffer; |
585 | info.format = format; |
586 | info.offset = offset; |
587 | info.range = range; |
588 | |
589 | VkResult res = |
590 | vkCreateBufferView(buffer->device, &info, nullptr, &view->view); |
591 | BAIL_ON_VK_BAD_RESULT_NO_RETURN(res, "failed to create buffer view" ); |
592 | |
593 | return view; |
594 | } |
595 | |
596 | IVkAccelerationStructureKHR create_acceleration_structure( |
597 | VkAccelerationStructureCreateFlagsKHR flags, |
598 | IVkBuffer buffer, |
599 | VkDeviceSize offset, |
600 | VkDeviceSize size, |
601 | VkAccelerationStructureTypeKHR type) { |
602 | IVkAccelerationStructureKHR obj = |
603 | std::make_shared<DeviceObjVkAccelerationStructureKHR>(); |
604 | obj->device = buffer->device; |
605 | obj->ref_buffer = buffer; |
606 | obj->offset = offset; |
607 | obj->size = size; |
608 | obj->type = type; |
609 | |
610 | VkAccelerationStructureCreateInfoKHR info{}; |
611 | info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; |
612 | info.pNext = nullptr; |
613 | info.createFlags = flags; |
614 | info.buffer = buffer->buffer; |
615 | info.offset = offset; |
616 | info.size = size; |
617 | info.type = type; |
618 | info.deviceAddress = 0; |
619 | |
620 | PFN_vkCreateAccelerationStructureKHR create_acceleration_structure_khr = |
621 | PFN_vkCreateAccelerationStructureKHR(vkGetInstanceProcAddr( |
622 | taichi::lang::vulkan::VulkanLoader::instance().get_instance(), |
623 | "vkCreateAccelerationStructureKHR" )); |
624 | |
625 | VkResult res = create_acceleration_structure_khr(buffer->device, &info, |
626 | nullptr, &obj->accel); |
627 | BAIL_ON_VK_BAD_RESULT_NO_RETURN(res, |
628 | "failed to create acceleration structure" ); |
629 | |
630 | return obj; |
631 | } |
632 | |
633 | IVkQueryPool create_query_pool(VkDevice device) { |
634 | VkQueryPoolCreateInfo info{}; |
635 | info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; |
636 | info.pNext = nullptr; |
637 | info.queryCount = 2; |
638 | info.queryType = VK_QUERY_TYPE_TIMESTAMP; |
639 | |
640 | VkQueryPool query_pool; |
641 | VkResult res = vkCreateQueryPool(device, &info, nullptr, &query_pool); |
642 | BAIL_ON_VK_BAD_RESULT_NO_RETURN(res, "failed to create query pool" ); |
643 | |
644 | IVkQueryPool obj = std::make_shared<DeviceObjVkQueryPool>(); |
645 | obj->device = device; |
646 | obj->query_pool = query_pool; |
647 | |
648 | return obj; |
649 | } |
650 | |
651 | } // namespace vkapi |
652 | |