Blender V5.0
cuda/graphics_interop.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#ifdef WITH_CUDA
6
8
10# include "device/cuda/util.h"
11
13
14# ifdef _WIN32
15# include "util/windows.h"
16# else
17# include <unistd.h>
18# endif
19
21
22CUDADeviceGraphicsInterop::CUDADeviceGraphicsInterop(CUDADeviceQueue *queue)
23 : queue_(queue), device_(static_cast<CUDADevice *>(queue->device))
24{
25}
26
27CUDADeviceGraphicsInterop::~CUDADeviceGraphicsInterop()
28{
29 CUDAContextScope scope(device_);
30 free();
31}
32
33void CUDADeviceGraphicsInterop::set_buffer(GraphicsInteropBuffer &interop_buffer)
34{
35 CUDAContextScope scope(device_);
36
37 if (interop_buffer.is_empty()) {
38 free();
39 return;
40 }
41
42 need_zero_ |= interop_buffer.take_zero();
43
44 if (!interop_buffer.has_new_handle()) {
45 return;
46 }
47 free();
48
49 switch (interop_buffer.get_type()) {
51 const CUresult result = cuGraphicsGLRegisterBuffer(&cu_graphics_resource_,
52 interop_buffer.take_handle(),
53 CU_GRAPHICS_MAP_RESOURCE_FLAGS_NONE);
54 if (result != CUDA_SUCCESS) {
55 LOG_ERROR << "Error registering OpenGL buffer: " << cuewErrorString(result);
56 break;
57 }
58
59 buffer_size_ = interop_buffer.get_size();
60 break;
61 }
63 CUDA_EXTERNAL_MEMORY_HANDLE_DESC external_memory_handle_desc = {};
64# ifdef _WIN32
65 /* cuImportExternalMemory will not take ownership of the handle. */
66 vulkan_windows_handle_ = interop_buffer.take_handle();
67 external_memory_handle_desc.type = CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32;
68 external_memory_handle_desc.handle.win32.handle = reinterpret_cast<void *>(
69 vulkan_windows_handle_);
70# else
71 /* cuImportExternalMemory will take ownership of the handle. */
72 external_memory_handle_desc.type = CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD;
73 external_memory_handle_desc.handle.fd = interop_buffer.take_handle();
74# endif
75 external_memory_handle_desc.size = interop_buffer.get_size();
76
77 CUresult result = cuImportExternalMemory(&cu_external_memory_, &external_memory_handle_desc);
78 if (result != CUDA_SUCCESS) {
79# ifdef _WIN32
80 CloseHandle(HANDLE(vulkan_windows_handle_));
81 vulkan_windows_handle_ = 0;
82# else
83 close(external_memory_handle_desc.handle.fd);
84# endif
85 LOG_ERROR << "Error importing Vulkan memory: " << cuewErrorString(result);
86 break;
87 }
88
89 buffer_size_ = interop_buffer.get_size();
90
91 CUDA_EXTERNAL_MEMORY_BUFFER_DESC external_memory_buffer_desc = {};
92 external_memory_buffer_desc.size = external_memory_handle_desc.size;
93 external_memory_buffer_desc.offset = 0;
94
95 CUdeviceptr external_memory_device_ptr = 0;
96 result = cuExternalMemoryGetMappedBuffer(
97 &external_memory_device_ptr, cu_external_memory_, &external_memory_buffer_desc);
98 if (result != CUDA_SUCCESS) {
99 if (external_memory_device_ptr) {
100 cuMemFree(external_memory_device_ptr);
101 external_memory_device_ptr = 0;
102 }
103
104 LOG_ERROR << "Error mapping Vulkan memory: " << cuewErrorString(result);
105 break;
106 }
107
108 cu_external_memory_ptr_ = external_memory_device_ptr;
109 break;
110 }
113 break;
114 }
115}
116
117device_ptr CUDADeviceGraphicsInterop::map()
118{
119 CUdeviceptr cu_buffer = 0;
120
121 if (cu_graphics_resource_) {
122 /* OpenGL buffer needs mapping. */
123 CUDAContextScope scope(device_);
124 size_t bytes;
125
126 cuda_device_assert(device_,
127 cuGraphicsMapResources(1, &cu_graphics_resource_, queue_->stream()));
128 cuda_device_assert(
129 device_, cuGraphicsResourceGetMappedPointer(&cu_buffer, &bytes, cu_graphics_resource_));
130 }
131 else {
132 /* Vulkan buffer is always mapped. */
133 cu_buffer = cu_external_memory_ptr_;
134 }
135
136 if (cu_buffer && need_zero_) {
137 cuda_device_assert(device_, cuMemsetD8Async(cu_buffer, 0, buffer_size_, queue_->stream()));
138
139 need_zero_ = false;
140 }
141
142 return static_cast<device_ptr>(cu_buffer);
143}
144
145void CUDADeviceGraphicsInterop::unmap()
146{
147 if (cu_graphics_resource_) {
148 CUDAContextScope scope(device_);
149
150 cuda_device_assert(device_,
151 cuGraphicsUnmapResources(1, &cu_graphics_resource_, queue_->stream()));
152 }
153}
154
155void CUDADeviceGraphicsInterop::free()
156{
157 if (cu_graphics_resource_) {
158 cuda_device_assert(device_, cuGraphicsUnregisterResource(cu_graphics_resource_));
159 cu_graphics_resource_ = nullptr;
160 }
161
162 if (cu_external_memory_ptr_) {
163 cuda_device_assert(device_, cuMemFree(cu_external_memory_ptr_));
164 cu_external_memory_ptr_ = 0;
165 }
166
167 if (cu_external_memory_) {
168 cuda_device_assert(device_, cuDestroyExternalMemory(cu_external_memory_));
169 cu_external_memory_ = nullptr;
170 }
171
172# ifdef _WIN32
173 if (vulkan_windows_handle_) {
174 CloseHandle(HANDLE(vulkan_windows_handle_));
175 vulkan_windows_handle_ = 0;
176 }
177# endif
178
179 buffer_size_ = 0;
180
181 need_zero_ = false;
182}
183
185
186#endif
void BLI_kdtree_nd_ free(KDTree *tree)
GraphicsInteropDevice::Type get_type() const
#define CCL_NAMESPACE_END
#define LOG_ERROR
Definition log.h:101
uint64_t device_ptr
Definition types_base.h:44