1010#include " vulkan_resources.h"
1111
1212using namespace Halide ::Runtime::Internal::Vulkan;
13+ using Halide::Runtime::Internal::MemoryOwnership;
14+
15+ // --------------------------------------------------------------------------
16+
17+ namespace Halide {
18+ namespace Runtime {
19+ namespace Internal {
20+ namespace Vulkan {
21+
22+ ALWAYS_INLINE uint64_t vk_external_buffer_offset_bytes (void *user_context, VulkanMemoryAllocator *allocator, MemoryRegion *region) {
23+ halide_debug_assert (user_context, region != nullptr );
24+ MemoryRegion *owner = allocator->owner_of (user_context, region);
25+ return (owner != nullptr && owner->ownership == MemoryOwnership::Wrapped) ? owner->allocation .offset : 0 ;
26+ }
27+
28+ ALWAYS_INLINE uint64_t vk_total_buffer_offset_bytes (void *user_context, VulkanMemoryAllocator *allocator, MemoryRegion *region, halide_type_t type) {
29+ return vk_external_buffer_offset_bytes (user_context, allocator, region) + (region->indexing .offset * type.bytes ());
30+ }
31+
32+ ALWAYS_INLINE void vk_destroy_wrapped_region (void *user_context,
33+ VulkanMemoryAllocator *allocator,
34+ MemoryRegion *region) {
35+ if (region == nullptr ) {
36+ return ;
37+ }
38+
39+ MemoryRegion *owner = allocator->owner_of (user_context, region);
40+ if (owner == nullptr ) {
41+ return ;
42+ }
43+
44+ if (region != owner && region->ownership == MemoryOwnership::CropAlias) {
45+ vk_host_free (user_context, region, allocator->callbacks ());
46+ return ;
47+ }
48+
49+ if (owner->ownership != MemoryOwnership::Wrapped) {
50+ return ;
51+ }
52+
53+ vk_host_free (user_context, owner->handle , allocator->callbacks ());
54+ vk_host_free (user_context, owner, allocator->callbacks ());
55+ }
56+
57+ ALWAYS_INLINE MemoryRegion *vk_create_wrapped_buffer_region (void *user_context,
58+ halide_buffer_t *buf,
59+ VkBuffer vk_buffer,
60+ uint64_t offset,
61+ const VkAllocationCallbacks *callbacks) {
62+ constexpr VkSystemAllocationScope alloc_scope = VK_SYSTEM_ALLOCATION_SCOPE_OBJECT ;
63+ VkBuffer *native_handle = reinterpret_cast <VkBuffer *>(
64+ vk_host_malloc (user_context, sizeof (VkBuffer), 0 , alloc_scope, callbacks));
65+ if (native_handle == nullptr ) {
66+ error (user_context) << " Vulkan: Failed to allocate wrapped buffer handle metadata.\n " ;
67+ return nullptr ;
68+ }
69+
70+ MemoryRegion *region = reinterpret_cast <MemoryRegion *>(
71+ vk_host_malloc (user_context, sizeof (MemoryRegion), 0 , alloc_scope, callbacks));
72+ if (region == nullptr ) {
73+ vk_host_free (user_context, native_handle, callbacks);
74+ error (user_context) << " Vulkan: Failed to allocate wrapped buffer region metadata.\n " ;
75+ return nullptr ;
76+ }
77+
78+ *native_handle = vk_buffer;
79+ memset (region, 0 , sizeof (MemoryRegion));
80+ region->handle = native_handle;
81+ region->allocation .offset = offset;
82+ region->allocation .size = buf->size_in_bytes ();
83+ region->is_owner = true ;
84+ region->ownership = MemoryOwnership::Wrapped;
85+ region->owner = nullptr ;
86+ return region;
87+ }
88+
89+ } // namespace Vulkan
90+ } // namespace Internal
91+ } // namespace Runtime
92+ } // namespace Halide
1393
1494// --------------------------------------------------------------------------
1595
@@ -110,12 +190,20 @@ WEAK int halide_vulkan_device_free(void *user_context, halide_buffer_t *halide_b
110190
111191 // get the allocated region for the device
112192 MemoryRegion *device_region = reinterpret_cast <MemoryRegion *>(halide_buffer->device );
193+ #ifdef DEBUG_RUNTIME
194+ const uint64_t device_region_size = device_region->allocation .size ;
195+ #endif
113196 MemoryRegion *memory_region = ctx.allocator ->owner_of (user_context, device_region);
114197 if (ctx.allocator && memory_region && memory_region->handle ) {
115- if (halide_can_reuse_device_allocations (user_context)) {
116- ctx.allocator ->release (user_context, memory_region);
198+ if (memory_region->ownership == MemoryOwnership::Wrapped) {
199+ debug (user_context) << " Vulkan: Releasing wrapped external buffer metadata only.\n " ;
200+ vk_destroy_wrapped_region (user_context, ctx.allocator , device_region);
117201 } else {
118- ctx.allocator ->reclaim (user_context, memory_region);
202+ if (halide_can_reuse_device_allocations (user_context)) {
203+ ctx.allocator ->release (user_context, memory_region);
204+ } else {
205+ ctx.allocator ->reclaim (user_context, memory_region);
206+ }
119207 }
120208 }
121209 halide_buffer->device = 0 ;
@@ -126,7 +214,7 @@ WEAK int halide_vulkan_device_free(void *user_context, halide_buffer_t *halide_b
126214 debug (user_context) << " Vulkan: Released memory for device region ("
127215 << " user_context: " << user_context << " , "
128216 << " buffer: " << halide_buffer << " , "
129- << " size_in_bytes: " << ( uint64_t )device_region-> allocation . size << " )\n " ;
217+ << " size_in_bytes: " << device_region_size << " )\n " ;
130218
131219 uint64_t t_after = halide_current_time_ns (user_context);
132220 debug (user_context) << " Time: " << (t_after - t_before) / 1.0e6 << " ms\n " ;
@@ -272,15 +360,24 @@ WEAK int halide_vulkan_device_malloc(void *user_context, halide_buffer_t *buf) {
272360 size_t size = buf->size_in_bytes ();
273361 if (buf->device ) {
274362 MemoryRegion *device_region = (MemoryRegion *)(buf->device );
275- if (device_region->allocation .size >= size) {
363+ MemoryRegion *memory_region = ctx.allocator ->owner_of (user_context, device_region);
364+ if (memory_region != nullptr && memory_region->allocation .size >= size) {
276365 debug (user_context) << " Vulkan: Requested allocation for existing device memory ... using existing buffer!\n " ;
277366 return halide_error_code_success;
278367 } else {
368+ if (memory_region == nullptr ) {
369+ error (user_context) << " Vulkan: Failed to retrieve memory region for existing device buffer!\n " ;
370+ return halide_error_code_internal_error;
371+ }
372+ if (memory_region->ownership == MemoryOwnership::Wrapped) {
373+ error (user_context) << " Vulkan: Wrapped external buffer is too small for requested allocation!\n " ;
374+ return halide_error_code_device_malloc_failed;
375+ }
279376 debug (user_context) << " Vulkan: Requested allocation of different size ... reallocating buffer!\n " ;
280377 if (halide_can_reuse_device_allocations (user_context)) {
281- ctx.allocator ->release (user_context, device_region );
378+ ctx.allocator ->release (user_context, memory_region );
282379 } else {
283- ctx.allocator ->reclaim (user_context, device_region );
380+ ctx.allocator ->reclaim (user_context, memory_region );
284381 }
285382 buf->device = 0 ;
286383 }
@@ -487,7 +584,7 @@ WEAK int halide_vulkan_copy_to_device(void *user_context, halide_buffer_t *halid
487584 bool to_host = false ;
488585
489586 uint64_t src_offset = copy_helper.src_begin ;
490- uint64_t dst_offset = copy_helper.dst_begin + (device_region-> indexing . offset * halide_buffer->type . bytes () );
587+ uint64_t dst_offset = copy_helper.dst_begin + vk_total_buffer_offset_bytes (user_context, ctx. allocator , device_region, halide_buffer->type );
491588
492589 copy_helper.src = (uint64_t )(staging_buffer);
493590 copy_helper.dst = (uint64_t )(device_buffer);
@@ -656,7 +753,7 @@ WEAK int halide_vulkan_copy_to_host(void *user_context, halide_buffer_t *halide_
656753 bool from_host = false ;
657754 bool to_host = true ;
658755 uint64_t copy_dst = copy_helper.dst ;
659- uint64_t src_offset = copy_helper.src_begin + (device_region-> indexing . offset * halide_buffer->type . bytes () );
756+ uint64_t src_offset = copy_helper.src_begin + vk_total_buffer_offset_bytes (user_context, ctx. allocator , device_region, halide_buffer->type );
660757 uint64_t dst_offset = copy_helper.dst_begin ;
661758
662759 copy_helper.src = (uint64_t )(device_buffer);
@@ -937,8 +1034,8 @@ WEAK int halide_vulkan_buffer_copy(void *user_context, struct halide_buffer_t *s
9371034
9381035 // define the src and dst config
9391036 uint64_t copy_dst = copy_helper.dst ;
940- uint64_t src_offset = copy_helper.src_begin + (src_buffer_region-> indexing . offset * src->type . bytes () );
941- uint64_t dst_offset = copy_helper.dst_begin + (dst_buffer_region-> indexing . offset * dst->type . bytes () );
1037+ uint64_t src_offset = copy_helper.src_begin + vk_total_buffer_offset_bytes (user_context, ctx. allocator , src_buffer_region, src->type );
1038+ uint64_t dst_offset = copy_helper.dst_begin + vk_total_buffer_offset_bytes (user_context, ctx. allocator , dst_buffer_region, dst->type );
9421039
9431040 copy_helper.src = (uint64_t )(src_device_buffer);
9441041 copy_helper.dst = (uint64_t )(dst_device_buffer);
@@ -1345,13 +1442,33 @@ WEAK int halide_vulkan_device_and_host_free(void *user_context, struct halide_bu
13451442 return halide_default_device_and_host_free (user_context, buf, &vulkan_device_interface);
13461443}
13471444
1348- WEAK int halide_vulkan_wrap_vk_buffer (void *user_context, struct halide_buffer_t *buf, uint64_t vk_buffer) {
1445+ WEAK int halide_vulkan_wrap_vk_buffer (void *user_context,
1446+ struct halide_buffer_t *buf,
1447+ uint64_t vk_buffer,
1448+ uint64_t offset) {
13491449 halide_debug_assert (user_context, buf->device == 0 );
13501450 if (buf->device != 0 ) {
13511451 error (user_context) << " Vulkan: Unable to wrap buffer ... invalid device pointer!\n " ;
13521452 return halide_error_code_device_wrap_native_failed;
13531453 }
1354- buf->device = vk_buffer;
1454+ if (vk_buffer == 0 ) {
1455+ error (user_context) << " Vulkan: Unable to wrap buffer ... invalid VkBuffer handle!\n " ;
1456+ return halide_error_code_device_wrap_native_failed;
1457+ }
1458+
1459+ VulkanContext ctx (user_context);
1460+ if (ctx.error != halide_error_code_success) {
1461+ error (user_context) << " Vulkan: Failed to acquire context!\n " ;
1462+ return ctx.error ;
1463+ }
1464+
1465+ MemoryRegion *region = vk_create_wrapped_buffer_region (
1466+ user_context, buf, reinterpret_cast <VkBuffer>(vk_buffer), offset, ctx.allocator ->callbacks ());
1467+ if (region == nullptr ) {
1468+ return halide_error_code_out_of_memory;
1469+ }
1470+
1471+ buf->device = reinterpret_cast <uint64_t >(region);
13551472 buf->device_interface = &vulkan_device_interface;
13561473 buf->device_interface ->impl ->use_module ();
13571474 return halide_error_code_success;
@@ -1365,6 +1482,19 @@ WEAK int halide_vulkan_detach_vk_buffer(void *user_context, halide_buffer_t *buf
13651482 error (user_context) << " Vulkan: Unable to detach buffer ... invalid device interface!\n " ;
13661483 return halide_error_code_incompatible_device_interface;
13671484 }
1485+ MemoryRegion *device_region = reinterpret_cast <MemoryRegion *>(buf->device );
1486+ VulkanContext ctx (user_context);
1487+ if (ctx.error != halide_error_code_success) {
1488+ error (user_context) << " Vulkan: Failed to acquire context!\n " ;
1489+ return ctx.error ;
1490+ }
1491+
1492+ MemoryRegion *owner = ctx.allocator ->owner_of (user_context, device_region);
1493+ if (owner == nullptr || owner->ownership != MemoryOwnership::Wrapped) {
1494+ error (user_context) << " Vulkan: Unable to detach buffer ... buffer is not externally wrapped!\n " ;
1495+ return halide_error_code_device_detach_native_failed;
1496+ }
1497+ vk_destroy_wrapped_region (user_context, ctx.allocator , device_region);
13681498 buf->device = 0 ;
13691499 buf->device_interface ->impl ->release_module ();
13701500 buf->device_interface = nullptr ;
@@ -1376,7 +1506,29 @@ WEAK uintptr_t halide_vulkan_get_vk_buffer(void *user_context, halide_buffer_t *
13761506 return 0 ;
13771507 }
13781508 halide_debug_assert (user_context, buf->device_interface == &vulkan_device_interface);
1379- return (uintptr_t )buf->device ;
1509+ MemoryRegion *device_region = reinterpret_cast <MemoryRegion *>(buf->device );
1510+ VulkanContext ctx (user_context);
1511+ if (ctx.error != halide_error_code_success) {
1512+ return 0 ;
1513+ }
1514+ MemoryRegion *owner = ctx.allocator ->owner_of (user_context, device_region);
1515+ if (owner == nullptr || owner->handle == nullptr ) {
1516+ return 0 ;
1517+ }
1518+ return (uintptr_t )(*reinterpret_cast <VkBuffer *>(owner->handle ));
1519+ }
1520+
1521+ WEAK uint64_t halide_vulkan_get_vk_crop_offset (void *user_context, halide_buffer_t *buf) {
1522+ if (buf->device == 0 ) {
1523+ return 0 ;
1524+ }
1525+ halide_debug_assert (user_context, buf->device_interface == &vulkan_device_interface);
1526+ MemoryRegion *device_region = reinterpret_cast <MemoryRegion *>(buf->device );
1527+ VulkanContext ctx (user_context);
1528+ if (ctx.error != halide_error_code_success) {
1529+ return 0 ;
1530+ }
1531+ return vk_total_buffer_offset_bytes (user_context, ctx.allocator , device_region, buf->type );
13801532}
13811533
13821534WEAK const struct halide_device_interface_t *halide_vulkan_device_interface () {
@@ -1445,6 +1597,10 @@ namespace Vulkan {
14451597
14461598// --------------------------------------------------------------------------
14471599
1600+ int vk_wrap_native_vk_buffer (void *user_context, struct halide_buffer_t *buf, uint64_t vk_buffer) {
1601+ return halide_vulkan_wrap_vk_buffer (user_context, buf, vk_buffer, 0 );
1602+ }
1603+
14481604WEAK halide_device_interface_impl_t vulkan_device_interface_impl = {
14491605 halide_use_jit_module,
14501606 halide_release_jit_module,
@@ -1460,7 +1616,7 @@ WEAK halide_device_interface_impl_t vulkan_device_interface_impl = {
14601616 halide_vulkan_device_crop,
14611617 halide_vulkan_device_slice,
14621618 halide_vulkan_device_release_crop,
1463- halide_vulkan_wrap_vk_buffer ,
1619+ vk_wrap_native_vk_buffer ,
14641620 halide_vulkan_detach_vk_buffer,
14651621};
14661622
0 commit comments