xref: /aosp_15_r20/external/OpenCL-CTS/test_conformance/common/vulkan_wrapper/vulkan_wrapper.cpp (revision 6467f958c7de8070b317fc65bcb0f6472e388d82)
1 //
2 // Copyright (c) 2022 The Khronos Group Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //    http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #ifdef _WIN32
18 #include <Windows.h>
19 #include <dxgi1_2.h>
20 #include <aclapi.h>
21 #include <algorithm>
22 #endif
23 #include <vulkan/vulkan.h>
24 #include "vulkan_wrapper.hpp"
25 #if defined(__linux__) && !defined(__ANDROID__)
26 #include <gnu/libc-version.h>
27 #include <dlfcn.h>
28 #elif defined(__ANDROID__)
29 #include <dlfcn.h>
30 #endif
31 #if defined _WIN32
32 #define LoadFunction GetProcAddress
33 #elif defined __linux
34 #define LoadFunction dlsym
35 #endif
36 
37 extern "C" {
38 #define VK_FUNC_DECL(name) PFN_##name _##name = NULL;
39 VK_FUNC_LIST
40 #if defined(_WIN32) || defined(_WIN64)
41 VK_WINDOWS_FUNC_LIST
42 #endif
43 #undef VK_FUNC_DECL
44 }
45 
46 #define WAIVED 2
47 #define HANDLE_ERROR -1
48 
49 #define CHECK_VK(call)                                                         \
50     if (call != VK_SUCCESS) return call;
51 ///////////////////////////////////
52 // VulkanInstance implementation //
53 ///////////////////////////////////
54 
VulkanInstance(const VulkanInstance & instance)55 VulkanInstance::VulkanInstance(const VulkanInstance &instance)
56     : m_vkInstance(instance.m_vkInstance),
57       m_physicalDeviceList(instance.m_physicalDeviceList)
58 {}
59 
VulkanInstance()60 VulkanInstance::VulkanInstance(): m_vkInstance(VK_NULL_HANDLE)
61 {
62 #if defined(__linux__) && !defined(__ANDROID__)
63     char *glibcVersion = strdup(gnu_get_libc_version());
64     int majNum = (int)atoi(strtok(glibcVersion, "."));
65     int minNum = (int)atoi(strtok(NULL, "."));
66     free(glibcVersion);
67     if ((majNum < 2) || (majNum == 2 && minNum < 17))
68     {
69         // WAIVE_TEST() << "Insufficient GLIBC version. Test waived!";
70     }
71 #endif
72 
73 #if defined(_WIN32) || defined(_WIN64)
74     const char *vulkanLoaderLibraryName = "vulkan-1.dll";
75 #elif defined(__ANDROID__)
76     const char *vulkanLoaderLibraryName = "libvulkan.so";
77 #else
78     const char *vulkanLoaderLibraryName = "libvulkan.so.1";
79 #endif
80 #ifdef _WIN32
81     HINSTANCE hDLL;
82     hDLL = LoadLibrary(vulkanLoaderLibraryName);
83     if (hDLL == NULL)
84     {
85         throw std::runtime_error("LoadLibrary failed!");
86     }
87     vkGetInstanceProcAddr =
88         (PFN_vkGetInstanceProcAddr)LoadFunction(hDLL, "vkGetInstanceProcAddr");
89 #else
90 #if !defined(__APPLE__)
91     void *handle;
92     handle = dlopen(vulkanLoaderLibraryName, RTLD_LAZY);
93     if (!handle)
94     {
95         fputs(dlerror(), stderr);
96         throw std::runtime_error("dlopen failed !!!");
97     }
98     vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)LoadFunction(
99         handle, "vkGetInstanceProcAddr");
100 #endif
101 #endif
102     if ((unsigned long long)vkGetInstanceProcAddr == (unsigned long long)NULL)
103     {
104         throw std::runtime_error("vkGetInstanceProcAddr() not found!");
105     }
106 #define VK_GET_NULL_INSTANCE_PROC_ADDR(name)                                   \
107     _##name = (PFN_##name)vkGetInstanceProcAddr(NULL, #name);
108 
109     if ((unsigned long long)vkGetInstanceProcAddr == (unsigned long long)NULL)
110     {
111         throw std::runtime_error("Couldn't obtain address for function");
112     }
113     VK_GET_NULL_INSTANCE_PROC_ADDR(vkEnumerateInstanceExtensionProperties);
114     uint32_t instanceExtensionPropertiesCount;
115     VkResult vkStatus = VK_SUCCESS;
116     vkStatus = vkEnumerateInstanceExtensionProperties(
117         NULL, &instanceExtensionPropertiesCount, NULL);
118     // Something went wrong in vulkan initialization (most likely incompatible
119     // device/driver combination)
120     if (vkStatus == VK_ERROR_INCOMPATIBLE_DRIVER)
121     {
122         throw std::runtime_error(
123             "Waiving vulkan test because "
124             "vkEnumerateInstanceExtensionProperties failed.");
125         // return WAIVED;
126     }
127 
128     VK_GET_NULL_INSTANCE_PROC_ADDR(vkEnumerateInstanceVersion);
129     VK_GET_NULL_INSTANCE_PROC_ADDR(vkEnumerateInstanceLayerProperties);
130     VK_GET_NULL_INSTANCE_PROC_ADDR(vkCreateInstance);
131 #undef VK_GET_NULL_INSTANCE_PROC_ADDR
132 
133     VkApplicationInfo vkApplicationInfo = {};
134     vkApplicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
135     vkApplicationInfo.pNext = NULL;
136     vkApplicationInfo.pApplicationName = "Default app";
137     vkApplicationInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
138     vkApplicationInfo.pEngineName = "No engine";
139     vkApplicationInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
140     vkApplicationInfo.apiVersion = VK_API_VERSION_1_0;
141 
142     std::vector<const char *> enabledExtensionNameList;
143     enabledExtensionNameList.push_back(
144         VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
145     enabledExtensionNameList.push_back(
146         VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME);
147     enabledExtensionNameList.push_back(
148         VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME);
149 
150     std::vector<VkExtensionProperties> vkExtensionPropertiesList(
151         instanceExtensionPropertiesCount);
152     vkEnumerateInstanceExtensionProperties(NULL,
153                                            &instanceExtensionPropertiesCount,
154                                            vkExtensionPropertiesList.data());
155 
156     for (size_t eenIdx = 0; eenIdx < enabledExtensionNameList.size(); eenIdx++)
157     {
158         bool isSupported = false;
159         for (size_t epIdx = 0; epIdx < vkExtensionPropertiesList.size();
160              epIdx++)
161         {
162             if (!strcmp(enabledExtensionNameList[eenIdx],
163                         vkExtensionPropertiesList[epIdx].extensionName))
164             {
165                 isSupported = true;
166                 break;
167             }
168         }
169         if (!isSupported)
170         {
171             return;
172         }
173     }
174 
175     VkInstanceCreateInfo vkInstanceCreateInfo = {};
176     vkInstanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
177     vkInstanceCreateInfo.pNext = NULL;
178     vkInstanceCreateInfo.flags = 0;
179     vkInstanceCreateInfo.pApplicationInfo = &vkApplicationInfo;
180     vkInstanceCreateInfo.enabledLayerCount = 0;
181     vkInstanceCreateInfo.ppEnabledLayerNames = NULL;
182     vkInstanceCreateInfo.enabledExtensionCount =
183         (uint32_t)enabledExtensionNameList.size();
184     vkInstanceCreateInfo.ppEnabledExtensionNames =
185         enabledExtensionNameList.data();
186 
187     vkCreateInstance(&vkInstanceCreateInfo, NULL, &m_vkInstance);
188 
189 #define VK_FUNC_DECL(name)                                                     \
190     _##name = (PFN_##name)vkGetInstanceProcAddr(m_vkInstance, #name);          \
191     // ASSERT_NEQ((unsigned long long)name, 0ULL) << "Couldn't obtain address
192     // for function" << #name;
193 
194     VK_FUNC_LIST
195 #if defined(_WIN32) || defined(_WIN64)
196     VK_WINDOWS_FUNC_LIST
197 #endif
198 #undef VK_FUNC_DECL
199 
200     uint32_t physicalDeviceCount = 0;
201     vkEnumeratePhysicalDevices(m_vkInstance, &physicalDeviceCount, NULL);
202     // CHECK_NEQ(physicalDeviceCount, uint32_t(0));
203 
204     if (physicalDeviceCount == uint32_t(0))
205     {
206         std::cout << "failed to find GPUs with Vulkan support!\n";
207         return;
208     }
209 
210     std::vector<VkPhysicalDevice> vkPhysicalDeviceList(physicalDeviceCount,
211                                                        VK_NULL_HANDLE);
212     vkEnumeratePhysicalDevices(m_vkInstance, &physicalDeviceCount,
213                                vkPhysicalDeviceList.data());
214 
215     for (size_t ppdIdx = 0; ppdIdx < vkPhysicalDeviceList.size(); ppdIdx++)
216     {
217         VulkanPhysicalDevice *physicalDevice =
218             new VulkanPhysicalDevice(vkPhysicalDeviceList[ppdIdx]);
219         m_physicalDeviceList.add(*physicalDevice);
220     }
221 }
222 
~VulkanInstance()223 VulkanInstance::~VulkanInstance()
224 {
225     for (size_t pdIdx = 0; pdIdx < m_physicalDeviceList.size(); pdIdx++)
226     {
227         const VulkanPhysicalDevice &physicalDevice =
228             m_physicalDeviceList[pdIdx];
229         delete &physicalDevice;
230     }
231     if (m_vkInstance)
232     {
233         vkDestroyInstance(m_vkInstance, NULL);
234     }
235 }
236 
getPhysicalDeviceList() const237 const VulkanPhysicalDeviceList &VulkanInstance::getPhysicalDeviceList() const
238 {
239     return m_physicalDeviceList;
240 }
241 
operator VkInstance() const242 VulkanInstance::operator VkInstance() const { return m_vkInstance; }
243 
244 /////////////////////////////////////////
245 // VulkanPhysicalDevice implementation //
246 /////////////////////////////////////////
247 
VulkanPhysicalDevice(const VulkanPhysicalDevice & physicalDevice)248 VulkanPhysicalDevice::VulkanPhysicalDevice(
249     const VulkanPhysicalDevice &physicalDevice)
250     : m_vkPhysicalDevice(physicalDevice.m_vkPhysicalDevice),
251       m_vkPhysicalDeviceProperties(physicalDevice.m_vkPhysicalDeviceProperties),
252       m_vkDeviceNodeMask(physicalDevice.m_vkDeviceNodeMask),
253       m_vkPhysicalDeviceFeatures(physicalDevice.m_vkPhysicalDeviceFeatures),
254       m_vkPhysicalDeviceMemoryProperties(
255           physicalDevice.m_vkPhysicalDeviceMemoryProperties),
256       m_queueFamilyList(physicalDevice.m_queueFamilyList)
257 {
258     memcpy(m_vkDeviceUUID, physicalDevice.m_vkDeviceUUID, VK_UUID_SIZE);
259 }
260 
VulkanPhysicalDevice(VkPhysicalDevice vkPhysicalDevice)261 VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkPhysicalDevice)
262     : m_vkPhysicalDevice(vkPhysicalDevice)
263 {
264     if (m_vkPhysicalDevice == (VkPhysicalDevice)VK_NULL_HANDLE)
265     {
266         throw std::runtime_error("failed to find a suitable GPU!");
267     }
268 
269     vkGetPhysicalDeviceProperties(m_vkPhysicalDevice,
270                                   &m_vkPhysicalDeviceProperties);
271     vkGetPhysicalDeviceFeatures(m_vkPhysicalDevice,
272                                 &m_vkPhysicalDeviceFeatures);
273 
274     VkPhysicalDeviceIDPropertiesKHR vkPhysicalDeviceIDPropertiesKHR = {};
275     vkPhysicalDeviceIDPropertiesKHR.sType =
276         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR;
277     vkPhysicalDeviceIDPropertiesKHR.pNext = NULL;
278 
279     VkPhysicalDeviceProperties2 vkPhysicalDeviceProperties2 = {};
280     vkPhysicalDeviceProperties2.sType =
281         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
282     vkPhysicalDeviceProperties2.pNext = &vkPhysicalDeviceIDPropertiesKHR;
283 
284     vkGetPhysicalDeviceProperties2(m_vkPhysicalDevice,
285                                    &vkPhysicalDeviceProperties2);
286 
287     memcpy(m_vkDeviceUUID, vkPhysicalDeviceIDPropertiesKHR.deviceUUID,
288            sizeof(m_vkDeviceUUID));
289     memcpy(m_vkDeviceLUID, vkPhysicalDeviceIDPropertiesKHR.deviceLUID,
290            sizeof(m_vkDeviceLUID));
291     m_vkDeviceNodeMask = vkPhysicalDeviceIDPropertiesKHR.deviceNodeMask;
292 
293     uint32_t queueFamilyCount = 0;
294     vkGetPhysicalDeviceQueueFamilyProperties(m_vkPhysicalDevice,
295                                              &queueFamilyCount, NULL);
296 
297     std::vector<VkQueueFamilyProperties> vkQueueFamilyPropertiesList(
298         queueFamilyCount);
299     vkGetPhysicalDeviceQueueFamilyProperties(
300         m_vkPhysicalDevice, &queueFamilyCount,
301         vkQueueFamilyPropertiesList.data());
302 
303     for (size_t qfpIdx = 0; qfpIdx < vkQueueFamilyPropertiesList.size();
304          qfpIdx++)
305     {
306         VulkanQueueFamily *queueFamily = new VulkanQueueFamily(
307             uint32_t(qfpIdx), vkQueueFamilyPropertiesList[qfpIdx]);
308         m_queueFamilyList.add(*queueFamily);
309     }
310 
311     vkGetPhysicalDeviceMemoryProperties(m_vkPhysicalDevice,
312                                         &m_vkPhysicalDeviceMemoryProperties);
313 
314     for (uint32_t mhIdx = 0;
315          mhIdx < m_vkPhysicalDeviceMemoryProperties.memoryHeapCount; mhIdx++)
316     {
317         VulkanMemoryHeap *memoryHeap = new VulkanMemoryHeap(
318             mhIdx, m_vkPhysicalDeviceMemoryProperties.memoryHeaps[mhIdx].size,
319             (VulkanMemoryHeapFlag)m_vkPhysicalDeviceMemoryProperties
320                 .memoryHeaps[mhIdx]
321                 .flags);
322         m_memoryHeapList.add(*memoryHeap);
323     }
324 
325     for (uint32_t mtIdx = 0;
326          mtIdx < m_vkPhysicalDeviceMemoryProperties.memoryTypeCount; mtIdx++)
327     {
328         const VulkanMemoryHeap &memoryHeap = m_memoryHeapList
329             [m_vkPhysicalDeviceMemoryProperties.memoryTypes[mtIdx].heapIndex];
330         VulkanMemoryType *memoryType = new VulkanMemoryType(
331             mtIdx,
332             (VulkanMemoryTypeProperty)m_vkPhysicalDeviceMemoryProperties
333                 .memoryTypes[mtIdx]
334                 .propertyFlags,
335             memoryHeap);
336         m_memoryTypeList.add(*memoryType);
337     }
338 }
339 
~VulkanPhysicalDevice()340 VulkanPhysicalDevice::~VulkanPhysicalDevice()
341 {
342     for (size_t mtIdx = 0; mtIdx < m_memoryTypeList.size(); mtIdx++)
343     {
344         const VulkanMemoryType &memoryType = m_memoryTypeList[mtIdx];
345         delete &memoryType;
346     }
347 
348     for (size_t mhIdx = 0; mhIdx < m_memoryHeapList.size(); mhIdx++)
349     {
350         const VulkanMemoryHeap &memoryHeap = m_memoryHeapList[mhIdx];
351         delete &memoryHeap;
352     }
353 
354     for (size_t qfIdx = 0; qfIdx < m_queueFamilyList.size(); qfIdx++)
355     {
356         const VulkanQueueFamily &queueFamily = m_queueFamilyList[qfIdx];
357         delete &queueFamily;
358     }
359 }
360 
361 
getQueueFamilyList() const362 const VulkanQueueFamilyList &VulkanPhysicalDevice::getQueueFamilyList() const
363 {
364     return m_queueFamilyList;
365 }
366 
getMemoryHeapList() const367 const VulkanMemoryHeapList &VulkanPhysicalDevice::getMemoryHeapList() const
368 {
369     return m_memoryHeapList;
370 }
371 
getMemoryTypeList() const372 const VulkanMemoryTypeList &VulkanPhysicalDevice::getMemoryTypeList() const
373 {
374     return m_memoryTypeList;
375 }
376 
getUUID() const377 const uint8_t *VulkanPhysicalDevice::getUUID() const { return m_vkDeviceUUID; }
378 
getLUID() const379 const uint8_t *VulkanPhysicalDevice::getLUID() const { return m_vkDeviceLUID; }
380 
getNodeMask() const381 uint32_t VulkanPhysicalDevice::getNodeMask() const
382 {
383     return m_vkDeviceNodeMask;
384 }
385 
operator VkPhysicalDevice() const386 VulkanPhysicalDevice::operator VkPhysicalDevice() const
387 {
388     return m_vkPhysicalDevice;
389 }
390 
operator <(const VulkanQueueFamily & queueFamilyA,const VulkanQueueFamily & queueFamilyB)391 bool operator<(const VulkanQueueFamily &queueFamilyA,
392                const VulkanQueueFamily &queueFamilyB)
393 {
394     return (uint32_t)queueFamilyA < (uint32_t)queueFamilyB;
395 }
396 
397 /////////////////////////////////////
398 // VulkanMemoryHeap implementation //
399 /////////////////////////////////////
400 
VulkanMemoryHeap(const VulkanMemoryHeap & memoryHeap)401 VulkanMemoryHeap::VulkanMemoryHeap(const VulkanMemoryHeap &memoryHeap)
402     : m_memoryHeapIndex(memoryHeap.m_memoryHeapIndex),
403       m_size(memoryHeap.m_size), m_memoryHeapFlag(memoryHeap.m_memoryHeapFlag)
404 {}
405 
VulkanMemoryHeap(uint32_t memoryHeapIndex,uint64_t size,VulkanMemoryHeapFlag memoryHeapFlag)406 VulkanMemoryHeap::VulkanMemoryHeap(uint32_t memoryHeapIndex, uint64_t size,
407                                    VulkanMemoryHeapFlag memoryHeapFlag)
408     : m_memoryHeapIndex(memoryHeapIndex), m_size(size),
409       m_memoryHeapFlag(memoryHeapFlag)
410 {}
411 
~VulkanMemoryHeap()412 VulkanMemoryHeap::~VulkanMemoryHeap() {}
413 
getSize() const414 uint64_t VulkanMemoryHeap::getSize() const { return m_size; }
415 
416 
getMemoryHeapFlag() const417 VulkanMemoryHeapFlag VulkanMemoryHeap::getMemoryHeapFlag() const
418 {
419     return m_memoryHeapFlag;
420 }
421 
operator uint32_t() const422 VulkanMemoryHeap::operator uint32_t() const { return m_memoryHeapIndex; }
423 
424 /////////////////////////////////////
425 // VulkanMemoryType implementation //
426 /////////////////////////////////////
427 
VulkanMemoryType(const VulkanMemoryType & memoryType)428 VulkanMemoryType::VulkanMemoryType(const VulkanMemoryType &memoryType)
429     : m_memoryTypeIndex(memoryType.m_memoryTypeIndex),
430       m_memoryTypeProperty(memoryType.m_memoryTypeProperty),
431       m_memoryHeap(memoryType.m_memoryHeap)
432 {}
433 
VulkanMemoryType(uint32_t memoryTypeIndex,VulkanMemoryTypeProperty memoryTypeProperty,const VulkanMemoryHeap & memoryHeap)434 VulkanMemoryType::VulkanMemoryType(uint32_t memoryTypeIndex,
435                                    VulkanMemoryTypeProperty memoryTypeProperty,
436                                    const VulkanMemoryHeap &memoryHeap)
437     : m_memoryTypeIndex(memoryTypeIndex),
438       m_memoryTypeProperty(memoryTypeProperty), m_memoryHeap(memoryHeap)
439 {}
440 
~VulkanMemoryType()441 VulkanMemoryType::~VulkanMemoryType() {}
442 
getMemoryTypeProperty() const443 VulkanMemoryTypeProperty VulkanMemoryType::getMemoryTypeProperty() const
444 {
445     return m_memoryTypeProperty;
446 }
447 
getMemoryHeap() const448 const VulkanMemoryHeap &VulkanMemoryType::getMemoryHeap() const
449 {
450     return m_memoryHeap;
451 }
452 
operator uint32_t() const453 VulkanMemoryType::operator uint32_t() const { return m_memoryTypeIndex; }
454 
455 //////////////////////////////////////
456 // VulkanQueueFamily implementation //
457 //////////////////////////////////////
458 
VulkanQueueFamily(const VulkanQueueFamily & queueFamily)459 VulkanQueueFamily::VulkanQueueFamily(const VulkanQueueFamily &queueFamily)
460     : m_queueFamilyIndex(queueFamily.m_queueFamilyIndex),
461       m_vkQueueFamilyProperties(queueFamily.m_vkQueueFamilyProperties)
462 {}
463 
VulkanQueueFamily(uint32_t queueFamilyIndex,VkQueueFamilyProperties vkQueueFamilyProperties)464 VulkanQueueFamily::VulkanQueueFamily(
465     uint32_t queueFamilyIndex, VkQueueFamilyProperties vkQueueFamilyProperties)
466     : m_queueFamilyIndex(queueFamilyIndex),
467       m_vkQueueFamilyProperties(vkQueueFamilyProperties)
468 {}
469 
~VulkanQueueFamily()470 VulkanQueueFamily::~VulkanQueueFamily() {}
471 
getQueueFlags() const472 uint32_t VulkanQueueFamily::getQueueFlags() const
473 {
474     return m_vkQueueFamilyProperties.queueFlags
475         & (uint32_t)VULKAN_QUEUE_FLAG_MASK_ALL;
476 }
477 
getQueueCount() const478 uint32_t VulkanQueueFamily::getQueueCount() const
479 {
480     return m_vkQueueFamilyProperties.queueCount;
481 }
482 
operator uint32_t() const483 VulkanQueueFamily::operator uint32_t() const { return m_queueFamilyIndex; }
484 
485 /////////////////////////////////
486 // VulkanDevice implementation //
487 /////////////////////////////////
488 
VulkanDevice(const VulkanDevice & device)489 VulkanDevice::VulkanDevice(const VulkanDevice &device)
490     : m_physicalDevice(device.m_physicalDevice), m_vkDevice(device.m_vkDevice)
491 {}
492 
VulkanDevice(const VulkanPhysicalDevice & physicalDevice,const VulkanQueueFamilyToQueueCountMap & queueFamilyToQueueCountMap)493 VulkanDevice::VulkanDevice(
494     const VulkanPhysicalDevice &physicalDevice,
495     const VulkanQueueFamilyToQueueCountMap &queueFamilyToQueueCountMap)
496     : m_physicalDevice(physicalDevice), m_vkDevice(NULL)
497 {
498     uint32_t maxQueueCount = 0;
499     for (uint32_t qfIdx = 0;
500          qfIdx < (uint32_t)physicalDevice.getQueueFamilyList().size(); qfIdx++)
501     {
502         maxQueueCount =
503             std::max(maxQueueCount, queueFamilyToQueueCountMap[qfIdx]);
504     }
505 
506     std::vector<VkDeviceQueueCreateInfo> vkDeviceQueueCreateInfoList;
507     std::vector<float> queuePriorities(maxQueueCount);
508     for (uint32_t qfIdx = 0;
509          qfIdx < (uint32_t)physicalDevice.getQueueFamilyList().size(); qfIdx++)
510     {
511         if (queueFamilyToQueueCountMap[qfIdx])
512         {
513             VkDeviceQueueCreateInfo vkDeviceQueueCreateInfo = {};
514             vkDeviceQueueCreateInfo.sType =
515                 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
516             vkDeviceQueueCreateInfo.pNext = NULL;
517             vkDeviceQueueCreateInfo.flags = 0;
518             vkDeviceQueueCreateInfo.queueFamilyIndex = qfIdx;
519             vkDeviceQueueCreateInfo.queueCount =
520                 queueFamilyToQueueCountMap[qfIdx];
521             vkDeviceQueueCreateInfo.pQueuePriorities = queuePriorities.data();
522 
523             vkDeviceQueueCreateInfoList.push_back(vkDeviceQueueCreateInfo);
524         }
525     }
526 
527     std::vector<const char *> enabledExtensionNameList;
528     enabledExtensionNameList.push_back(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME);
529     enabledExtensionNameList.push_back(
530         VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME);
531 #if defined(_WIN32) || defined(_WIN64)
532     enabledExtensionNameList.push_back(
533         VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME);
534     enabledExtensionNameList.push_back(
535         VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME);
536 #else
537     enabledExtensionNameList.push_back(
538         VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME);
539     enabledExtensionNameList.push_back(
540         VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME);
541 #endif
542 
543 
544     VkDeviceCreateInfo vkDeviceCreateInfo = {};
545     vkDeviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
546     vkDeviceCreateInfo.pNext = NULL;
547     vkDeviceCreateInfo.flags = 0;
548     vkDeviceCreateInfo.queueCreateInfoCount =
549         (uint32_t)vkDeviceQueueCreateInfoList.size();
550     vkDeviceCreateInfo.pQueueCreateInfos = vkDeviceQueueCreateInfoList.data();
551     vkDeviceCreateInfo.enabledLayerCount = 0;
552     vkDeviceCreateInfo.ppEnabledLayerNames = NULL;
553     vkDeviceCreateInfo.enabledExtensionCount =
554         (uint32_t)enabledExtensionNameList.size();
555     vkDeviceCreateInfo.ppEnabledExtensionNames =
556         enabledExtensionNameList.data();
557     vkDeviceCreateInfo.pEnabledFeatures = NULL;
558 
559     vkCreateDevice(physicalDevice, &vkDeviceCreateInfo, NULL, &m_vkDevice);
560 
561     for (uint32_t qfIdx = 0;
562          qfIdx < (uint32_t)m_physicalDevice.getQueueFamilyList().size();
563          qfIdx++)
564     {
565         VulkanQueueList *queueList = new VulkanQueueList();
566         m_queueFamilyIndexToQueueListMap.insert(qfIdx, *queueList);
567         for (uint32_t qIdx = 0; qIdx < queueFamilyToQueueCountMap[qfIdx];
568              qIdx++)
569         {
570             VkQueue vkQueue;
571             vkGetDeviceQueue(m_vkDevice, qfIdx, qIdx, &vkQueue);
572             VulkanQueue *queue = new VulkanQueue(vkQueue);
573             m_queueFamilyIndexToQueueListMap[qfIdx].add(*queue);
574         }
575     }
576 }
577 
~VulkanDevice()578 VulkanDevice::~VulkanDevice()
579 {
580     for (uint32_t qfIdx = 0;
581          qfIdx < (uint32_t)m_physicalDevice.getQueueFamilyList().size();
582          qfIdx++)
583     {
584         for (size_t qIdx = 0;
585              qIdx < m_queueFamilyIndexToQueueListMap[qfIdx].size(); qIdx++)
586         {
587             VulkanQueue &queue = m_queueFamilyIndexToQueueListMap[qfIdx][qIdx];
588             delete &queue;
589         }
590         VulkanQueueList &queueList = m_queueFamilyIndexToQueueListMap[qfIdx];
591         delete &queueList;
592     }
593     vkDestroyDevice(m_vkDevice, NULL);
594 }
595 
getPhysicalDevice() const596 const VulkanPhysicalDevice &VulkanDevice::getPhysicalDevice() const
597 {
598     return m_physicalDevice;
599 }
600 
getQueue(const VulkanQueueFamily & queueFamily,uint32_t queueIndex)601 VulkanQueue &VulkanDevice::getQueue(const VulkanQueueFamily &queueFamily,
602                                     uint32_t queueIndex)
603 {
604     return m_queueFamilyIndexToQueueListMap[queueFamily][queueIndex];
605 }
606 
operator VkDevice() const607 VulkanDevice::operator VkDevice() const { return m_vkDevice; }
608 
609 ////////////////////////////////
610 // VulkanFence implementation //
611 ////////////////////////////////
612 
VulkanFence(const VulkanDevice & vkDevice)613 VulkanFence::VulkanFence(const VulkanDevice &vkDevice)
614 {
615 
616     device = vkDevice;
617 
618     VkFenceCreateInfo fenceInfo{};
619     fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
620     fenceInfo.pNext = nullptr;
621     fenceInfo.flags = 0;
622 
623     VkResult vkStatus = vkCreateFence(device, &fenceInfo, nullptr, &fence);
624 
625     if (vkStatus != VK_SUCCESS)
626     {
627         throw std::runtime_error("Error: Failed create fence.");
628     }
629 }
630 
~VulkanFence()631 VulkanFence::~VulkanFence() { vkDestroyFence(device, fence, nullptr); }
632 
reset()633 void VulkanFence::reset() { vkResetFences(device, 1, &fence); }
634 
wait()635 void VulkanFence::wait()
636 {
637     vkWaitForFences(device, 1, &fence, VK_TRUE, UINT64_MAX);
638 }
639 
640 ////////////////////////////////
641 // VulkanQueue implementation //
642 ////////////////////////////////
643 
VulkanQueue(const VulkanQueue & queue)644 VulkanQueue::VulkanQueue(const VulkanQueue &queue): m_vkQueue(queue.m_vkQueue)
645 {}
646 
VulkanQueue(VkQueue vkQueue)647 VulkanQueue::VulkanQueue(VkQueue vkQueue): m_vkQueue(vkQueue) {}
648 
~VulkanQueue()649 VulkanQueue::~VulkanQueue() {}
650 
submit(const VulkanCommandBuffer & commandBuffer,const std::shared_ptr<VulkanFence> & vkFence)651 void VulkanQueue::submit(const VulkanCommandBuffer &commandBuffer,
652                          const std::shared_ptr<VulkanFence> &vkFence)
653 {
654     VulkanCommandBufferList commandBufferList;
655     commandBufferList.add(commandBuffer);
656 
657     VkSubmitInfo vkSubmitInfo = {};
658     vkSubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
659     vkSubmitInfo.pNext = NULL;
660     vkSubmitInfo.waitSemaphoreCount = (uint32_t)0;
661     vkSubmitInfo.commandBufferCount = (uint32_t)commandBufferList.size();
662     vkSubmitInfo.pCommandBuffers = commandBufferList();
663 
664     vkQueueSubmit(m_vkQueue, 1, &vkSubmitInfo, vkFence->fence);
665 }
666 
submit(const VulkanSemaphoreList & waitSemaphoreList,const VulkanCommandBufferList & commandBufferList,const VulkanSemaphoreList & signalSemaphoreList)667 void VulkanQueue::submit(const VulkanSemaphoreList &waitSemaphoreList,
668                          const VulkanCommandBufferList &commandBufferList,
669                          const VulkanSemaphoreList &signalSemaphoreList)
670 {
671     std::vector<VkPipelineStageFlags> vkPipelineStageFlagsList(
672         waitSemaphoreList.size(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
673 
674     VkSubmitInfo vkSubmitInfo = {};
675     vkSubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
676     vkSubmitInfo.pNext = NULL;
677     vkSubmitInfo.waitSemaphoreCount = (uint32_t)waitSemaphoreList.size();
678     vkSubmitInfo.pWaitSemaphores = waitSemaphoreList();
679     vkSubmitInfo.pWaitDstStageMask = vkPipelineStageFlagsList.data();
680     vkSubmitInfo.commandBufferCount = (uint32_t)commandBufferList.size();
681     vkSubmitInfo.pCommandBuffers = commandBufferList();
682     vkSubmitInfo.signalSemaphoreCount = (uint32_t)signalSemaphoreList.size();
683     vkSubmitInfo.pSignalSemaphores = signalSemaphoreList();
684 
685     vkQueueSubmit(m_vkQueue, 1, &vkSubmitInfo, NULL);
686 }
687 
submit(const VulkanSemaphore & waitSemaphore,const VulkanCommandBuffer & commandBuffer,const VulkanSemaphore & signalSemaphore)688 void VulkanQueue::submit(const VulkanSemaphore &waitSemaphore,
689                          const VulkanCommandBuffer &commandBuffer,
690                          const VulkanSemaphore &signalSemaphore)
691 {
692     VulkanSemaphoreList waitSemaphoreList;
693     VulkanCommandBufferList commandBufferList;
694     VulkanSemaphoreList signalSemaphoreList;
695 
696     waitSemaphoreList.add(waitSemaphore);
697     commandBufferList.add(commandBuffer);
698     signalSemaphoreList.add(signalSemaphore);
699 
700     submit(waitSemaphoreList, commandBufferList, signalSemaphoreList);
701 }
702 
submit(const VulkanCommandBuffer & commandBuffer,const VulkanSemaphore & signalSemaphore)703 void VulkanQueue::submit(const VulkanCommandBuffer &commandBuffer,
704                          const VulkanSemaphore &signalSemaphore)
705 {
706     VulkanSemaphoreList waitSemaphoreList;
707     VulkanCommandBufferList commandBufferList;
708     VulkanSemaphoreList signalSemaphoreList;
709 
710     commandBufferList.add(commandBuffer);
711     signalSemaphoreList.add(signalSemaphore);
712 
713     submit(waitSemaphoreList, commandBufferList, signalSemaphoreList);
714 }
715 
submit(const VulkanCommandBuffer & commandBuffer)716 void VulkanQueue::submit(const VulkanCommandBuffer &commandBuffer)
717 {
718     VulkanSemaphoreList waitSemaphoreList;
719     VulkanCommandBufferList commandBufferList;
720     VulkanSemaphoreList signalSemaphoreList;
721 
722     commandBufferList.add(commandBuffer);
723 
724     submit(waitSemaphoreList, commandBufferList, signalSemaphoreList);
725 }
726 
waitIdle()727 void VulkanQueue::waitIdle() { vkQueueWaitIdle(m_vkQueue); }
728 
operator VkQueue() const729 VulkanQueue::operator VkQueue() const { return m_vkQueue; }
730 
731 /////////////////////////////////////////////////////
732 // VulkanDescriptorSetLayoutBinding implementation //
733 /////////////////////////////////////////////////////
734 
VulkanDescriptorSetLayoutBinding(const VulkanDescriptorSetLayoutBinding & descriptorSetLayoutBinding)735 VulkanDescriptorSetLayoutBinding::VulkanDescriptorSetLayoutBinding(
736     const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding)
737     : m_vkDescriptorSetLayoutBinding(
738         descriptorSetLayoutBinding.m_vkDescriptorSetLayoutBinding)
739 {}
740 
VulkanDescriptorSetLayoutBinding(uint32_t binding,VulkanDescriptorType descriptorType,uint32_t descriptorCount,VulkanShaderStage shaderStage)741 VulkanDescriptorSetLayoutBinding::VulkanDescriptorSetLayoutBinding(
742     uint32_t binding, VulkanDescriptorType descriptorType,
743     uint32_t descriptorCount, VulkanShaderStage shaderStage)
744 {
745     m_vkDescriptorSetLayoutBinding.binding = binding;
746     m_vkDescriptorSetLayoutBinding.descriptorType =
747         (VkDescriptorType)descriptorType;
748     m_vkDescriptorSetLayoutBinding.descriptorCount = descriptorCount;
749     m_vkDescriptorSetLayoutBinding.stageFlags =
750         (VkShaderStageFlags)(VkShaderStageFlagBits)shaderStage;
751     m_vkDescriptorSetLayoutBinding.pImmutableSamplers = NULL;
752 }
753 
~VulkanDescriptorSetLayoutBinding()754 VulkanDescriptorSetLayoutBinding::~VulkanDescriptorSetLayoutBinding() {}
755 
operator VkDescriptorSetLayoutBinding() const756 VulkanDescriptorSetLayoutBinding::operator VkDescriptorSetLayoutBinding() const
757 {
758     return m_vkDescriptorSetLayoutBinding;
759 }
760 
761 //////////////////////////////////////////////
762 // VulkanDescriptorSetLayout implementation //
763 //////////////////////////////////////////////
764 
VulkanDescriptorSetLayout(const VulkanDescriptorSetLayout & descriptorSetLayout)765 VulkanDescriptorSetLayout::VulkanDescriptorSetLayout(
766     const VulkanDescriptorSetLayout &descriptorSetLayout)
767     : m_device(descriptorSetLayout.m_device),
768       m_vkDescriptorSetLayout(descriptorSetLayout.m_vkDescriptorSetLayout)
769 {}
770 
VulkanDescriptorSetLayoutCommon(const VulkanDescriptorSetLayoutBindingList & descriptorSetLayoutBindingList)771 void VulkanDescriptorSetLayout::VulkanDescriptorSetLayoutCommon(
772     const VulkanDescriptorSetLayoutBindingList &descriptorSetLayoutBindingList)
773 {
774     VkDescriptorSetLayoutCreateInfo vkDescriptorSetLayoutCreateInfo = {};
775     vkDescriptorSetLayoutCreateInfo.sType =
776         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
777     vkDescriptorSetLayoutCreateInfo.pNext = NULL;
778     vkDescriptorSetLayoutCreateInfo.flags = 0;
779     vkDescriptorSetLayoutCreateInfo.bindingCount =
780         (uint32_t)descriptorSetLayoutBindingList.size();
781     vkDescriptorSetLayoutCreateInfo.pBindings =
782         descriptorSetLayoutBindingList();
783 
784     vkCreateDescriptorSetLayout(m_device, &vkDescriptorSetLayoutCreateInfo,
785                                 NULL, &m_vkDescriptorSetLayout);
786 }
787 
VulkanDescriptorSetLayout(const VulkanDevice & device,const VulkanDescriptorSetLayoutBinding & descriptorSetLayoutBinding)788 VulkanDescriptorSetLayout::VulkanDescriptorSetLayout(
789     const VulkanDevice &device,
790     const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding)
791     : m_device(device), m_vkDescriptorSetLayout(VK_NULL_HANDLE)
792 {
793     VulkanDescriptorSetLayoutBindingList descriptorSetLayoutBindingList;
794     descriptorSetLayoutBindingList.add(descriptorSetLayoutBinding);
795 
796     VulkanDescriptorSetLayoutCommon(descriptorSetLayoutBindingList);
797 }
798 
VulkanDescriptorSetLayout(const VulkanDevice & device,const VulkanDescriptorSetLayoutBinding & descriptorSetLayoutBinding0,const VulkanDescriptorSetLayoutBinding & descriptorSetLayoutBinding1)799 VulkanDescriptorSetLayout::VulkanDescriptorSetLayout(
800     const VulkanDevice &device,
801     const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding0,
802     const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding1)
803     : m_device(device), m_vkDescriptorSetLayout(VK_NULL_HANDLE)
804 {
805     VulkanDescriptorSetLayoutBindingList descriptorSetLayoutBindingList;
806     descriptorSetLayoutBindingList.add(descriptorSetLayoutBinding0);
807     descriptorSetLayoutBindingList.add(descriptorSetLayoutBinding1);
808 
809     VulkanDescriptorSetLayoutCommon(descriptorSetLayoutBindingList);
810 }
811 
VulkanDescriptorSetLayout(const VulkanDevice & device,const VulkanDescriptorSetLayoutBindingList & descriptorSetLayoutBindingList)812 VulkanDescriptorSetLayout::VulkanDescriptorSetLayout(
813     const VulkanDevice &device,
814     const VulkanDescriptorSetLayoutBindingList &descriptorSetLayoutBindingList)
815     : m_device(device), m_vkDescriptorSetLayout(VK_NULL_HANDLE)
816 {
817     VulkanDescriptorSetLayoutCommon(descriptorSetLayoutBindingList);
818 }
819 
~VulkanDescriptorSetLayout()820 VulkanDescriptorSetLayout::~VulkanDescriptorSetLayout()
821 {
822     if (m_vkDescriptorSetLayout != VK_NULL_HANDLE)
823     {
824         vkDestroyDescriptorSetLayout(m_device, m_vkDescriptorSetLayout, NULL);
825     }
826 }
827 
operator VkDescriptorSetLayout() const828 VulkanDescriptorSetLayout::operator VkDescriptorSetLayout() const
829 {
830     return m_vkDescriptorSetLayout;
831 }
832 
833 /////////////////////////////////////////
834 // VulkanPipelineLayout implementation //
835 /////////////////////////////////////////
836 
VulkanPipelineLayout(const VulkanPipelineLayout & pipelineLayout)837 VulkanPipelineLayout::VulkanPipelineLayout(
838     const VulkanPipelineLayout &pipelineLayout)
839     : m_device(pipelineLayout.m_device),
840       m_vkPipelineLayout(pipelineLayout.m_vkPipelineLayout)
841 {}
842 
VulkanPipelineLayoutCommon(const VulkanDescriptorSetLayoutList & descriptorSetLayoutList)843 void VulkanPipelineLayout::VulkanPipelineLayoutCommon(
844     const VulkanDescriptorSetLayoutList &descriptorSetLayoutList)
845 {
846     VkPipelineLayoutCreateInfo vkPipelineLayoutCreateInfo = {};
847     vkPipelineLayoutCreateInfo.sType =
848         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
849     vkPipelineLayoutCreateInfo.pNext = NULL;
850     vkPipelineLayoutCreateInfo.flags = 0;
851     vkPipelineLayoutCreateInfo.setLayoutCount =
852         (uint32_t)descriptorSetLayoutList.size();
853     vkPipelineLayoutCreateInfo.pSetLayouts = descriptorSetLayoutList();
854     vkPipelineLayoutCreateInfo.pushConstantRangeCount = 0;
855     vkPipelineLayoutCreateInfo.pPushConstantRanges = NULL;
856 
857     vkCreatePipelineLayout(m_device, &vkPipelineLayoutCreateInfo, NULL,
858                            &m_vkPipelineLayout);
859 }
860 
VulkanPipelineLayout(const VulkanDevice & device,const VulkanDescriptorSetLayout & descriptorSetLayout)861 VulkanPipelineLayout::VulkanPipelineLayout(
862     const VulkanDevice &device,
863     const VulkanDescriptorSetLayout &descriptorSetLayout)
864     : m_device(device), m_vkPipelineLayout(VK_NULL_HANDLE)
865 {
866     VulkanDescriptorSetLayoutList descriptorSetLayoutList;
867     descriptorSetLayoutList.add(descriptorSetLayout);
868 
869     VulkanPipelineLayoutCommon(descriptorSetLayoutList);
870 }
871 
VulkanPipelineLayout(const VulkanDevice & device,const VulkanDescriptorSetLayoutList & descriptorSetLayoutList)872 VulkanPipelineLayout::VulkanPipelineLayout(
873     const VulkanDevice &device,
874     const VulkanDescriptorSetLayoutList &descriptorSetLayoutList)
875     : m_device(device), m_vkPipelineLayout(VK_NULL_HANDLE)
876 {
877     VulkanPipelineLayoutCommon(descriptorSetLayoutList);
878 }
879 
~VulkanPipelineLayout()880 VulkanPipelineLayout::~VulkanPipelineLayout()
881 {
882     vkDestroyPipelineLayout(m_device, m_vkPipelineLayout, NULL);
883 }
884 
operator VkPipelineLayout() const885 VulkanPipelineLayout::operator VkPipelineLayout() const
886 {
887     return m_vkPipelineLayout;
888 }
889 
890 ///////////////////////////////////////
891 // VulkanShaderModule implementation //
892 ///////////////////////////////////////
893 
VulkanShaderModule(const VulkanShaderModule & shaderModule)894 VulkanShaderModule::VulkanShaderModule(const VulkanShaderModule &shaderModule)
895     : m_device(shaderModule.m_device),
896       m_vkShaderModule(shaderModule.m_vkShaderModule)
897 {}
898 
VulkanShaderModule(const VulkanDevice & device,const std::vector<char> & code)899 VulkanShaderModule::VulkanShaderModule(const VulkanDevice &device,
900                                        const std::vector<char> &code)
901     : m_device(device)
902 {
903 
904     VkShaderModuleCreateInfo vkShaderModuleCreateInfo = {};
905     vkShaderModuleCreateInfo.sType =
906         VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
907     vkShaderModuleCreateInfo.pNext = NULL;
908     vkShaderModuleCreateInfo.flags = 0;
909     vkShaderModuleCreateInfo.codeSize = code.size();
910     vkShaderModuleCreateInfo.pCode =
911         reinterpret_cast<const uint32_t *>(code.data());
912 
913     vkCreateShaderModule(m_device, &vkShaderModuleCreateInfo, NULL,
914                          &m_vkShaderModule);
915 }
916 
~VulkanShaderModule()917 VulkanShaderModule::~VulkanShaderModule()
918 {
919     vkDestroyShaderModule(m_device, m_vkShaderModule, NULL);
920 }
921 
operator VkShaderModule() const922 VulkanShaderModule::operator VkShaderModule() const { return m_vkShaderModule; }
923 
924 ///////////////////////////////////
925 // VulkanPipeline implementation //
926 ///////////////////////////////////
927 
VulkanPipeline(const VulkanPipeline & pipeline)928 VulkanPipeline::VulkanPipeline(const VulkanPipeline &pipeline)
929     : m_device(pipeline.m_device), m_vkPipeline(pipeline.m_vkPipeline)
930 {}
931 
VulkanPipeline(const VulkanDevice & device)932 VulkanPipeline::VulkanPipeline(const VulkanDevice &device)
933     : m_device(device), m_vkPipeline(VK_NULL_HANDLE)
934 {}
935 
~VulkanPipeline()936 VulkanPipeline::~VulkanPipeline()
937 {
938     vkDestroyPipeline(m_device, m_vkPipeline, NULL);
939 }
940 
operator VkPipeline() const941 VulkanPipeline::operator VkPipeline() const { return m_vkPipeline; }
942 
943 //////////////////////////////////////////
944 // VulkanComputePipeline implementation //
945 //////////////////////////////////////////
946 
VulkanComputePipeline(const VulkanComputePipeline & computePipeline)947 VulkanComputePipeline::VulkanComputePipeline(
948     const VulkanComputePipeline &computePipeline)
949     : VulkanPipeline(computePipeline)
950 {}
951 
VulkanComputePipeline(const VulkanDevice & device,const VulkanPipelineLayout & pipelineLayout,const VulkanShaderModule & shaderModule,const std::string & entryFuncName)952 VulkanComputePipeline::VulkanComputePipeline(
953     const VulkanDevice &device, const VulkanPipelineLayout &pipelineLayout,
954     const VulkanShaderModule &shaderModule, const std::string &entryFuncName)
955     : VulkanPipeline(device)
956 {
957     VkPipelineShaderStageCreateInfo vkPipelineShaderStageCreateInfo = {};
958     vkPipelineShaderStageCreateInfo.sType =
959         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
960     vkPipelineShaderStageCreateInfo.pNext = NULL;
961     vkPipelineShaderStageCreateInfo.flags = 0;
962     vkPipelineShaderStageCreateInfo.stage = VK_SHADER_STAGE_COMPUTE_BIT;
963     vkPipelineShaderStageCreateInfo.module = shaderModule;
964     vkPipelineShaderStageCreateInfo.pName = entryFuncName.c_str();
965     vkPipelineShaderStageCreateInfo.pSpecializationInfo = NULL;
966 
967     VkComputePipelineCreateInfo vkComputePipelineCreateInfo = {};
968     vkComputePipelineCreateInfo.sType =
969         VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
970     vkComputePipelineCreateInfo.pNext = NULL;
971     vkComputePipelineCreateInfo.flags = 0;
972     vkComputePipelineCreateInfo.stage = vkPipelineShaderStageCreateInfo;
973     vkComputePipelineCreateInfo.layout = pipelineLayout;
974     vkComputePipelineCreateInfo.basePipelineHandle = VK_NULL_HANDLE;
975     vkComputePipelineCreateInfo.basePipelineIndex = 0;
976 
977     vkCreateComputePipelines(device, VK_NULL_HANDLE, 1,
978                              &vkComputePipelineCreateInfo, NULL, &m_vkPipeline);
979 }
980 
~VulkanComputePipeline()981 VulkanComputePipeline::~VulkanComputePipeline() {}
982 
getPipelineBindPoint() const983 VulkanPipelineBindPoint VulkanComputePipeline::getPipelineBindPoint() const
984 {
985     return VULKAN_PIPELINE_BIND_POINT_COMPUTE;
986 }
987 
988 /////////////////////////////////////////
989 // VulkanDescriptorPool implementation //
990 /////////////////////////////////////////
991 
VulkanDescriptorPool(const VulkanDescriptorPool & descriptorPool)992 VulkanDescriptorPool::VulkanDescriptorPool(
993     const VulkanDescriptorPool &descriptorPool)
994     : m_device(descriptorPool.m_device),
995       m_vkDescriptorPool(descriptorPool.m_vkDescriptorPool)
996 {}
997 
VulkanDescriptorPoolCommon(const VulkanDescriptorSetLayoutBindingList & descriptorSetLayoutBindingList)998 void VulkanDescriptorPool::VulkanDescriptorPoolCommon(
999     const VulkanDescriptorSetLayoutBindingList &descriptorSetLayoutBindingList)
1000 {
1001     if (descriptorSetLayoutBindingList.size())
1002     {
1003         std::map<VkDescriptorType, uint32_t>
1004             vkDescriptorTypeToDescriptorCountMap;
1005 
1006         for (size_t dslbIdx = 0;
1007              dslbIdx < descriptorSetLayoutBindingList.size(); dslbIdx++)
1008         {
1009             VkDescriptorSetLayoutBinding vkDescriptorSetLayoutBinding =
1010                 descriptorSetLayoutBindingList[dslbIdx];
1011             if (vkDescriptorTypeToDescriptorCountMap.find(
1012                     vkDescriptorSetLayoutBinding.descriptorType)
1013                 == vkDescriptorTypeToDescriptorCountMap.end())
1014             {
1015                 vkDescriptorTypeToDescriptorCountMap
1016                     [vkDescriptorSetLayoutBinding.descriptorType] =
1017                         vkDescriptorSetLayoutBinding.descriptorCount;
1018             }
1019             else
1020             {
1021                 vkDescriptorTypeToDescriptorCountMap
1022                     [vkDescriptorSetLayoutBinding.descriptorType] +=
1023                     vkDescriptorSetLayoutBinding.descriptorCount;
1024             }
1025         }
1026 
1027         std::vector<VkDescriptorPoolSize> vkDescriptorPoolSizeList;
1028         std::map<VkDescriptorType, uint32_t>::iterator dtdcIt;
1029         for (dtdcIt = vkDescriptorTypeToDescriptorCountMap.begin();
1030              dtdcIt != vkDescriptorTypeToDescriptorCountMap.end(); ++dtdcIt)
1031         {
1032             VkDescriptorPoolSize vkDescriptorPoolSize = {};
1033             vkDescriptorPoolSize.type = dtdcIt->first;
1034             vkDescriptorPoolSize.descriptorCount = dtdcIt->second;
1035 
1036             vkDescriptorPoolSizeList.push_back(vkDescriptorPoolSize);
1037         }
1038 
1039         VkDescriptorPoolCreateInfo vkDescriptorPoolCreateInfo = {};
1040         vkDescriptorPoolCreateInfo.sType =
1041             VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
1042         vkDescriptorPoolCreateInfo.pNext = NULL;
1043         vkDescriptorPoolCreateInfo.flags =
1044             VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
1045         vkDescriptorPoolCreateInfo.maxSets = 1;
1046         vkDescriptorPoolCreateInfo.poolSizeCount =
1047             (uint32_t)vkDescriptorPoolSizeList.size();
1048         vkDescriptorPoolCreateInfo.pPoolSizes = vkDescriptorPoolSizeList.data();
1049 
1050         vkCreateDescriptorPool(m_device, &vkDescriptorPoolCreateInfo, NULL,
1051                                &m_vkDescriptorPool);
1052     }
1053 }
1054 
VulkanDescriptorPool(const VulkanDevice & device,const VulkanDescriptorSetLayoutBinding & descriptorSetLayoutBinding)1055 VulkanDescriptorPool::VulkanDescriptorPool(
1056     const VulkanDevice &device,
1057     const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding)
1058     : m_device(device), m_vkDescriptorPool(VK_NULL_HANDLE)
1059 {
1060     VulkanDescriptorSetLayoutBindingList descriptorSetLayoutBindingList;
1061     descriptorSetLayoutBindingList.add(descriptorSetLayoutBinding);
1062 
1063     VulkanDescriptorPoolCommon(descriptorSetLayoutBindingList);
1064 }
1065 
VulkanDescriptorPool(const VulkanDevice & device,const VulkanDescriptorSetLayoutBinding & descriptorSetLayoutBinding0,const VulkanDescriptorSetLayoutBinding & descriptorSetLayoutBinding1)1066 VulkanDescriptorPool::VulkanDescriptorPool(
1067     const VulkanDevice &device,
1068     const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding0,
1069     const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding1)
1070     : m_device(device), m_vkDescriptorPool(VK_NULL_HANDLE)
1071 {
1072     VulkanDescriptorSetLayoutBindingList descriptorSetLayoutBindingList;
1073     descriptorSetLayoutBindingList.add(descriptorSetLayoutBinding0);
1074     descriptorSetLayoutBindingList.add(descriptorSetLayoutBinding1);
1075 
1076     VulkanDescriptorPoolCommon(descriptorSetLayoutBindingList);
1077 }
1078 
VulkanDescriptorPool(const VulkanDevice & device,const VulkanDescriptorSetLayoutBindingList & descriptorSetLayoutBindingList)1079 VulkanDescriptorPool::VulkanDescriptorPool(
1080     const VulkanDevice &device,
1081     const VulkanDescriptorSetLayoutBindingList &descriptorSetLayoutBindingList)
1082     : m_device(device), m_vkDescriptorPool(VK_NULL_HANDLE)
1083 {
1084     VulkanDescriptorPoolCommon(descriptorSetLayoutBindingList);
1085 }
1086 
~VulkanDescriptorPool()1087 VulkanDescriptorPool::~VulkanDescriptorPool()
1088 {
1089     if (m_vkDescriptorPool != VK_NULL_HANDLE)
1090     {
1091         vkDestroyDescriptorPool(m_device, m_vkDescriptorPool, NULL);
1092     }
1093 }
1094 
operator VkDescriptorPool() const1095 VulkanDescriptorPool::operator VkDescriptorPool() const
1096 {
1097     return m_vkDescriptorPool;
1098 }
1099 
1100 ////////////////////////////////////////
1101 // VulkanDescriptorSet implementation //
1102 ////////////////////////////////////////
1103 
VulkanDescriptorSet(const VulkanDescriptorSet & descriptorSet)1104 VulkanDescriptorSet::VulkanDescriptorSet(
1105     const VulkanDescriptorSet &descriptorSet)
1106     : m_device(descriptorSet.m_device),
1107       m_descriptorPool(descriptorSet.m_descriptorPool),
1108       m_vkDescriptorSet(descriptorSet.m_vkDescriptorSet)
1109 {}
1110 
VulkanDescriptorSet(const VulkanDevice & device,const VulkanDescriptorPool & descriptorPool,const VulkanDescriptorSetLayout & descriptorSetLayout)1111 VulkanDescriptorSet::VulkanDescriptorSet(
1112     const VulkanDevice &device, const VulkanDescriptorPool &descriptorPool,
1113     const VulkanDescriptorSetLayout &descriptorSetLayout)
1114     : m_device(device), m_descriptorPool(descriptorPool),
1115       m_vkDescriptorSet(VK_NULL_HANDLE)
1116 {
1117     VkDescriptorSetLayout vkDescriptorSetLayout = descriptorSetLayout;
1118 
1119     if ((VkDescriptorPool)m_descriptorPool)
1120     {
1121         VkDescriptorSetAllocateInfo vkDescriptorSetAllocateInfo = {};
1122         vkDescriptorSetAllocateInfo.sType =
1123             VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
1124         vkDescriptorSetAllocateInfo.pNext = NULL;
1125         vkDescriptorSetAllocateInfo.descriptorPool = descriptorPool;
1126         vkDescriptorSetAllocateInfo.descriptorSetCount = 1;
1127         vkDescriptorSetAllocateInfo.pSetLayouts = &vkDescriptorSetLayout;
1128 
1129         vkAllocateDescriptorSets(m_device, &vkDescriptorSetAllocateInfo,
1130                                  &m_vkDescriptorSet);
1131     }
1132 }
1133 
~VulkanDescriptorSet()1134 VulkanDescriptorSet::~VulkanDescriptorSet()
1135 {
1136     if ((VkDescriptorPool)m_descriptorPool)
1137     {
1138         vkFreeDescriptorSets(m_device, m_descriptorPool, 1, &m_vkDescriptorSet);
1139     }
1140 }
1141 
update(uint32_t binding,const VulkanBuffer & buffer)1142 void VulkanDescriptorSet::update(uint32_t binding, const VulkanBuffer &buffer)
1143 {
1144     VkDescriptorBufferInfo vkDescriptorBufferInfo = {};
1145     vkDescriptorBufferInfo.buffer = buffer;
1146     vkDescriptorBufferInfo.offset = 0;
1147     vkDescriptorBufferInfo.range = VK_WHOLE_SIZE;
1148 
1149     VkWriteDescriptorSet vkWriteDescriptorSet = {};
1150     vkWriteDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1151     vkWriteDescriptorSet.pNext = NULL;
1152     vkWriteDescriptorSet.dstSet = m_vkDescriptorSet;
1153     vkWriteDescriptorSet.dstBinding = binding;
1154     vkWriteDescriptorSet.dstArrayElement = 0;
1155     vkWriteDescriptorSet.descriptorCount = 1;
1156     vkWriteDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1157     vkWriteDescriptorSet.pImageInfo = NULL;
1158     vkWriteDescriptorSet.pBufferInfo = &vkDescriptorBufferInfo;
1159     vkWriteDescriptorSet.pTexelBufferView = NULL;
1160 
1161     vkUpdateDescriptorSets(m_device, 1, &vkWriteDescriptorSet, 0, NULL);
1162 }
1163 
updateArray(uint32_t binding,unsigned numBuffers,const VulkanBufferList & buffers)1164 void VulkanDescriptorSet::updateArray(uint32_t binding, unsigned numBuffers,
1165                                       const VulkanBufferList &buffers)
1166 {
1167     VkDescriptorBufferInfo *vkDescriptorBufferInfo =
1168         (VkDescriptorBufferInfo *)calloc(numBuffers,
1169                                          sizeof(VkDescriptorBufferInfo));
1170     for (unsigned i = 0; i < numBuffers; i++)
1171     {
1172         vkDescriptorBufferInfo[i].buffer = buffers[i];
1173         vkDescriptorBufferInfo[i].offset = 0;
1174         vkDescriptorBufferInfo[i].range = VK_WHOLE_SIZE;
1175     }
1176 
1177     VkWriteDescriptorSet vkWriteDescriptorSet = {};
1178     vkWriteDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1179     vkWriteDescriptorSet.pNext = NULL;
1180     vkWriteDescriptorSet.dstSet = m_vkDescriptorSet;
1181     vkWriteDescriptorSet.dstBinding = binding;
1182     vkWriteDescriptorSet.dstArrayElement = 0;
1183     vkWriteDescriptorSet.descriptorCount = numBuffers;
1184     vkWriteDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1185     vkWriteDescriptorSet.pImageInfo = NULL;
1186     vkWriteDescriptorSet.pBufferInfo = vkDescriptorBufferInfo;
1187     vkWriteDescriptorSet.pTexelBufferView = NULL;
1188 
1189     vkUpdateDescriptorSets(m_device, 1, &vkWriteDescriptorSet, 0, NULL);
1190     free(vkDescriptorBufferInfo);
1191 }
1192 
update(uint32_t binding,const VulkanImageView & imageView)1193 void VulkanDescriptorSet::update(uint32_t binding,
1194                                  const VulkanImageView &imageView)
1195 {
1196     VkDescriptorImageInfo vkDescriptorImageInfo = {};
1197     vkDescriptorImageInfo.sampler = VK_NULL_HANDLE;
1198     vkDescriptorImageInfo.imageView = imageView;
1199     vkDescriptorImageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
1200 
1201     VkWriteDescriptorSet vkWriteDescriptorSet = {};
1202     vkWriteDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1203     vkWriteDescriptorSet.pNext = NULL;
1204     vkWriteDescriptorSet.dstSet = m_vkDescriptorSet;
1205     vkWriteDescriptorSet.dstBinding = binding;
1206     vkWriteDescriptorSet.dstArrayElement = 0;
1207     vkWriteDescriptorSet.descriptorCount = 1;
1208     vkWriteDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
1209     vkWriteDescriptorSet.pImageInfo = &vkDescriptorImageInfo;
1210     vkWriteDescriptorSet.pBufferInfo = NULL;
1211     vkWriteDescriptorSet.pTexelBufferView = NULL;
1212 
1213     vkUpdateDescriptorSets(m_device, 1, &vkWriteDescriptorSet, 0, NULL);
1214 }
1215 
updateArray(uint32_t binding,const VulkanImageViewList & imageViewList)1216 void VulkanDescriptorSet::updateArray(uint32_t binding,
1217                                       const VulkanImageViewList &imageViewList)
1218 {
1219     VkDescriptorImageInfo *vkDescriptorImageInfo =
1220         new VkDescriptorImageInfo[imageViewList.size()];
1221     for (size_t i = 0; i < imageViewList.size(); i++)
1222     {
1223         vkDescriptorImageInfo[i].sampler = VK_NULL_HANDLE;
1224         vkDescriptorImageInfo[i].imageView = imageViewList[i];
1225         vkDescriptorImageInfo[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
1226     }
1227 
1228     VkWriteDescriptorSet vkWriteDescriptorSet = {};
1229     vkWriteDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1230     vkWriteDescriptorSet.pNext = NULL;
1231     vkWriteDescriptorSet.dstSet = m_vkDescriptorSet;
1232     vkWriteDescriptorSet.dstBinding = binding;
1233     vkWriteDescriptorSet.dstArrayElement = 0;
1234     vkWriteDescriptorSet.descriptorCount = imageViewList.size();
1235     vkWriteDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
1236     vkWriteDescriptorSet.pImageInfo = vkDescriptorImageInfo;
1237     vkWriteDescriptorSet.pBufferInfo = NULL;
1238     vkWriteDescriptorSet.pTexelBufferView = NULL;
1239 
1240     vkUpdateDescriptorSets(m_device, 1, &vkWriteDescriptorSet, 0, NULL);
1241     delete[] vkDescriptorImageInfo;
1242 }
1243 
operator VkDescriptorSet() const1244 VulkanDescriptorSet::operator VkDescriptorSet() const
1245 {
1246     return m_vkDescriptorSet;
1247 }
1248 
1249 ///////////////////////////////////
1250 // VulkanOffset3D implementation //
1251 ///////////////////////////////////
1252 
VulkanOffset3D(const VulkanOffset3D & offset3D)1253 VulkanOffset3D::VulkanOffset3D(const VulkanOffset3D &offset3D)
1254     : m_vkOffset3D(offset3D.m_vkOffset3D)
1255 {}
1256 
VulkanOffset3D(uint32_t x,uint32_t y,uint32_t z)1257 VulkanOffset3D::VulkanOffset3D(uint32_t x, uint32_t y, uint32_t z)
1258 {
1259     m_vkOffset3D.x = x;
1260     m_vkOffset3D.y = y;
1261     m_vkOffset3D.z = z;
1262 }
1263 
~VulkanOffset3D()1264 VulkanOffset3D::~VulkanOffset3D() {}
1265 
getX() const1266 uint32_t VulkanOffset3D::getX() const { return m_vkOffset3D.x; }
1267 
getY() const1268 uint32_t VulkanOffset3D::getY() const { return m_vkOffset3D.y; }
1269 
getZ() const1270 uint32_t VulkanOffset3D::getZ() const { return m_vkOffset3D.z; }
1271 
operator VkOffset3D() const1272 VulkanOffset3D::operator VkOffset3D() const { return m_vkOffset3D; }
1273 
1274 ///////////////////////////////////
1275 // VulkanExtent3D implementation //
1276 ///////////////////////////////////
1277 
VulkanExtent3D(const VulkanExtent3D & extent3D)1278 VulkanExtent3D::VulkanExtent3D(const VulkanExtent3D &extent3D)
1279     : m_vkExtent3D(extent3D.m_vkExtent3D)
1280 {}
1281 
VulkanExtent3D(uint32_t width,uint32_t height,uint32_t depth)1282 VulkanExtent3D::VulkanExtent3D(uint32_t width, uint32_t height, uint32_t depth)
1283 {
1284     m_vkExtent3D.width = width;
1285     m_vkExtent3D.height = height;
1286     m_vkExtent3D.depth = depth;
1287 }
1288 
~VulkanExtent3D()1289 VulkanExtent3D::~VulkanExtent3D() {}
1290 
getWidth() const1291 uint32_t VulkanExtent3D::getWidth() const { return m_vkExtent3D.width; }
1292 
getHeight() const1293 uint32_t VulkanExtent3D::getHeight() const { return m_vkExtent3D.height; }
1294 
getDepth() const1295 uint32_t VulkanExtent3D::getDepth() const { return m_vkExtent3D.depth; }
1296 
operator VkExtent3D() const1297 VulkanExtent3D::operator VkExtent3D() const { return m_vkExtent3D; }
1298 
1299 //////////////////////////////////////
1300 // VulkanCommandPool implementation //
1301 //////////////////////////////////////
1302 
VulkanCommandPool(const VulkanCommandPool & commandPool)1303 VulkanCommandPool::VulkanCommandPool(const VulkanCommandPool &commandPool)
1304     : m_device(commandPool.m_device),
1305       m_vkCommandPool(commandPool.m_vkCommandPool)
1306 {}
1307 
VulkanCommandPool(const VulkanDevice & device,const VulkanQueueFamily & queueFamily)1308 VulkanCommandPool::VulkanCommandPool(const VulkanDevice &device,
1309                                      const VulkanQueueFamily &queueFamily)
1310     : m_device(device)
1311 {
1312     VkCommandPoolCreateInfo vkCommandPoolCreateInfo = {};
1313     vkCommandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
1314     vkCommandPoolCreateInfo.pNext = NULL;
1315     vkCommandPoolCreateInfo.flags =
1316         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
1317     vkCommandPoolCreateInfo.queueFamilyIndex = queueFamily;
1318 
1319     vkCreateCommandPool(m_device, &vkCommandPoolCreateInfo, NULL,
1320                         &m_vkCommandPool);
1321 }
1322 
~VulkanCommandPool()1323 VulkanCommandPool::~VulkanCommandPool()
1324 {
1325     vkDestroyCommandPool(m_device, m_vkCommandPool, NULL);
1326 }
1327 
operator VkCommandPool() const1328 VulkanCommandPool::operator VkCommandPool() const { return m_vkCommandPool; }
1329 
1330 ////////////////////////////////////////
1331 // VulkanCommandBuffer implementation //
1332 ////////////////////////////////////////
1333 
VulkanCommandBuffer(const VulkanCommandBuffer & commandBuffer)1334 VulkanCommandBuffer::VulkanCommandBuffer(
1335     const VulkanCommandBuffer &commandBuffer)
1336     : m_device(commandBuffer.m_device),
1337       m_commandPool(commandBuffer.m_commandPool),
1338       m_vkCommandBuffer(commandBuffer.m_vkCommandBuffer)
1339 {}
1340 
VulkanCommandBuffer(const VulkanDevice & device,const VulkanCommandPool & commandPool)1341 VulkanCommandBuffer::VulkanCommandBuffer(const VulkanDevice &device,
1342                                          const VulkanCommandPool &commandPool)
1343     : m_device(device), m_commandPool(commandPool)
1344 {
1345     VkCommandBufferAllocateInfo vkCommandBufferAllocateInfo = {};
1346     vkCommandBufferAllocateInfo.sType =
1347         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
1348     vkCommandBufferAllocateInfo.pNext = NULL;
1349     vkCommandBufferAllocateInfo.commandPool = commandPool;
1350     vkCommandBufferAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
1351     vkCommandBufferAllocateInfo.commandBufferCount = 1;
1352 
1353     vkAllocateCommandBuffers(m_device, &vkCommandBufferAllocateInfo,
1354                              &m_vkCommandBuffer);
1355 }
1356 
~VulkanCommandBuffer()1357 VulkanCommandBuffer::~VulkanCommandBuffer()
1358 {
1359     vkFreeCommandBuffers(m_device, m_commandPool, 1, &m_vkCommandBuffer);
1360 }
1361 
begin()1362 void VulkanCommandBuffer::begin()
1363 {
1364     VkCommandBufferBeginInfo vkCommandBufferBeginInfo = {};
1365     vkCommandBufferBeginInfo.sType =
1366         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
1367     vkCommandBufferBeginInfo.pNext = NULL;
1368     vkCommandBufferBeginInfo.flags =
1369         VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
1370     vkCommandBufferBeginInfo.pInheritanceInfo = NULL;
1371 
1372     vkBeginCommandBuffer(m_vkCommandBuffer, &vkCommandBufferBeginInfo);
1373 }
1374 
bindPipeline(const VulkanPipeline & pipeline)1375 void VulkanCommandBuffer::bindPipeline(const VulkanPipeline &pipeline)
1376 {
1377     VkPipelineBindPoint vkPipelineBindPoint =
1378         (VkPipelineBindPoint)pipeline.getPipelineBindPoint();
1379 
1380     vkCmdBindPipeline(m_vkCommandBuffer, vkPipelineBindPoint, pipeline);
1381 }
1382 
bindDescriptorSets(const VulkanPipeline & pipeline,const VulkanPipelineLayout & pipelineLayout,const VulkanDescriptorSet & descriptorSet)1383 void VulkanCommandBuffer::bindDescriptorSets(
1384     const VulkanPipeline &pipeline, const VulkanPipelineLayout &pipelineLayout,
1385     const VulkanDescriptorSet &descriptorSet)
1386 {
1387     VkPipelineBindPoint vkPipelineBindPoint =
1388         (VkPipelineBindPoint)pipeline.getPipelineBindPoint();
1389     VkDescriptorSet vkDescriptorSet = descriptorSet;
1390 
1391     vkCmdBindDescriptorSets(m_vkCommandBuffer, vkPipelineBindPoint,
1392                             pipelineLayout, 0, 1, &vkDescriptorSet, 0, NULL);
1393 }
1394 
pipelineBarrier(const VulkanImage2DList & image2DList,VulkanImageLayout oldImageLayout,VulkanImageLayout newImageLayout)1395 void VulkanCommandBuffer::pipelineBarrier(const VulkanImage2DList &image2DList,
1396                                           VulkanImageLayout oldImageLayout,
1397                                           VulkanImageLayout newImageLayout)
1398 {
1399     std::vector<VkImageMemoryBarrier> vkImageMemoryBarrierList;
1400     for (size_t i2DIdx = 0; i2DIdx < image2DList.size(); i2DIdx++)
1401     {
1402         VkImageSubresourceRange vkImageSubresourceRange = {};
1403         vkImageSubresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1404         vkImageSubresourceRange.baseMipLevel = 0;
1405         vkImageSubresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
1406         vkImageSubresourceRange.baseArrayLayer = 0;
1407         vkImageSubresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
1408 
1409         VkImageMemoryBarrier vkImageMemoryBarrier = {};
1410         vkImageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
1411         vkImageMemoryBarrier.pNext = NULL;
1412         vkImageMemoryBarrier.srcAccessMask = 0;
1413         vkImageMemoryBarrier.dstAccessMask = 0;
1414         vkImageMemoryBarrier.oldLayout = (VkImageLayout)oldImageLayout;
1415         vkImageMemoryBarrier.newLayout = (VkImageLayout)newImageLayout;
1416         vkImageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1417         vkImageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1418         vkImageMemoryBarrier.image = image2DList[i2DIdx];
1419         vkImageMemoryBarrier.subresourceRange = vkImageSubresourceRange;
1420 
1421         vkImageMemoryBarrierList.push_back(vkImageMemoryBarrier);
1422     }
1423 
1424     vkCmdPipelineBarrier(m_vkCommandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
1425                          VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, NULL, 0,
1426                          NULL, (uint32_t)vkImageMemoryBarrierList.size(),
1427                          vkImageMemoryBarrierList.data());
1428 }
1429 
dispatch(uint32_t groupCountX,uint32_t groupCountY,uint32_t groupCountZ)1430 void VulkanCommandBuffer::dispatch(uint32_t groupCountX, uint32_t groupCountY,
1431                                    uint32_t groupCountZ)
1432 {
1433     vkCmdDispatch(m_vkCommandBuffer, groupCountX, groupCountY, groupCountZ);
1434 }
1435 
fillBuffer(const VulkanBuffer & buffer,uint32_t data,uint64_t offset,uint64_t size)1436 void VulkanCommandBuffer::fillBuffer(const VulkanBuffer &buffer, uint32_t data,
1437                                      uint64_t offset, uint64_t size)
1438 {
1439     vkCmdFillBuffer(m_vkCommandBuffer, buffer, offset, size, data);
1440 }
1441 
updateBuffer(const VulkanBuffer & buffer,void * pdata,uint64_t offset,uint64_t size)1442 void VulkanCommandBuffer::updateBuffer(const VulkanBuffer &buffer, void *pdata,
1443                                        uint64_t offset, uint64_t size)
1444 {
1445     vkCmdUpdateBuffer(m_vkCommandBuffer, buffer, offset, size, pdata);
1446 }
1447 
copyBufferToImage(const VulkanBuffer & buffer,const VulkanImage & image,VulkanImageLayout imageLayout)1448 void VulkanCommandBuffer::copyBufferToImage(const VulkanBuffer &buffer,
1449                                             const VulkanImage &image,
1450                                             VulkanImageLayout imageLayout)
1451 {
1452     VkDeviceSize bufferOffset = 0;
1453 
1454     std::vector<VkBufferImageCopy> vkBufferImageCopyList;
1455     for (uint32_t mipLevel = 0; mipLevel < image.getNumMipLevels(); mipLevel++)
1456     {
1457         VulkanExtent3D extent3D = image.getExtent3D(mipLevel);
1458         size_t elementSize = getVulkanFormatElementSize(image.getFormat());
1459 
1460         VkImageSubresourceLayers vkImageSubresourceLayers = {};
1461         vkImageSubresourceLayers.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1462         vkImageSubresourceLayers.mipLevel = mipLevel;
1463         vkImageSubresourceLayers.baseArrayLayer = 0;
1464         vkImageSubresourceLayers.layerCount = image.getNumLayers();
1465 
1466         VkBufferImageCopy vkBufferImageCopy = {};
1467         vkBufferImageCopy.bufferOffset = bufferOffset;
1468         vkBufferImageCopy.bufferRowLength = 0;
1469         vkBufferImageCopy.bufferImageHeight = 0;
1470         vkBufferImageCopy.imageSubresource = vkImageSubresourceLayers;
1471         vkBufferImageCopy.imageOffset = VulkanOffset3D(0, 0, 0);
1472         vkBufferImageCopy.imageExtent = extent3D;
1473 
1474         vkBufferImageCopyList.push_back(vkBufferImageCopy);
1475 
1476         bufferOffset += extent3D.getWidth() * extent3D.getHeight()
1477             * extent3D.getDepth() * elementSize;
1478         bufferOffset =
1479             ROUND_UP(bufferOffset,
1480                      std::max(elementSize,
1481                               (size_t)VULKAN_MIN_BUFFER_OFFSET_COPY_ALIGNMENT));
1482     }
1483 
1484     vkCmdCopyBufferToImage(
1485         m_vkCommandBuffer, buffer, image, (VkImageLayout)imageLayout,
1486         (uint32_t)vkBufferImageCopyList.size(), vkBufferImageCopyList.data());
1487 }
1488 
copyBufferToImage(const VulkanBuffer & buffer,const VulkanImage & image,uint64_t bufferOffset,uint32_t mipLevel,uint32_t baseArrayLayer,uint32_t layerCount,VulkanOffset3D offset3D,VulkanExtent3D extent3D)1489 void VulkanCommandBuffer::copyBufferToImage(
1490     const VulkanBuffer &buffer, const VulkanImage &image, uint64_t bufferOffset,
1491     uint32_t mipLevel, uint32_t baseArrayLayer, uint32_t layerCount,
1492     VulkanOffset3D offset3D, VulkanExtent3D extent3D)
1493 {
1494     VkImageSubresourceLayers vkImageSubresourceLayers = {};
1495     vkImageSubresourceLayers.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1496     vkImageSubresourceLayers.mipLevel = mipLevel;
1497     vkImageSubresourceLayers.baseArrayLayer = baseArrayLayer;
1498     vkImageSubresourceLayers.layerCount = layerCount;
1499 
1500     VkExtent3D vkExtent3D = extent3D;
1501     if ((extent3D.getWidth() == 0) && (extent3D.getHeight() == 0)
1502         && (extent3D.getDepth() == 0))
1503     {
1504         vkExtent3D = image.getExtent3D(mipLevel);
1505     }
1506 
1507     VkBufferImageCopy vkBufferImageCopy = {};
1508     vkBufferImageCopy.bufferOffset = bufferOffset;
1509     vkBufferImageCopy.bufferRowLength = 0;
1510     vkBufferImageCopy.bufferImageHeight = 0;
1511     vkBufferImageCopy.imageSubresource = vkImageSubresourceLayers;
1512     vkBufferImageCopy.imageOffset = offset3D;
1513     vkBufferImageCopy.imageExtent = vkExtent3D;
1514 
1515     vkCmdCopyBufferToImage(m_vkCommandBuffer, buffer, image,
1516                            VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1,
1517                            &vkBufferImageCopy);
1518 }
1519 
copyImageToBuffer(const VulkanImage & image,const VulkanBuffer & buffer,uint64_t bufferOffset,uint32_t mipLevel,uint32_t baseArrayLayer,uint32_t layerCount,VulkanOffset3D offset3D,VulkanExtent3D extent3D)1520 void VulkanCommandBuffer::copyImageToBuffer(
1521     const VulkanImage &image, const VulkanBuffer &buffer, uint64_t bufferOffset,
1522     uint32_t mipLevel, uint32_t baseArrayLayer, uint32_t layerCount,
1523     VulkanOffset3D offset3D, VulkanExtent3D extent3D)
1524 {
1525     VkImageSubresourceLayers vkImageSubresourceLayers = {};
1526     vkImageSubresourceLayers.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1527     vkImageSubresourceLayers.mipLevel = mipLevel;
1528     vkImageSubresourceLayers.baseArrayLayer = baseArrayLayer;
1529     vkImageSubresourceLayers.layerCount = layerCount;
1530 
1531     VkExtent3D vkExtent3D = extent3D;
1532     if ((extent3D.getWidth() == 0) && (extent3D.getHeight() == 0)
1533         && (extent3D.getDepth() == 0))
1534     {
1535         vkExtent3D = image.getExtent3D(mipLevel);
1536     }
1537 
1538     VkBufferImageCopy vkBufferImageCopy = {};
1539     vkBufferImageCopy.bufferOffset = bufferOffset;
1540     vkBufferImageCopy.bufferRowLength = 0;
1541     vkBufferImageCopy.bufferImageHeight = 0;
1542     vkBufferImageCopy.imageSubresource = vkImageSubresourceLayers;
1543     vkBufferImageCopy.imageOffset = offset3D;
1544     vkBufferImageCopy.imageExtent = vkExtent3D;
1545 
1546     vkCmdCopyImageToBuffer(m_vkCommandBuffer, image, VK_IMAGE_LAYOUT_GENERAL,
1547                            buffer, 1, &vkBufferImageCopy);
1548 }
1549 
end()1550 void VulkanCommandBuffer::end() { vkEndCommandBuffer(m_vkCommandBuffer); }
1551 
operator VkCommandBuffer() const1552 VulkanCommandBuffer::operator VkCommandBuffer() const
1553 {
1554     return m_vkCommandBuffer;
1555 }
1556 
1557 /////////////////////////////////
1558 // VulkanBuffer implementation //
1559 /////////////////////////////////
1560 
VulkanBuffer(const VulkanBuffer & buffer)1561 VulkanBuffer::VulkanBuffer(const VulkanBuffer &buffer)
1562     : m_device(buffer.m_device), m_vkBuffer(buffer.m_vkBuffer),
1563       m_size(buffer.m_size), m_alignment(buffer.m_alignment),
1564       m_memoryTypeList(buffer.m_memoryTypeList)
1565 {}
1566 
isDedicated() const1567 bool VulkanBuffer::isDedicated() const { return m_dedicated; }
1568 
VulkanBuffer(const VulkanDevice & device,uint64_t size,VulkanExternalMemoryHandleType externalMemoryHandleType,VulkanBufferUsage bufferUsage,VulkanSharingMode sharingMode,const VulkanQueueFamilyList & queueFamilyList)1569 VulkanBuffer::VulkanBuffer(
1570     const VulkanDevice &device, uint64_t size,
1571     VulkanExternalMemoryHandleType externalMemoryHandleType,
1572     VulkanBufferUsage bufferUsage, VulkanSharingMode sharingMode,
1573     const VulkanQueueFamilyList &queueFamilyList)
1574     : m_device(device), m_vkBuffer(VK_NULL_HANDLE), m_dedicated(false)
1575 {
1576     std::vector<uint32_t> queueFamilyIndexList;
1577     if (queueFamilyList.size() == 0)
1578     {
1579         for (size_t qfIdx = 0;
1580              qfIdx < device.getPhysicalDevice().getQueueFamilyList().size();
1581              qfIdx++)
1582         {
1583             queueFamilyIndexList.push_back(
1584                 device.getPhysicalDevice().getQueueFamilyList()[qfIdx]);
1585         }
1586     }
1587     else
1588     {
1589         for (size_t qfIdx = 0; qfIdx < queueFamilyList.size(); qfIdx++)
1590         {
1591             queueFamilyIndexList.push_back(queueFamilyList[qfIdx]);
1592         }
1593     }
1594 
1595     VkBufferCreateInfo vkBufferCreateInfo = {};
1596     vkBufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
1597     vkBufferCreateInfo.pNext = NULL;
1598     vkBufferCreateInfo.flags = 0;
1599     vkBufferCreateInfo.size = (VkDeviceSize)size;
1600     vkBufferCreateInfo.usage = (VkBufferUsageFlags)bufferUsage;
1601     vkBufferCreateInfo.sharingMode = (VkSharingMode)sharingMode;
1602     vkBufferCreateInfo.queueFamilyIndexCount =
1603         (uint32_t)queueFamilyIndexList.size();
1604     vkBufferCreateInfo.pQueueFamilyIndices = queueFamilyIndexList.data();
1605 
1606     VkExternalMemoryBufferCreateInfo vkExternalMemoryBufferCreateInfo = {};
1607     if (externalMemoryHandleType != VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_NONE)
1608     {
1609         vkExternalMemoryBufferCreateInfo.sType =
1610             VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR;
1611         vkExternalMemoryBufferCreateInfo.pNext = NULL;
1612         vkExternalMemoryBufferCreateInfo.handleTypes =
1613             (VkExternalMemoryHandleTypeFlags)externalMemoryHandleType;
1614 
1615         vkBufferCreateInfo.pNext = &vkExternalMemoryBufferCreateInfo;
1616     }
1617 
1618     vkCreateBuffer(m_device, &vkBufferCreateInfo, NULL, &m_vkBuffer);
1619 
1620     VkMemoryDedicatedRequirements vkMemoryDedicatedRequirements = {};
1621     vkMemoryDedicatedRequirements.sType =
1622         VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS;
1623     vkMemoryDedicatedRequirements.pNext = NULL;
1624 
1625     VkMemoryRequirements2 vkMemoryRequirements = {};
1626     vkMemoryRequirements.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
1627     vkMemoryRequirements.pNext = &vkMemoryDedicatedRequirements;
1628 
1629     VkBufferMemoryRequirementsInfo2 vkMemoryRequirementsInfo = {};
1630 
1631     vkMemoryRequirementsInfo.sType =
1632         VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2;
1633     vkMemoryRequirementsInfo.buffer = m_vkBuffer;
1634     vkMemoryRequirementsInfo.pNext = NULL;
1635 
1636     vkGetBufferMemoryRequirements2(m_device, &vkMemoryRequirementsInfo,
1637                                    &vkMemoryRequirements);
1638 
1639     m_dedicated = vkMemoryDedicatedRequirements.requiresDedicatedAllocation;
1640 
1641     m_size = vkMemoryRequirements.memoryRequirements.size;
1642     m_alignment = vkMemoryRequirements.memoryRequirements.alignment;
1643     const VulkanMemoryTypeList &memoryTypeList =
1644         m_device.getPhysicalDevice().getMemoryTypeList();
1645     for (size_t mtIdx = 0; mtIdx < memoryTypeList.size(); mtIdx++)
1646     {
1647         uint32_t memoryTypeIndex = memoryTypeList[mtIdx];
1648         if ((1 << memoryTypeIndex)
1649             & vkMemoryRequirements.memoryRequirements.memoryTypeBits)
1650         {
1651             m_memoryTypeList.add(memoryTypeList[mtIdx]);
1652         }
1653     }
1654 }
1655 
~VulkanBuffer()1656 VulkanBuffer::~VulkanBuffer() { vkDestroyBuffer(m_device, m_vkBuffer, NULL); }
1657 
getSize() const1658 uint64_t VulkanBuffer::getSize() const { return m_size; }
1659 
getAlignment() const1660 uint64_t VulkanBuffer::getAlignment() const { return m_alignment; }
1661 
getMemoryTypeList() const1662 const VulkanMemoryTypeList &VulkanBuffer::getMemoryTypeList() const
1663 {
1664     return m_memoryTypeList;
1665 }
1666 
operator VkBuffer() const1667 VulkanBuffer::operator VkBuffer() const { return m_vkBuffer; }
1668 
1669 ////////////////////////////////
1670 // VulkanImage implementation //
1671 ////////////////////////////////
1672 
VulkanImage(const VulkanImage & image)1673 VulkanImage::VulkanImage(const VulkanImage &image)
1674     : m_device(image.m_device), m_imageType(image.m_imageType),
1675       m_extent3D(image.m_extent3D), m_format(image.m_format),
1676       m_numMipLevels(image.m_numMipLevels), m_numLayers(image.m_numLayers),
1677       m_vkImage(image.m_vkImage), m_size(image.m_size),
1678       m_alignment(image.m_alignment), m_memoryTypeList(image.m_memoryTypeList)
1679 {}
1680 
VulkanImage(const VulkanDevice & device,VulkanImageType imageType,VulkanFormat format,const VulkanExtent3D & extent3D,uint32_t numMipLevels,uint32_t arrayLayers,VulkanExternalMemoryHandleType externalMemoryHandleType,VulkanImageCreateFlag imageCreateFlag,VulkanImageTiling imageTiling,VulkanImageUsage imageUsage,VulkanSharingMode sharingMode)1681 VulkanImage::VulkanImage(
1682     const VulkanDevice &device, VulkanImageType imageType, VulkanFormat format,
1683     const VulkanExtent3D &extent3D, uint32_t numMipLevels, uint32_t arrayLayers,
1684     VulkanExternalMemoryHandleType externalMemoryHandleType,
1685     VulkanImageCreateFlag imageCreateFlag, VulkanImageTiling imageTiling,
1686     VulkanImageUsage imageUsage, VulkanSharingMode sharingMode)
1687     : m_device(device), m_imageType(imageType), m_extent3D(extent3D),
1688       m_format(format), m_numMipLevels(numMipLevels), m_numLayers(arrayLayers),
1689       m_vkImage(VK_NULL_HANDLE)
1690 {
1691     VkImageCreateInfo vkImageCreateInfo = {};
1692     vkImageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
1693     vkImageCreateInfo.pNext = NULL;
1694     vkImageCreateInfo.flags = (VkImageCreateFlags)imageCreateFlag;
1695     vkImageCreateInfo.imageType = (VkImageType)imageType;
1696     vkImageCreateInfo.format = (VkFormat)format;
1697     vkImageCreateInfo.extent = extent3D;
1698     vkImageCreateInfo.mipLevels = numMipLevels;
1699     vkImageCreateInfo.arrayLayers = arrayLayers;
1700     vkImageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
1701     vkImageCreateInfo.tiling = (VkImageTiling)imageTiling;
1702     vkImageCreateInfo.usage = (VkImageUsageFlags)imageUsage;
1703     vkImageCreateInfo.sharingMode = (VkSharingMode)sharingMode;
1704     vkImageCreateInfo.queueFamilyIndexCount =
1705         (uint32_t)m_device.getPhysicalDevice().getQueueFamilyList().size();
1706     vkImageCreateInfo.pQueueFamilyIndices =
1707         m_device.getPhysicalDevice().getQueueFamilyList()();
1708     vkImageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
1709 
1710     VkExternalMemoryImageCreateInfo vkExternalMemoryImageCreateInfo = {};
1711     if (externalMemoryHandleType != VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_NONE)
1712     {
1713         vkExternalMemoryImageCreateInfo.sType =
1714             VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
1715         vkExternalMemoryImageCreateInfo.pNext = NULL;
1716         vkExternalMemoryImageCreateInfo.handleTypes =
1717             (VkExternalMemoryHandleTypeFlags)externalMemoryHandleType;
1718 
1719         vkImageCreateInfo.pNext = &vkExternalMemoryImageCreateInfo;
1720     }
1721 
1722     vkCreateImage(m_device, &vkImageCreateInfo, NULL, &m_vkImage);
1723     VulkanImageCreateInfo = vkImageCreateInfo;
1724 
1725     VkMemoryDedicatedRequirements vkMemoryDedicatedRequirements = {};
1726     vkMemoryDedicatedRequirements.sType =
1727         VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS;
1728     vkMemoryDedicatedRequirements.pNext = NULL;
1729 
1730     VkMemoryRequirements2 vkMemoryRequirements = {};
1731     vkMemoryRequirements.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
1732     vkMemoryRequirements.pNext = &vkMemoryDedicatedRequirements;
1733 
1734     VkImageMemoryRequirementsInfo2 vkMemoryRequirementsInfo = {};
1735 
1736     vkMemoryRequirementsInfo.sType =
1737         VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2;
1738     vkMemoryRequirementsInfo.image = m_vkImage;
1739     vkMemoryRequirementsInfo.pNext = NULL;
1740 
1741     vkGetImageMemoryRequirements2(m_device, &vkMemoryRequirementsInfo,
1742                                   &vkMemoryRequirements);
1743     m_size = vkMemoryRequirements.memoryRequirements.size;
1744     m_alignment = vkMemoryRequirements.memoryRequirements.alignment;
1745     m_dedicated = vkMemoryDedicatedRequirements.requiresDedicatedAllocation;
1746 
1747     const VulkanMemoryTypeList &memoryTypeList =
1748         m_device.getPhysicalDevice().getMemoryTypeList();
1749     for (size_t mtIdx = 0; mtIdx < memoryTypeList.size(); mtIdx++)
1750     {
1751         uint32_t memoryTypeIndex = memoryTypeList[mtIdx];
1752         if ((1 << memoryTypeIndex)
1753             & vkMemoryRequirements.memoryRequirements.memoryTypeBits)
1754         {
1755             m_memoryTypeList.add(memoryTypeList[mtIdx]);
1756         }
1757     }
1758 }
1759 
~VulkanImage()1760 VulkanImage::~VulkanImage() { vkDestroyImage(m_device, m_vkImage, NULL); }
1761 
getExtent3D(uint32_t mipLevel) const1762 VulkanExtent3D VulkanImage::getExtent3D(uint32_t mipLevel) const
1763 {
1764     return VulkanExtent3D(0, 0, 0);
1765 }
1766 
getFormat() const1767 VulkanFormat VulkanImage::getFormat() const { return m_format; }
1768 
getVkImageCreateInfo() const1769 VkImageCreateInfo VulkanImage::getVkImageCreateInfo() const
1770 {
1771     return VulkanImageCreateInfo;
1772 }
1773 
getNumMipLevels() const1774 uint32_t VulkanImage::getNumMipLevels() const { return m_numMipLevels; }
1775 
getNumLayers() const1776 uint32_t VulkanImage::getNumLayers() const { return m_numLayers; }
1777 
getSize() const1778 uint64_t VulkanImage::getSize() const { return m_size; }
1779 
getAlignment() const1780 uint64_t VulkanImage::getAlignment() const { return m_alignment; }
1781 
isDedicated() const1782 bool VulkanImage::isDedicated() const { return m_dedicated; }
1783 
getMemoryTypeList() const1784 const VulkanMemoryTypeList &VulkanImage::getMemoryTypeList() const
1785 {
1786     return m_memoryTypeList;
1787 }
1788 
operator VkImage() const1789 VulkanImage::operator VkImage() const { return m_vkImage; }
1790 
1791 //////////////////////////////////
1792 // VulkanImage2D implementation //
1793 //////////////////////////////////
1794 
VulkanImage2D(const VulkanImage2D & image2D)1795 VulkanImage2D::VulkanImage2D(const VulkanImage2D &image2D): VulkanImage(image2D)
1796 {}
1797 
VulkanImage2D(const VulkanDevice & device,VulkanFormat format,uint32_t width,uint32_t height,VulkanImageTiling imageTiling,uint32_t numMipLevels,VulkanExternalMemoryHandleType externalMemoryHandleType,VulkanImageCreateFlag imageCreateFlag,VulkanImageUsage imageUsage,VulkanSharingMode sharingMode)1798 VulkanImage2D::VulkanImage2D(
1799     const VulkanDevice &device, VulkanFormat format, uint32_t width,
1800     uint32_t height, VulkanImageTiling imageTiling, uint32_t numMipLevels,
1801     VulkanExternalMemoryHandleType externalMemoryHandleType,
1802     VulkanImageCreateFlag imageCreateFlag, VulkanImageUsage imageUsage,
1803     VulkanSharingMode sharingMode)
1804     : VulkanImage(device, VULKAN_IMAGE_TYPE_2D, format,
1805                   VulkanExtent3D(width, height, 1), numMipLevels, 1,
1806                   externalMemoryHandleType, imageCreateFlag, imageTiling,
1807                   imageUsage, sharingMode)
1808 {}
1809 
~VulkanImage2D()1810 VulkanImage2D::~VulkanImage2D() {}
1811 
getExtent3D(uint32_t mipLevel) const1812 VulkanExtent3D VulkanImage2D::getExtent3D(uint32_t mipLevel) const
1813 {
1814     uint32_t width = std::max(m_extent3D.getWidth() >> mipLevel, uint32_t(1));
1815     uint32_t height = std::max(m_extent3D.getHeight() >> mipLevel, uint32_t(1));
1816     uint32_t depth = 1;
1817 
1818     return VulkanExtent3D(width, height, depth);
1819 }
1820 
1821 ////////////////////////////////////
1822 // VulkanImageView implementation //
1823 ////////////////////////////////////
1824 
VulkanImageView(const VulkanImageView & imageView)1825 VulkanImageView::VulkanImageView(const VulkanImageView &imageView)
1826     : m_device(imageView.m_device), m_vkImageView(imageView.m_vkImageView)
1827 {}
1828 
VulkanImageView(const VulkanDevice & device,const VulkanImage & image,VulkanImageViewType imageViewType,uint32_t baseMipLevel,uint32_t levelCount,uint32_t baseArrayLayer,uint32_t layerCount)1829 VulkanImageView::VulkanImageView(const VulkanDevice &device,
1830                                  const VulkanImage &image,
1831                                  VulkanImageViewType imageViewType,
1832                                  uint32_t baseMipLevel, uint32_t levelCount,
1833                                  uint32_t baseArrayLayer, uint32_t layerCount)
1834     : m_device(device), m_vkImageView(VK_NULL_HANDLE)
1835 {
1836     VkComponentMapping vkComponentMapping = {};
1837     vkComponentMapping.r = VK_COMPONENT_SWIZZLE_IDENTITY;
1838     vkComponentMapping.g = VK_COMPONENT_SWIZZLE_IDENTITY;
1839     vkComponentMapping.b = VK_COMPONENT_SWIZZLE_IDENTITY;
1840     vkComponentMapping.a = VK_COMPONENT_SWIZZLE_IDENTITY;
1841 
1842     VkImageSubresourceRange vkImageSubresourceRange = {};
1843     vkImageSubresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1844     vkImageSubresourceRange.baseMipLevel = baseMipLevel;
1845     vkImageSubresourceRange.levelCount = levelCount;
1846     vkImageSubresourceRange.baseArrayLayer = baseArrayLayer;
1847     vkImageSubresourceRange.layerCount = layerCount;
1848 
1849     VkImageViewCreateInfo vkImageViewCreateInfo = {};
1850     vkImageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
1851     vkImageViewCreateInfo.pNext = NULL;
1852     vkImageViewCreateInfo.flags = 0;
1853     vkImageViewCreateInfo.image = image;
1854     vkImageViewCreateInfo.viewType = (VkImageViewType)imageViewType;
1855     vkImageViewCreateInfo.format = (VkFormat)image.getFormat();
1856     vkImageViewCreateInfo.components = vkComponentMapping;
1857     vkImageViewCreateInfo.subresourceRange = vkImageSubresourceRange;
1858 
1859     vkCreateImageView(m_device, &vkImageViewCreateInfo, NULL, &m_vkImageView);
1860 }
1861 
~VulkanImageView()1862 VulkanImageView::~VulkanImageView()
1863 {
1864     vkDestroyImageView(m_device, m_vkImageView, NULL);
1865 }
1866 
operator VkImageView() const1867 VulkanImageView::operator VkImageView() const { return m_vkImageView; }
1868 
1869 ///////////////////////////////////////
1870 // VulkanDeviceMemory implementation //
1871 ///////////////////////////////////////
1872 
1873 #if defined(_WIN32) || defined(_WIN64)
1874 
1875 class WindowsSecurityAttributes {
1876 protected:
1877     SECURITY_ATTRIBUTES m_winSecurityAttributes;
1878     PSECURITY_DESCRIPTOR m_winPSecurityDescriptor;
1879 
1880 public:
1881     WindowsSecurityAttributes();
1882     SECURITY_ATTRIBUTES *operator&();
1883     ~WindowsSecurityAttributes();
1884 };
1885 
1886 
WindowsSecurityAttributes()1887 WindowsSecurityAttributes::WindowsSecurityAttributes()
1888 {
1889     m_winPSecurityDescriptor = (PSECURITY_DESCRIPTOR)calloc(
1890         1, SECURITY_DESCRIPTOR_MIN_LENGTH + 2 * sizeof(void **));
1891     // CHECK_NEQ(m_winPSecurityDescriptor, (PSECURITY_DESCRIPTOR)NULL);
1892     PSID *ppSID = (PSID *)((PBYTE)m_winPSecurityDescriptor
1893                            + SECURITY_DESCRIPTOR_MIN_LENGTH);
1894     PACL *ppACL = (PACL *)((PBYTE)ppSID + sizeof(PSID *));
1895     InitializeSecurityDescriptor(m_winPSecurityDescriptor,
1896                                  SECURITY_DESCRIPTOR_REVISION);
1897     SID_IDENTIFIER_AUTHORITY sidIdentifierAuthority =
1898         SECURITY_WORLD_SID_AUTHORITY;
1899     AllocateAndInitializeSid(&sidIdentifierAuthority, 1, SECURITY_WORLD_RID, 0,
1900                              0, 0, 0, 0, 0, 0, ppSID);
1901     EXPLICIT_ACCESS explicitAccess;
1902     ZeroMemory(&explicitAccess, sizeof(EXPLICIT_ACCESS));
1903     explicitAccess.grfAccessPermissions =
1904         STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL;
1905     explicitAccess.grfAccessMode = SET_ACCESS;
1906     explicitAccess.grfInheritance = INHERIT_ONLY;
1907     explicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
1908     explicitAccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
1909     explicitAccess.Trustee.ptstrName = (LPTSTR)*ppSID;
1910     SetEntriesInAcl(1, &explicitAccess, NULL, ppACL);
1911     SetSecurityDescriptorDacl(m_winPSecurityDescriptor, TRUE, *ppACL, FALSE);
1912     m_winSecurityAttributes.nLength = sizeof(m_winSecurityAttributes);
1913     m_winSecurityAttributes.lpSecurityDescriptor = m_winPSecurityDescriptor;
1914     m_winSecurityAttributes.bInheritHandle = TRUE;
1915 }
1916 
operator &()1917 SECURITY_ATTRIBUTES *WindowsSecurityAttributes::operator&()
1918 {
1919     return &m_winSecurityAttributes;
1920 }
1921 
~WindowsSecurityAttributes()1922 WindowsSecurityAttributes::~WindowsSecurityAttributes()
1923 {
1924     PSID *ppSID = (PSID *)((PBYTE)m_winPSecurityDescriptor
1925                            + SECURITY_DESCRIPTOR_MIN_LENGTH);
1926     PACL *ppACL = (PACL *)((PBYTE)ppSID + sizeof(PSID *));
1927     if (*ppSID)
1928     {
1929         FreeSid(*ppSID);
1930     }
1931     if (*ppACL)
1932     {
1933         LocalFree(*ppACL);
1934     }
1935     free(m_winPSecurityDescriptor);
1936 }
1937 
1938 #endif
1939 
VulkanDeviceMemory(const VulkanDeviceMemory & deviceMemory)1940 VulkanDeviceMemory::VulkanDeviceMemory(const VulkanDeviceMemory &deviceMemory)
1941     : m_device(deviceMemory.m_device),
1942       m_vkDeviceMemory(deviceMemory.m_vkDeviceMemory),
1943       m_size(deviceMemory.m_size), m_isDedicated(deviceMemory.m_isDedicated)
1944 {}
1945 
VulkanDeviceMemory(const VulkanDevice & device,uint64_t size,const VulkanMemoryType & memoryType,VulkanExternalMemoryHandleType externalMemoryHandleType,const void * name)1946 VulkanDeviceMemory::VulkanDeviceMemory(
1947     const VulkanDevice &device, uint64_t size,
1948     const VulkanMemoryType &memoryType,
1949     VulkanExternalMemoryHandleType externalMemoryHandleType, const void *name)
1950     : m_device(device), m_size(size), m_isDedicated(false)
1951 {
1952 #if defined(_WIN32) || defined(_WIN64)
1953     WindowsSecurityAttributes winSecurityAttributes;
1954 
1955     VkExportMemoryWin32HandleInfoKHR vkExportMemoryWin32HandleInfoKHR = {};
1956     vkExportMemoryWin32HandleInfoKHR.sType =
1957         VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR;
1958     vkExportMemoryWin32HandleInfoKHR.pNext = NULL;
1959     vkExportMemoryWin32HandleInfoKHR.pAttributes = &winSecurityAttributes;
1960     vkExportMemoryWin32HandleInfoKHR.dwAccess =
1961         DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE;
1962     vkExportMemoryWin32HandleInfoKHR.name = (LPCWSTR)name;
1963 
1964 #endif
1965 
1966     VkExportMemoryAllocateInfoKHR vkExportMemoryAllocateInfoKHR = {};
1967     vkExportMemoryAllocateInfoKHR.sType =
1968         VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR;
1969 #if defined(_WIN32) || defined(_WIN64)
1970     vkExportMemoryAllocateInfoKHR.pNext = externalMemoryHandleType
1971             & VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT
1972         ? &vkExportMemoryWin32HandleInfoKHR
1973         : NULL;
1974 #else
1975     vkExportMemoryAllocateInfoKHR.pNext = NULL;
1976 #endif
1977     vkExportMemoryAllocateInfoKHR.handleTypes =
1978         (VkExternalMemoryHandleTypeFlagsKHR)externalMemoryHandleType;
1979 
1980     VkMemoryAllocateInfo vkMemoryAllocateInfo = {};
1981     vkMemoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
1982     vkMemoryAllocateInfo.pNext =
1983         externalMemoryHandleType ? &vkExportMemoryAllocateInfoKHR : NULL;
1984     vkMemoryAllocateInfo.allocationSize = m_size;
1985     vkMemoryAllocateInfo.memoryTypeIndex = (uint32_t)memoryType;
1986 
1987     vkAllocateMemory(m_device, &vkMemoryAllocateInfo, NULL, &m_vkDeviceMemory);
1988 }
1989 
VulkanDeviceMemory(const VulkanDevice & device,const VulkanImage & image,const VulkanMemoryType & memoryType,VulkanExternalMemoryHandleType externalMemoryHandleType,const void * name)1990 VulkanDeviceMemory::VulkanDeviceMemory(
1991     const VulkanDevice &device, const VulkanImage &image,
1992     const VulkanMemoryType &memoryType,
1993     VulkanExternalMemoryHandleType externalMemoryHandleType, const void *name)
1994     : m_device(device), m_size(image.getSize()),
1995       m_isDedicated(image.isDedicated())
1996 {
1997 #if defined(_WIN32) || defined(_WIN64)
1998     WindowsSecurityAttributes winSecurityAttributes;
1999 
2000     VkExportMemoryWin32HandleInfoKHR vkExportMemoryWin32HandleInfoKHR = {};
2001     vkExportMemoryWin32HandleInfoKHR.sType =
2002         VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR;
2003     vkExportMemoryWin32HandleInfoKHR.pNext = NULL;
2004     vkExportMemoryWin32HandleInfoKHR.pAttributes = &winSecurityAttributes;
2005     vkExportMemoryWin32HandleInfoKHR.dwAccess =
2006         DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE;
2007     vkExportMemoryWin32HandleInfoKHR.name = (LPCWSTR)name;
2008 
2009 #endif
2010 
2011     VkExportMemoryAllocateInfoKHR vkExportMemoryAllocateInfoKHR = {};
2012     vkExportMemoryAllocateInfoKHR.sType =
2013         VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR;
2014 #if defined(_WIN32) || defined(_WIN64)
2015     vkExportMemoryAllocateInfoKHR.pNext = externalMemoryHandleType
2016             & VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT
2017         ? &vkExportMemoryWin32HandleInfoKHR
2018         : NULL;
2019 #else
2020     vkExportMemoryAllocateInfoKHR.pNext = NULL;
2021 #endif
2022     vkExportMemoryAllocateInfoKHR.handleTypes =
2023         (VkExternalMemoryHandleTypeFlagsKHR)externalMemoryHandleType;
2024 
2025     VkMemoryDedicatedAllocateInfo vkMemoryDedicatedAllocateInfo = {};
2026     vkMemoryDedicatedAllocateInfo.sType =
2027         VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
2028     vkMemoryDedicatedAllocateInfo.pNext = NULL;
2029     vkMemoryDedicatedAllocateInfo.image = image;
2030     vkMemoryDedicatedAllocateInfo.buffer = VK_NULL_HANDLE;
2031 
2032     VkMemoryAllocateInfo vkMemoryAllocateInfo = {};
2033     vkMemoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
2034     vkMemoryAllocateInfo.allocationSize = m_size;
2035     vkMemoryAllocateInfo.memoryTypeIndex = (uint32_t)memoryType;
2036 
2037     if (m_isDedicated)
2038     {
2039         vkMemoryAllocateInfo.pNext = &vkMemoryDedicatedAllocateInfo;
2040         vkMemoryDedicatedAllocateInfo.pNext =
2041             externalMemoryHandleType ? &vkExportMemoryAllocateInfoKHR : NULL;
2042     }
2043     else
2044     {
2045         vkMemoryAllocateInfo.pNext =
2046             externalMemoryHandleType ? &vkExportMemoryAllocateInfoKHR : NULL;
2047     }
2048 
2049     vkAllocateMemory(m_device, &vkMemoryAllocateInfo, NULL, &m_vkDeviceMemory);
2050 }
2051 
VulkanDeviceMemory(const VulkanDevice & device,const VulkanBuffer & buffer,const VulkanMemoryType & memoryType,VulkanExternalMemoryHandleType externalMemoryHandleType,const void * name)2052 VulkanDeviceMemory::VulkanDeviceMemory(
2053     const VulkanDevice &device, const VulkanBuffer &buffer,
2054     const VulkanMemoryType &memoryType,
2055     VulkanExternalMemoryHandleType externalMemoryHandleType, const void *name)
2056     : m_device(device), m_size(buffer.getSize()),
2057       m_isDedicated(buffer.isDedicated())
2058 {
2059 #if defined(_WIN32) || defined(_WIN64)
2060     WindowsSecurityAttributes winSecurityAttributes;
2061 
2062     VkExportMemoryWin32HandleInfoKHR vkExportMemoryWin32HandleInfoKHR = {};
2063     vkExportMemoryWin32HandleInfoKHR.sType =
2064         VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR;
2065     vkExportMemoryWin32HandleInfoKHR.pNext = NULL;
2066     vkExportMemoryWin32HandleInfoKHR.pAttributes = &winSecurityAttributes;
2067     vkExportMemoryWin32HandleInfoKHR.dwAccess =
2068         DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE;
2069     vkExportMemoryWin32HandleInfoKHR.name = (LPCWSTR)name;
2070 
2071 #endif
2072 
2073     VkExportMemoryAllocateInfoKHR vkExportMemoryAllocateInfoKHR = {};
2074     vkExportMemoryAllocateInfoKHR.sType =
2075         VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR;
2076 #if defined(_WIN32) || defined(_WIN64)
2077     vkExportMemoryAllocateInfoKHR.pNext = externalMemoryHandleType
2078             & VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT
2079         ? &vkExportMemoryWin32HandleInfoKHR
2080         : NULL;
2081 #else
2082     vkExportMemoryAllocateInfoKHR.pNext = NULL;
2083 #endif
2084     vkExportMemoryAllocateInfoKHR.handleTypes =
2085         (VkExternalMemoryHandleTypeFlagsKHR)externalMemoryHandleType;
2086 
2087     VkMemoryDedicatedAllocateInfo vkMemoryDedicatedAllocateInfo = {};
2088     vkMemoryDedicatedAllocateInfo.sType =
2089         VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
2090     vkMemoryDedicatedAllocateInfo.pNext = NULL;
2091     vkMemoryDedicatedAllocateInfo.image = VK_NULL_HANDLE;
2092     vkMemoryDedicatedAllocateInfo.buffer = buffer;
2093 
2094     VkMemoryAllocateInfo vkMemoryAllocateInfo = {};
2095     vkMemoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
2096     vkMemoryAllocateInfo.allocationSize = m_size;
2097     vkMemoryAllocateInfo.memoryTypeIndex = (uint32_t)memoryType;
2098 
2099     if (m_isDedicated)
2100     {
2101         vkMemoryAllocateInfo.pNext = &vkMemoryDedicatedAllocateInfo;
2102         vkMemoryDedicatedAllocateInfo.pNext =
2103             externalMemoryHandleType ? &vkExportMemoryAllocateInfoKHR : NULL;
2104     }
2105     else
2106     {
2107         vkMemoryAllocateInfo.pNext =
2108             externalMemoryHandleType ? &vkExportMemoryAllocateInfoKHR : NULL;
2109     }
2110 
2111 
2112     VkResult res = vkAllocateMemory(m_device, &vkMemoryAllocateInfo, NULL,
2113                                     &m_vkDeviceMemory);
2114     ASSERT_SUCCESS(res, "Failed to allocate device memory");
2115 }
2116 
~VulkanDeviceMemory()2117 VulkanDeviceMemory::~VulkanDeviceMemory()
2118 {
2119     vkFreeMemory(m_device, m_vkDeviceMemory, NULL);
2120 }
2121 
getSize() const2122 uint64_t VulkanDeviceMemory::getSize() const { return m_size; }
2123 
2124 #ifdef _WIN32
getHandle(VulkanExternalMemoryHandleType externalMemoryHandleType) const2125 HANDLE VulkanDeviceMemory::getHandle(
2126     VulkanExternalMemoryHandleType externalMemoryHandleType) const
2127 {
2128     HANDLE handle;
2129 
2130     VkMemoryGetWin32HandleInfoKHR vkMemoryGetWin32HandleInfoKHR = {};
2131     vkMemoryGetWin32HandleInfoKHR.sType =
2132         VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR;
2133     vkMemoryGetWin32HandleInfoKHR.pNext = NULL;
2134     vkMemoryGetWin32HandleInfoKHR.memory = m_vkDeviceMemory;
2135     vkMemoryGetWin32HandleInfoKHR.handleType =
2136         (VkExternalMemoryHandleTypeFlagBitsKHR)externalMemoryHandleType;
2137 
2138     vkGetMemoryWin32HandleKHR(m_device, &vkMemoryGetWin32HandleInfoKHR,
2139                               &handle);
2140 
2141     return handle;
2142 }
2143 #else
getHandle(VulkanExternalMemoryHandleType externalMemoryHandleType) const2144 int VulkanDeviceMemory::getHandle(
2145     VulkanExternalMemoryHandleType externalMemoryHandleType) const
2146 {
2147     if (externalMemoryHandleType
2148         == VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD)
2149     {
2150         int fd;
2151 
2152         VkMemoryGetFdInfoKHR vkMemoryGetFdInfoKHR = {};
2153         vkMemoryGetFdInfoKHR.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR;
2154         vkMemoryGetFdInfoKHR.pNext = NULL;
2155         vkMemoryGetFdInfoKHR.memory = m_vkDeviceMemory;
2156         vkMemoryGetFdInfoKHR.handleType =
2157             VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
2158 
2159         vkGetMemoryFdKHR(m_device, &vkMemoryGetFdInfoKHR, &fd);
2160 
2161         return fd;
2162     }
2163     return HANDLE_ERROR;
2164 }
2165 #endif
2166 
isDedicated() const2167 bool VulkanDeviceMemory::isDedicated() const { return m_isDedicated; }
2168 
map(size_t offset,size_t size)2169 void *VulkanDeviceMemory::map(size_t offset, size_t size)
2170 {
2171     void *pData;
2172 
2173     vkMapMemory(m_device, m_vkDeviceMemory, (VkDeviceSize)offset,
2174                 (VkDeviceSize)size, 0, &pData);
2175 
2176     return pData;
2177 }
2178 
unmap()2179 void VulkanDeviceMemory::unmap() { vkUnmapMemory(m_device, m_vkDeviceMemory); }
2180 
bindBuffer(const VulkanBuffer & buffer,uint64_t offset)2181 void VulkanDeviceMemory::bindBuffer(const VulkanBuffer &buffer, uint64_t offset)
2182 {
2183     if (buffer.isDedicated() && !m_isDedicated)
2184     {
2185         throw std::runtime_error(
2186             "Buffer requires dedicated memory.  Failed to bind");
2187     }
2188     vkBindBufferMemory(m_device, buffer, m_vkDeviceMemory, offset);
2189 }
2190 
bindImage(const VulkanImage & image,uint64_t offset)2191 void VulkanDeviceMemory::bindImage(const VulkanImage &image, uint64_t offset)
2192 {
2193     if (image.isDedicated() && !m_isDedicated)
2194     {
2195         throw std::runtime_error(
2196             "Image requires dedicated memory.  Failed to bind");
2197     }
2198     vkBindImageMemory(m_device, image, m_vkDeviceMemory, offset);
2199 }
2200 
operator VkDeviceMemory() const2201 VulkanDeviceMemory::operator VkDeviceMemory() const { return m_vkDeviceMemory; }
2202 
2203 ////////////////////////////////////
2204 // VulkanSemaphore implementation //
2205 ////////////////////////////////////
2206 
VulkanSemaphore(const VulkanSemaphore & semaphore)2207 VulkanSemaphore::VulkanSemaphore(const VulkanSemaphore &semaphore)
2208     : m_device(semaphore.m_device), m_vkSemaphore(semaphore.m_vkSemaphore)
2209 {}
2210 
VulkanSemaphore(const VulkanDevice & device,VulkanExternalSemaphoreHandleType externalSemaphoreHandleType,const std::wstring name)2211 VulkanSemaphore::VulkanSemaphore(
2212     const VulkanDevice &device,
2213     VulkanExternalSemaphoreHandleType externalSemaphoreHandleType,
2214     const std::wstring name)
2215     : m_device(device), m_name(name)
2216 {
2217 #if defined(_WIN32) || defined(_WIN64)
2218     WindowsSecurityAttributes winSecurityAttributes;
2219 
2220     VkExportSemaphoreWin32HandleInfoKHR
2221         vkExportSemaphoreWin32HandleInfoKHR = {};
2222     vkExportSemaphoreWin32HandleInfoKHR.sType =
2223         VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR;
2224     vkExportSemaphoreWin32HandleInfoKHR.pNext = NULL;
2225     vkExportSemaphoreWin32HandleInfoKHR.pAttributes = &winSecurityAttributes;
2226     vkExportSemaphoreWin32HandleInfoKHR.dwAccess =
2227         DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE;
2228     vkExportSemaphoreWin32HandleInfoKHR.name =
2229         m_name.size() ? (LPCWSTR)m_name.c_str() : NULL;
2230 #endif
2231 
2232     VkExportSemaphoreCreateInfoKHR vkExportSemaphoreCreateInfoKHR = {};
2233     vkExportSemaphoreCreateInfoKHR.sType =
2234         VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR;
2235 #if defined(_WIN32) || defined(_WIN64)
2236     vkExportSemaphoreCreateInfoKHR.pNext =
2237         (externalSemaphoreHandleType
2238          & VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT)
2239         ? &vkExportSemaphoreWin32HandleInfoKHR
2240         : NULL;
2241 #else
2242     vkExportSemaphoreCreateInfoKHR.pNext = NULL;
2243 #endif
2244     vkExportSemaphoreCreateInfoKHR.handleTypes =
2245         (VkExternalSemaphoreHandleTypeFlagsKHR)externalSemaphoreHandleType;
2246 
2247     VkSemaphoreCreateInfo vkSemaphoreCreateInfo = {};
2248     vkSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
2249     vkSemaphoreCreateInfo.pNext =
2250         (externalSemaphoreHandleType
2251          != VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_NONE)
2252         ? &vkExportSemaphoreCreateInfoKHR
2253         : NULL;
2254     vkSemaphoreCreateInfo.flags = 0;
2255 
2256     vkCreateSemaphore(m_device, &vkSemaphoreCreateInfo, NULL, &m_vkSemaphore);
2257 }
2258 
~VulkanSemaphore()2259 VulkanSemaphore::~VulkanSemaphore()
2260 {
2261     vkDestroySemaphore(m_device, m_vkSemaphore, NULL);
2262 }
2263 
2264 #if defined(_WIN32) || defined(_WIN64)
getHandle(VulkanExternalSemaphoreHandleType externalSemaphoreHandleType) const2265 HANDLE VulkanSemaphore::getHandle(
2266     VulkanExternalSemaphoreHandleType externalSemaphoreHandleType) const
2267 {
2268     HANDLE handle;
2269 
2270     VkSemaphoreGetWin32HandleInfoKHR vkSemaphoreGetWin32HandleInfoKHR = {};
2271     vkSemaphoreGetWin32HandleInfoKHR.sType =
2272         VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR;
2273     vkSemaphoreGetWin32HandleInfoKHR.pNext = NULL;
2274     vkSemaphoreGetWin32HandleInfoKHR.semaphore = m_vkSemaphore;
2275     vkSemaphoreGetWin32HandleInfoKHR.handleType =
2276         (VkExternalSemaphoreHandleTypeFlagBitsKHR)externalSemaphoreHandleType;
2277 
2278     vkGetSemaphoreWin32HandleKHR(m_device, &vkSemaphoreGetWin32HandleInfoKHR,
2279                                  &handle);
2280 
2281     return handle;
2282 }
2283 #else
getHandle(VulkanExternalSemaphoreHandleType externalSemaphoreHandleType) const2284 int VulkanSemaphore::getHandle(
2285     VulkanExternalSemaphoreHandleType externalSemaphoreHandleType) const
2286 {
2287     if (externalSemaphoreHandleType
2288         == VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD)
2289     {
2290         int fd;
2291 
2292         VkSemaphoreGetFdInfoKHR vkSemaphoreGetFdInfoKHR = {};
2293         vkSemaphoreGetFdInfoKHR.sType =
2294             VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR;
2295         vkSemaphoreGetFdInfoKHR.pNext = NULL;
2296         vkSemaphoreGetFdInfoKHR.semaphore = m_vkSemaphore;
2297         vkSemaphoreGetFdInfoKHR.handleType =
2298             VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
2299 
2300         vkGetSemaphoreFdKHR(m_device, &vkSemaphoreGetFdInfoKHR, &fd);
2301 
2302         return fd;
2303     }
2304     return HANDLE_ERROR;
2305 }
2306 #endif
2307 
getName() const2308 const std::wstring &VulkanSemaphore::getName() const { return m_name; }
2309 
operator VkSemaphore() const2310 VulkanSemaphore::operator VkSemaphore() const { return m_vkSemaphore; }
2311