• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define NOMINMAX
19 #include <Windows.h>
20 #include <dxgi1_2.h>
21 #include <aclapi.h>
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(__linux__)
76     const char *vulkanLoaderLibraryName = "libvulkan.so.1";
77 #endif
78 #ifdef _WIN32
79     HINSTANCE hDLL;
80     hDLL = LoadLibrary(vulkanLoaderLibraryName);
81     if (hDLL == NULL)
82     {
83         throw std::runtime_error("LoadLibrary failed!");
84     }
85     vkGetInstanceProcAddr =
86         (PFN_vkGetInstanceProcAddr)LoadFunction(hDLL, "vkGetInstanceProcAddr");
87 #else
88 #if !defined(__APPLE__)
89     void *handle;
90     handle = dlopen(vulkanLoaderLibraryName, RTLD_LAZY);
91     if (!handle)
92     {
93         fputs(dlerror(), stderr);
94         throw std::runtime_error("dlopen failed !!!");
95     }
96     vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)LoadFunction(
97         handle, "vkGetInstanceProcAddr");
98 #endif
99 #endif
100     if ((unsigned long long)vkGetInstanceProcAddr == (unsigned long long)NULL)
101     {
102         throw std::runtime_error("vkGetInstanceProcAddr() not found!");
103     }
104 #define VK_GET_NULL_INSTANCE_PROC_ADDR(name)                                   \
105     _##name = (PFN_##name)vkGetInstanceProcAddr(NULL, #name);
106 
107     if ((unsigned long long)vkGetInstanceProcAddr == (unsigned long long)NULL)
108     {
109         throw std::runtime_error("Couldn't obtain address for function");
110     }
111     VK_GET_NULL_INSTANCE_PROC_ADDR(vkEnumerateInstanceExtensionProperties);
112     uint32_t instanceExtensionPropertiesCount;
113     VkResult vkStatus = VK_SUCCESS;
114     vkStatus = vkEnumerateInstanceExtensionProperties(
115         NULL, &instanceExtensionPropertiesCount, NULL);
116     // Something went wrong in vulkan initialization (most likely incompatible
117     // device/driver combination)
118     if (vkStatus == VK_ERROR_INCOMPATIBLE_DRIVER)
119     {
120         throw std::runtime_error(
121             "Waiving vulkan test because "
122             "vkEnumerateInstanceExtensionProperties failed.");
123         // return WAIVED;
124     }
125 
126     VK_GET_NULL_INSTANCE_PROC_ADDR(vkEnumerateInstanceVersion);
127     VK_GET_NULL_INSTANCE_PROC_ADDR(vkEnumerateInstanceLayerProperties);
128     VK_GET_NULL_INSTANCE_PROC_ADDR(vkCreateInstance);
129 #undef VK_GET_NULL_INSTANCE_PROC_ADDR
130 
131     VkApplicationInfo vkApplicationInfo = {};
132     vkApplicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
133     vkApplicationInfo.pNext = NULL;
134     vkApplicationInfo.pApplicationName = "Default app";
135     vkApplicationInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
136     vkApplicationInfo.pEngineName = "No engine";
137     vkApplicationInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
138     vkApplicationInfo.apiVersion = VK_API_VERSION_1_0;
139 
140     std::vector<const char *> enabledExtensionNameList;
141     enabledExtensionNameList.push_back(
142         VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
143     enabledExtensionNameList.push_back(
144         VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME);
145     enabledExtensionNameList.push_back(
146         VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME);
147 
148     std::vector<VkExtensionProperties> vkExtensionPropertiesList(
149         instanceExtensionPropertiesCount);
150     vkEnumerateInstanceExtensionProperties(NULL,
151                                            &instanceExtensionPropertiesCount,
152                                            vkExtensionPropertiesList.data());
153 
154     for (size_t eenIdx = 0; eenIdx < enabledExtensionNameList.size(); eenIdx++)
155     {
156         bool isSupported = false;
157         for (size_t epIdx = 0; epIdx < vkExtensionPropertiesList.size();
158              epIdx++)
159         {
160             if (!strcmp(enabledExtensionNameList[eenIdx],
161                         vkExtensionPropertiesList[epIdx].extensionName))
162             {
163                 isSupported = true;
164                 break;
165             }
166         }
167         if (!isSupported)
168         {
169             return;
170         }
171     }
172 
173     VkInstanceCreateInfo vkInstanceCreateInfo = {};
174     vkInstanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
175     vkInstanceCreateInfo.pNext = NULL;
176     vkInstanceCreateInfo.flags = 0;
177     vkInstanceCreateInfo.pApplicationInfo = &vkApplicationInfo;
178     vkInstanceCreateInfo.enabledLayerCount = 0;
179     vkInstanceCreateInfo.ppEnabledLayerNames = NULL;
180     vkInstanceCreateInfo.enabledExtensionCount =
181         (uint32_t)enabledExtensionNameList.size();
182     vkInstanceCreateInfo.ppEnabledExtensionNames =
183         enabledExtensionNameList.data();
184 
185     vkCreateInstance(&vkInstanceCreateInfo, NULL, &m_vkInstance);
186 
187 #define VK_FUNC_DECL(name)                                                     \
188     _##name = (PFN_##name)vkGetInstanceProcAddr(m_vkInstance, #name);          \
189     // ASSERT_NEQ((unsigned long long)name, 0ULL) << "Couldn't obtain address
190     // for function" << #name;
191 
192     VK_FUNC_LIST
193 #if defined(_WIN32) || defined(_WIN64)
194     VK_WINDOWS_FUNC_LIST
195 #endif
196 #undef VK_FUNC_DECL
197 
198     uint32_t physicalDeviceCount = 0;
199     vkEnumeratePhysicalDevices(m_vkInstance, &physicalDeviceCount, NULL);
200     // CHECK_NEQ(physicalDeviceCount, uint32_t(0));
201 
202     if (physicalDeviceCount == uint32_t(0))
203     {
204         std::cout << "failed to find GPUs with Vulkan support!\n";
205         return;
206     }
207 
208     std::vector<VkPhysicalDevice> vkPhysicalDeviceList(physicalDeviceCount,
209                                                        VK_NULL_HANDLE);
210     vkEnumeratePhysicalDevices(m_vkInstance, &physicalDeviceCount,
211                                vkPhysicalDeviceList.data());
212 
213     for (size_t ppdIdx = 0; ppdIdx < vkPhysicalDeviceList.size(); ppdIdx++)
214     {
215         VulkanPhysicalDevice *physicalDevice =
216             new VulkanPhysicalDevice(vkPhysicalDeviceList[ppdIdx]);
217         m_physicalDeviceList.add(*physicalDevice);
218     }
219 }
220 
~VulkanInstance()221 VulkanInstance::~VulkanInstance()
222 {
223     for (size_t pdIdx = 0; pdIdx < m_physicalDeviceList.size(); pdIdx++)
224     {
225         const VulkanPhysicalDevice &physicalDevice =
226             m_physicalDeviceList[pdIdx];
227         delete &physicalDevice;
228     }
229     if (m_vkInstance)
230     {
231         vkDestroyInstance(m_vkInstance, NULL);
232     }
233 }
234 
getPhysicalDeviceList() const235 const VulkanPhysicalDeviceList &VulkanInstance::getPhysicalDeviceList() const
236 {
237     return m_physicalDeviceList;
238 }
239 
operator VkInstance() const240 VulkanInstance::operator VkInstance() const { return m_vkInstance; }
241 
242 /////////////////////////////////////////
243 // VulkanPhysicalDevice implementation //
244 /////////////////////////////////////////
245 
VulkanPhysicalDevice(const VulkanPhysicalDevice & physicalDevice)246 VulkanPhysicalDevice::VulkanPhysicalDevice(
247     const VulkanPhysicalDevice &physicalDevice)
248     : m_vkPhysicalDevice(physicalDevice.m_vkPhysicalDevice),
249       m_vkPhysicalDeviceProperties(physicalDevice.m_vkPhysicalDeviceProperties),
250       m_vkDeviceNodeMask(physicalDevice.m_vkDeviceNodeMask),
251       m_vkPhysicalDeviceFeatures(physicalDevice.m_vkPhysicalDeviceFeatures),
252       m_vkPhysicalDeviceMemoryProperties(
253           physicalDevice.m_vkPhysicalDeviceMemoryProperties),
254       m_queueFamilyList(physicalDevice.m_queueFamilyList)
255 {
256     memcpy(m_vkDeviceUUID, physicalDevice.m_vkDeviceUUID, VK_UUID_SIZE);
257 }
258 
VulkanPhysicalDevice(VkPhysicalDevice vkPhysicalDevice)259 VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkPhysicalDevice)
260     : m_vkPhysicalDevice(vkPhysicalDevice)
261 {
262     if (m_vkPhysicalDevice == (VkPhysicalDevice)VK_NULL_HANDLE)
263     {
264         throw std::runtime_error("failed to find a suitable GPU!");
265     }
266 
267     vkGetPhysicalDeviceProperties(m_vkPhysicalDevice,
268                                   &m_vkPhysicalDeviceProperties);
269     vkGetPhysicalDeviceFeatures(m_vkPhysicalDevice,
270                                 &m_vkPhysicalDeviceFeatures);
271 
272     VkPhysicalDeviceIDPropertiesKHR vkPhysicalDeviceIDPropertiesKHR = {};
273     vkPhysicalDeviceIDPropertiesKHR.sType =
274         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR;
275     vkPhysicalDeviceIDPropertiesKHR.pNext = NULL;
276 
277     VkPhysicalDeviceProperties2KHR vkPhysicalDeviceProperties2KHR = {};
278     vkPhysicalDeviceProperties2KHR.sType =
279         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
280     vkPhysicalDeviceProperties2KHR.pNext = &vkPhysicalDeviceIDPropertiesKHR;
281 
282     vkGetPhysicalDeviceProperties2KHR(m_vkPhysicalDevice,
283                                       &vkPhysicalDeviceProperties2KHR);
284 
285     memcpy(m_vkDeviceUUID, vkPhysicalDeviceIDPropertiesKHR.deviceUUID,
286            sizeof(m_vkDeviceUUID));
287     memcpy(m_vkDeviceLUID, vkPhysicalDeviceIDPropertiesKHR.deviceLUID,
288            sizeof(m_vkDeviceLUID));
289     m_vkDeviceNodeMask = vkPhysicalDeviceIDPropertiesKHR.deviceNodeMask;
290 
291     uint32_t queueFamilyCount = 0;
292     vkGetPhysicalDeviceQueueFamilyProperties(m_vkPhysicalDevice,
293                                              &queueFamilyCount, NULL);
294 
295     std::vector<VkQueueFamilyProperties> vkQueueFamilyPropertiesList(
296         queueFamilyCount);
297     vkGetPhysicalDeviceQueueFamilyProperties(
298         m_vkPhysicalDevice, &queueFamilyCount,
299         vkQueueFamilyPropertiesList.data());
300 
301     for (size_t qfpIdx = 0; qfpIdx < vkQueueFamilyPropertiesList.size();
302          qfpIdx++)
303     {
304         VulkanQueueFamily *queueFamily = new VulkanQueueFamily(
305             uint32_t(qfpIdx), vkQueueFamilyPropertiesList[qfpIdx]);
306         m_queueFamilyList.add(*queueFamily);
307     }
308 
309     vkGetPhysicalDeviceMemoryProperties(m_vkPhysicalDevice,
310                                         &m_vkPhysicalDeviceMemoryProperties);
311 
312     for (uint32_t mhIdx = 0;
313          mhIdx < m_vkPhysicalDeviceMemoryProperties.memoryHeapCount; mhIdx++)
314     {
315         VulkanMemoryHeap *memoryHeap = new VulkanMemoryHeap(
316             mhIdx, m_vkPhysicalDeviceMemoryProperties.memoryHeaps[mhIdx].size,
317             (VulkanMemoryHeapFlag)m_vkPhysicalDeviceMemoryProperties
318                 .memoryHeaps[mhIdx]
319                 .flags);
320         m_memoryHeapList.add(*memoryHeap);
321     }
322 
323     for (uint32_t mtIdx = 0;
324          mtIdx < m_vkPhysicalDeviceMemoryProperties.memoryTypeCount; mtIdx++)
325     {
326         const VulkanMemoryHeap &memoryHeap = m_memoryHeapList
327             [m_vkPhysicalDeviceMemoryProperties.memoryTypes[mtIdx].heapIndex];
328         VulkanMemoryType *memoryType = new VulkanMemoryType(
329             mtIdx,
330             (VulkanMemoryTypeProperty)m_vkPhysicalDeviceMemoryProperties
331                 .memoryTypes[mtIdx]
332                 .propertyFlags,
333             memoryHeap);
334         m_memoryTypeList.add(*memoryType);
335     }
336 }
337 
~VulkanPhysicalDevice()338 VulkanPhysicalDevice::~VulkanPhysicalDevice()
339 {
340     for (size_t mtIdx = 0; mtIdx < m_memoryTypeList.size(); mtIdx++)
341     {
342         const VulkanMemoryType &memoryType = m_memoryTypeList[mtIdx];
343         delete &memoryType;
344     }
345 
346     for (size_t mhIdx = 0; mhIdx < m_memoryHeapList.size(); mhIdx++)
347     {
348         const VulkanMemoryHeap &memoryHeap = m_memoryHeapList[mhIdx];
349         delete &memoryHeap;
350     }
351 
352     for (size_t qfIdx = 0; qfIdx < m_queueFamilyList.size(); qfIdx++)
353     {
354         const VulkanQueueFamily &queueFamily = m_queueFamilyList[qfIdx];
355         delete &queueFamily;
356     }
357 }
358 
359 
getQueueFamilyList() const360 const VulkanQueueFamilyList &VulkanPhysicalDevice::getQueueFamilyList() const
361 {
362     return m_queueFamilyList;
363 }
364 
getMemoryHeapList() const365 const VulkanMemoryHeapList &VulkanPhysicalDevice::getMemoryHeapList() const
366 {
367     return m_memoryHeapList;
368 }
369 
getMemoryTypeList() const370 const VulkanMemoryTypeList &VulkanPhysicalDevice::getMemoryTypeList() const
371 {
372     return m_memoryTypeList;
373 }
374 
getUUID() const375 const uint8_t *VulkanPhysicalDevice::getUUID() const { return m_vkDeviceUUID; }
376 
getLUID() const377 const uint8_t *VulkanPhysicalDevice::getLUID() const { return m_vkDeviceLUID; }
378 
getNodeMask() const379 uint32_t VulkanPhysicalDevice::getNodeMask() const
380 {
381     return m_vkDeviceNodeMask;
382 }
383 
operator VkPhysicalDevice() const384 VulkanPhysicalDevice::operator VkPhysicalDevice() const
385 {
386     return m_vkPhysicalDevice;
387 }
388 
operator <(const VulkanQueueFamily & queueFamilyA,const VulkanQueueFamily & queueFamilyB)389 bool operator<(const VulkanQueueFamily &queueFamilyA,
390                const VulkanQueueFamily &queueFamilyB)
391 {
392     return (uint32_t)queueFamilyA < (uint32_t)queueFamilyB;
393 }
394 
395 /////////////////////////////////////
396 // VulkanMemoryHeap implementation //
397 /////////////////////////////////////
398 
VulkanMemoryHeap(const VulkanMemoryHeap & memoryHeap)399 VulkanMemoryHeap::VulkanMemoryHeap(const VulkanMemoryHeap &memoryHeap)
400     : m_memoryHeapIndex(memoryHeap.m_memoryHeapIndex),
401       m_size(memoryHeap.m_size), m_memoryHeapFlag(memoryHeap.m_memoryHeapFlag)
402 {}
403 
VulkanMemoryHeap(uint32_t memoryHeapIndex,uint64_t size,VulkanMemoryHeapFlag memoryHeapFlag)404 VulkanMemoryHeap::VulkanMemoryHeap(uint32_t memoryHeapIndex, uint64_t size,
405                                    VulkanMemoryHeapFlag memoryHeapFlag)
406     : m_memoryHeapIndex(memoryHeapIndex), m_size(size),
407       m_memoryHeapFlag(memoryHeapFlag)
408 {}
409 
~VulkanMemoryHeap()410 VulkanMemoryHeap::~VulkanMemoryHeap() {}
411 
getSize() const412 uint64_t VulkanMemoryHeap::getSize() const { return m_size; }
413 
414 
getMemoryHeapFlag() const415 VulkanMemoryHeapFlag VulkanMemoryHeap::getMemoryHeapFlag() const
416 {
417     return m_memoryHeapFlag;
418 }
419 
operator uint32_t() const420 VulkanMemoryHeap::operator uint32_t() const { return m_memoryHeapIndex; }
421 
422 /////////////////////////////////////
423 // VulkanMemoryType implementation //
424 /////////////////////////////////////
425 
VulkanMemoryType(const VulkanMemoryType & memoryType)426 VulkanMemoryType::VulkanMemoryType(const VulkanMemoryType &memoryType)
427     : m_memoryTypeIndex(memoryType.m_memoryTypeIndex),
428       m_memoryTypeProperty(memoryType.m_memoryTypeProperty),
429       m_memoryHeap(memoryType.m_memoryHeap)
430 {}
431 
VulkanMemoryType(uint32_t memoryTypeIndex,VulkanMemoryTypeProperty memoryTypeProperty,const VulkanMemoryHeap & memoryHeap)432 VulkanMemoryType::VulkanMemoryType(uint32_t memoryTypeIndex,
433                                    VulkanMemoryTypeProperty memoryTypeProperty,
434                                    const VulkanMemoryHeap &memoryHeap)
435     : m_memoryTypeIndex(memoryTypeIndex),
436       m_memoryTypeProperty(memoryTypeProperty), m_memoryHeap(memoryHeap)
437 {}
438 
~VulkanMemoryType()439 VulkanMemoryType::~VulkanMemoryType() {}
440 
getMemoryTypeProperty() const441 VulkanMemoryTypeProperty VulkanMemoryType::getMemoryTypeProperty() const
442 {
443     return m_memoryTypeProperty;
444 }
445 
getMemoryHeap() const446 const VulkanMemoryHeap &VulkanMemoryType::getMemoryHeap() const
447 {
448     return m_memoryHeap;
449 }
450 
operator uint32_t() const451 VulkanMemoryType::operator uint32_t() const { return m_memoryTypeIndex; }
452 
453 //////////////////////////////////////
454 // VulkanQueueFamily implementation //
455 //////////////////////////////////////
456 
VulkanQueueFamily(const VulkanQueueFamily & queueFamily)457 VulkanQueueFamily::VulkanQueueFamily(const VulkanQueueFamily &queueFamily)
458     : m_queueFamilyIndex(queueFamily.m_queueFamilyIndex),
459       m_vkQueueFamilyProperties(queueFamily.m_vkQueueFamilyProperties)
460 {}
461 
VulkanQueueFamily(uint32_t queueFamilyIndex,VkQueueFamilyProperties vkQueueFamilyProperties)462 VulkanQueueFamily::VulkanQueueFamily(
463     uint32_t queueFamilyIndex, VkQueueFamilyProperties vkQueueFamilyProperties)
464     : m_queueFamilyIndex(queueFamilyIndex),
465       m_vkQueueFamilyProperties(vkQueueFamilyProperties)
466 {}
467 
~VulkanQueueFamily()468 VulkanQueueFamily::~VulkanQueueFamily() {}
469 
getQueueFlags() const470 uint32_t VulkanQueueFamily::getQueueFlags() const
471 {
472     return m_vkQueueFamilyProperties.queueFlags
473         & (uint32_t)VULKAN_QUEUE_FLAG_MASK_ALL;
474 }
475 
getQueueCount() const476 uint32_t VulkanQueueFamily::getQueueCount() const
477 {
478     return m_vkQueueFamilyProperties.queueCount;
479 }
480 
operator uint32_t() const481 VulkanQueueFamily::operator uint32_t() const { return m_queueFamilyIndex; }
482 
483 /////////////////////////////////
484 // VulkanDevice implementation //
485 /////////////////////////////////
486 
VulkanDevice(const VulkanDevice & device)487 VulkanDevice::VulkanDevice(const VulkanDevice &device)
488     : m_physicalDevice(device.m_physicalDevice), m_vkDevice(device.m_vkDevice)
489 {}
490 
VulkanDevice(const VulkanPhysicalDevice & physicalDevice,const VulkanQueueFamilyToQueueCountMap & queueFamilyToQueueCountMap)491 VulkanDevice::VulkanDevice(
492     const VulkanPhysicalDevice &physicalDevice,
493     const VulkanQueueFamilyToQueueCountMap &queueFamilyToQueueCountMap)
494     : m_physicalDevice(physicalDevice), m_vkDevice(NULL)
495 {
496     uint32_t maxQueueCount = 0;
497     for (uint32_t qfIdx = 0;
498          qfIdx < (uint32_t)physicalDevice.getQueueFamilyList().size(); qfIdx++)
499     {
500         maxQueueCount =
501             std::max(maxQueueCount, queueFamilyToQueueCountMap[qfIdx]);
502     }
503 
504     std::vector<VkDeviceQueueCreateInfo> vkDeviceQueueCreateInfoList;
505     std::vector<float> queuePriorities(maxQueueCount);
506     for (uint32_t qfIdx = 0;
507          qfIdx < (uint32_t)physicalDevice.getQueueFamilyList().size(); qfIdx++)
508     {
509         if (queueFamilyToQueueCountMap[qfIdx])
510         {
511             VkDeviceQueueCreateInfo vkDeviceQueueCreateInfo = {};
512             vkDeviceQueueCreateInfo.sType =
513                 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
514             vkDeviceQueueCreateInfo.pNext = NULL;
515             vkDeviceQueueCreateInfo.flags = 0;
516             vkDeviceQueueCreateInfo.queueFamilyIndex = qfIdx;
517             vkDeviceQueueCreateInfo.queueCount =
518                 queueFamilyToQueueCountMap[qfIdx];
519             vkDeviceQueueCreateInfo.pQueuePriorities = queuePriorities.data();
520 
521             vkDeviceQueueCreateInfoList.push_back(vkDeviceQueueCreateInfo);
522         }
523     }
524 
525     std::vector<const char *> enabledExtensionNameList;
526     enabledExtensionNameList.push_back(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME);
527     enabledExtensionNameList.push_back(
528         VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME);
529 #if defined(_WIN32) || defined(_WIN64)
530     enabledExtensionNameList.push_back(
531         VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME);
532     enabledExtensionNameList.push_back(
533         VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME);
534 #else
535     enabledExtensionNameList.push_back(
536         VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME);
537     enabledExtensionNameList.push_back(
538         VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME);
539 #endif
540 
541 
542     VkDeviceCreateInfo vkDeviceCreateInfo = {};
543     vkDeviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
544     vkDeviceCreateInfo.pNext = NULL;
545     vkDeviceCreateInfo.flags = 0;
546     vkDeviceCreateInfo.queueCreateInfoCount =
547         (uint32_t)vkDeviceQueueCreateInfoList.size();
548     vkDeviceCreateInfo.pQueueCreateInfos = vkDeviceQueueCreateInfoList.data();
549     vkDeviceCreateInfo.enabledLayerCount = 0;
550     vkDeviceCreateInfo.ppEnabledLayerNames = NULL;
551     vkDeviceCreateInfo.enabledExtensionCount =
552         (uint32_t)enabledExtensionNameList.size();
553     vkDeviceCreateInfo.ppEnabledExtensionNames =
554         enabledExtensionNameList.data();
555     vkDeviceCreateInfo.pEnabledFeatures = NULL;
556 
557     vkCreateDevice(physicalDevice, &vkDeviceCreateInfo, NULL, &m_vkDevice);
558 
559     for (uint32_t qfIdx = 0;
560          qfIdx < (uint32_t)m_physicalDevice.getQueueFamilyList().size();
561          qfIdx++)
562     {
563         VulkanQueueList *queueList = new VulkanQueueList();
564         m_queueFamilyIndexToQueueListMap.insert(qfIdx, *queueList);
565         for (uint32_t qIdx = 0; qIdx < queueFamilyToQueueCountMap[qfIdx];
566              qIdx++)
567         {
568             VkQueue vkQueue;
569             vkGetDeviceQueue(m_vkDevice, qfIdx, qIdx, &vkQueue);
570             VulkanQueue *queue = new VulkanQueue(vkQueue);
571             m_queueFamilyIndexToQueueListMap[qfIdx].add(*queue);
572         }
573     }
574 }
575 
~VulkanDevice()576 VulkanDevice::~VulkanDevice()
577 {
578     for (uint32_t qfIdx = 0;
579          qfIdx < (uint32_t)m_physicalDevice.getQueueFamilyList().size();
580          qfIdx++)
581     {
582         for (size_t qIdx = 0;
583              qIdx < m_queueFamilyIndexToQueueListMap[qfIdx].size(); qIdx++)
584         {
585             VulkanQueue &queue = m_queueFamilyIndexToQueueListMap[qfIdx][qIdx];
586             delete &queue;
587         }
588         VulkanQueueList &queueList = m_queueFamilyIndexToQueueListMap[qfIdx];
589         delete &queueList;
590     }
591     vkDestroyDevice(m_vkDevice, NULL);
592 }
593 
getPhysicalDevice() const594 const VulkanPhysicalDevice &VulkanDevice::getPhysicalDevice() const
595 {
596     return m_physicalDevice;
597 }
598 
getQueue(const VulkanQueueFamily & queueFamily,uint32_t queueIndex)599 VulkanQueue &VulkanDevice::getQueue(const VulkanQueueFamily &queueFamily,
600                                     uint32_t queueIndex)
601 {
602     return m_queueFamilyIndexToQueueListMap[queueFamily][queueIndex];
603 }
604 
operator VkDevice() const605 VulkanDevice::operator VkDevice() const { return m_vkDevice; }
606 
607 ////////////////////////////////
608 // VulkanQueue implementation //
609 ////////////////////////////////
610 
VulkanQueue(const VulkanQueue & queue)611 VulkanQueue::VulkanQueue(const VulkanQueue &queue): m_vkQueue(queue.m_vkQueue)
612 {}
613 
VulkanQueue(VkQueue vkQueue)614 VulkanQueue::VulkanQueue(VkQueue vkQueue): m_vkQueue(vkQueue) {}
615 
~VulkanQueue()616 VulkanQueue::~VulkanQueue() {}
617 
submit(const VulkanSemaphoreList & waitSemaphoreList,const VulkanCommandBufferList & commandBufferList,const VulkanSemaphoreList & signalSemaphoreList)618 void VulkanQueue::submit(const VulkanSemaphoreList &waitSemaphoreList,
619                          const VulkanCommandBufferList &commandBufferList,
620                          const VulkanSemaphoreList &signalSemaphoreList)
621 {
622     std::vector<VkPipelineStageFlags> vkPipelineStageFlagsList(
623         waitSemaphoreList.size(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
624 
625     VkSubmitInfo vkSubmitInfo = {};
626     vkSubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
627     vkSubmitInfo.pNext = NULL;
628     vkSubmitInfo.waitSemaphoreCount = (uint32_t)waitSemaphoreList.size();
629     vkSubmitInfo.pWaitSemaphores = waitSemaphoreList();
630     vkSubmitInfo.pWaitDstStageMask = vkPipelineStageFlagsList.data();
631     vkSubmitInfo.commandBufferCount = (uint32_t)commandBufferList.size();
632     vkSubmitInfo.pCommandBuffers = commandBufferList();
633     vkSubmitInfo.signalSemaphoreCount = (uint32_t)signalSemaphoreList.size();
634     vkSubmitInfo.pSignalSemaphores = signalSemaphoreList();
635 
636     vkQueueSubmit(m_vkQueue, 1, &vkSubmitInfo, NULL);
637 }
638 
submit(const VulkanSemaphore & waitSemaphore,const VulkanCommandBuffer & commandBuffer,const VulkanSemaphore & signalSemaphore)639 void VulkanQueue::submit(const VulkanSemaphore &waitSemaphore,
640                          const VulkanCommandBuffer &commandBuffer,
641                          const VulkanSemaphore &signalSemaphore)
642 {
643     VulkanSemaphoreList waitSemaphoreList;
644     VulkanCommandBufferList commandBufferList;
645     VulkanSemaphoreList signalSemaphoreList;
646 
647     waitSemaphoreList.add(waitSemaphore);
648     commandBufferList.add(commandBuffer);
649     signalSemaphoreList.add(signalSemaphore);
650 
651     submit(waitSemaphoreList, commandBufferList, signalSemaphoreList);
652 }
653 
submit(const VulkanCommandBuffer & commandBuffer,const VulkanSemaphore & signalSemaphore)654 void VulkanQueue::submit(const VulkanCommandBuffer &commandBuffer,
655                          const VulkanSemaphore &signalSemaphore)
656 {
657     VulkanSemaphoreList waitSemaphoreList;
658     VulkanCommandBufferList commandBufferList;
659     VulkanSemaphoreList signalSemaphoreList;
660 
661     commandBufferList.add(commandBuffer);
662     signalSemaphoreList.add(signalSemaphore);
663 
664     submit(waitSemaphoreList, commandBufferList, signalSemaphoreList);
665 }
666 
submit(const VulkanCommandBuffer & commandBuffer)667 void VulkanQueue::submit(const VulkanCommandBuffer &commandBuffer)
668 {
669     VulkanSemaphoreList waitSemaphoreList;
670     VulkanCommandBufferList commandBufferList;
671     VulkanSemaphoreList signalSemaphoreList;
672 
673     commandBufferList.add(commandBuffer);
674 
675     submit(waitSemaphoreList, commandBufferList, signalSemaphoreList);
676 }
677 
waitIdle()678 void VulkanQueue::waitIdle() { vkQueueWaitIdle(m_vkQueue); }
679 
operator VkQueue() const680 VulkanQueue::operator VkQueue() const { return m_vkQueue; }
681 
682 /////////////////////////////////////////////////////
683 // VulkanDescriptorSetLayoutBinding implementation //
684 /////////////////////////////////////////////////////
685 
VulkanDescriptorSetLayoutBinding(const VulkanDescriptorSetLayoutBinding & descriptorSetLayoutBinding)686 VulkanDescriptorSetLayoutBinding::VulkanDescriptorSetLayoutBinding(
687     const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding)
688     : m_vkDescriptorSetLayoutBinding(
689         descriptorSetLayoutBinding.m_vkDescriptorSetLayoutBinding)
690 {}
691 
VulkanDescriptorSetLayoutBinding(uint32_t binding,VulkanDescriptorType descriptorType,uint32_t descriptorCount,VulkanShaderStage shaderStage)692 VulkanDescriptorSetLayoutBinding::VulkanDescriptorSetLayoutBinding(
693     uint32_t binding, VulkanDescriptorType descriptorType,
694     uint32_t descriptorCount, VulkanShaderStage shaderStage)
695 {
696     m_vkDescriptorSetLayoutBinding.binding = binding;
697     m_vkDescriptorSetLayoutBinding.descriptorType =
698         (VkDescriptorType)descriptorType;
699     m_vkDescriptorSetLayoutBinding.descriptorCount = descriptorCount;
700     m_vkDescriptorSetLayoutBinding.stageFlags =
701         (VkShaderStageFlags)(VkShaderStageFlagBits)shaderStage;
702     m_vkDescriptorSetLayoutBinding.pImmutableSamplers = NULL;
703 }
704 
~VulkanDescriptorSetLayoutBinding()705 VulkanDescriptorSetLayoutBinding::~VulkanDescriptorSetLayoutBinding() {}
706 
operator VkDescriptorSetLayoutBinding() const707 VulkanDescriptorSetLayoutBinding::operator VkDescriptorSetLayoutBinding() const
708 {
709     return m_vkDescriptorSetLayoutBinding;
710 }
711 
712 //////////////////////////////////////////////
713 // VulkanDescriptorSetLayout implementation //
714 //////////////////////////////////////////////
715 
VulkanDescriptorSetLayout(const VulkanDescriptorSetLayout & descriptorSetLayout)716 VulkanDescriptorSetLayout::VulkanDescriptorSetLayout(
717     const VulkanDescriptorSetLayout &descriptorSetLayout)
718     : m_device(descriptorSetLayout.m_device),
719       m_vkDescriptorSetLayout(descriptorSetLayout.m_vkDescriptorSetLayout)
720 {}
721 
VulkanDescriptorSetLayoutCommon(const VulkanDescriptorSetLayoutBindingList & descriptorSetLayoutBindingList)722 void VulkanDescriptorSetLayout::VulkanDescriptorSetLayoutCommon(
723     const VulkanDescriptorSetLayoutBindingList &descriptorSetLayoutBindingList)
724 {
725     VkDescriptorSetLayoutCreateInfo vkDescriptorSetLayoutCreateInfo = {};
726     vkDescriptorSetLayoutCreateInfo.sType =
727         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
728     vkDescriptorSetLayoutCreateInfo.pNext = NULL;
729     vkDescriptorSetLayoutCreateInfo.flags = 0;
730     vkDescriptorSetLayoutCreateInfo.bindingCount =
731         (uint32_t)descriptorSetLayoutBindingList.size();
732     vkDescriptorSetLayoutCreateInfo.pBindings =
733         descriptorSetLayoutBindingList();
734 
735     vkCreateDescriptorSetLayout(m_device, &vkDescriptorSetLayoutCreateInfo,
736                                 NULL, &m_vkDescriptorSetLayout);
737 }
738 
VulkanDescriptorSetLayout(const VulkanDevice & device,const VulkanDescriptorSetLayoutBinding & descriptorSetLayoutBinding)739 VulkanDescriptorSetLayout::VulkanDescriptorSetLayout(
740     const VulkanDevice &device,
741     const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding)
742     : m_device(device), m_vkDescriptorSetLayout(VK_NULL_HANDLE)
743 {
744     VulkanDescriptorSetLayoutBindingList descriptorSetLayoutBindingList;
745     descriptorSetLayoutBindingList.add(descriptorSetLayoutBinding);
746 
747     VulkanDescriptorSetLayoutCommon(descriptorSetLayoutBindingList);
748 }
749 
VulkanDescriptorSetLayout(const VulkanDevice & device,const VulkanDescriptorSetLayoutBinding & descriptorSetLayoutBinding0,const VulkanDescriptorSetLayoutBinding & descriptorSetLayoutBinding1)750 VulkanDescriptorSetLayout::VulkanDescriptorSetLayout(
751     const VulkanDevice &device,
752     const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding0,
753     const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding1)
754     : m_device(device), m_vkDescriptorSetLayout(VK_NULL_HANDLE)
755 {
756     VulkanDescriptorSetLayoutBindingList descriptorSetLayoutBindingList;
757     descriptorSetLayoutBindingList.add(descriptorSetLayoutBinding0);
758     descriptorSetLayoutBindingList.add(descriptorSetLayoutBinding1);
759 
760     VulkanDescriptorSetLayoutCommon(descriptorSetLayoutBindingList);
761 }
762 
VulkanDescriptorSetLayout(const VulkanDevice & device,const VulkanDescriptorSetLayoutBindingList & descriptorSetLayoutBindingList)763 VulkanDescriptorSetLayout::VulkanDescriptorSetLayout(
764     const VulkanDevice &device,
765     const VulkanDescriptorSetLayoutBindingList &descriptorSetLayoutBindingList)
766     : m_device(device), m_vkDescriptorSetLayout(VK_NULL_HANDLE)
767 {
768     VulkanDescriptorSetLayoutCommon(descriptorSetLayoutBindingList);
769 }
770 
~VulkanDescriptorSetLayout()771 VulkanDescriptorSetLayout::~VulkanDescriptorSetLayout()
772 {
773     if (m_vkDescriptorSetLayout != VK_NULL_HANDLE)
774     {
775         vkDestroyDescriptorSetLayout(m_device, m_vkDescriptorSetLayout, NULL);
776     }
777 }
778 
operator VkDescriptorSetLayout() const779 VulkanDescriptorSetLayout::operator VkDescriptorSetLayout() const
780 {
781     return m_vkDescriptorSetLayout;
782 }
783 
784 /////////////////////////////////////////
785 // VulkanPipelineLayout implementation //
786 /////////////////////////////////////////
787 
VulkanPipelineLayout(const VulkanPipelineLayout & pipelineLayout)788 VulkanPipelineLayout::VulkanPipelineLayout(
789     const VulkanPipelineLayout &pipelineLayout)
790     : m_device(pipelineLayout.m_device),
791       m_vkPipelineLayout(pipelineLayout.m_vkPipelineLayout)
792 {}
793 
VulkanPipelineLayoutCommon(const VulkanDescriptorSetLayoutList & descriptorSetLayoutList)794 void VulkanPipelineLayout::VulkanPipelineLayoutCommon(
795     const VulkanDescriptorSetLayoutList &descriptorSetLayoutList)
796 {
797     VkPipelineLayoutCreateInfo vkPipelineLayoutCreateInfo = {};
798     vkPipelineLayoutCreateInfo.sType =
799         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
800     vkPipelineLayoutCreateInfo.pNext = NULL;
801     vkPipelineLayoutCreateInfo.flags = 0;
802     vkPipelineLayoutCreateInfo.setLayoutCount =
803         (uint32_t)descriptorSetLayoutList.size();
804     vkPipelineLayoutCreateInfo.pSetLayouts = descriptorSetLayoutList();
805     vkPipelineLayoutCreateInfo.pushConstantRangeCount = 0;
806     vkPipelineLayoutCreateInfo.pPushConstantRanges = NULL;
807 
808     vkCreatePipelineLayout(m_device, &vkPipelineLayoutCreateInfo, NULL,
809                            &m_vkPipelineLayout);
810 }
811 
VulkanPipelineLayout(const VulkanDevice & device,const VulkanDescriptorSetLayout & descriptorSetLayout)812 VulkanPipelineLayout::VulkanPipelineLayout(
813     const VulkanDevice &device,
814     const VulkanDescriptorSetLayout &descriptorSetLayout)
815     : m_device(device), m_vkPipelineLayout(VK_NULL_HANDLE)
816 {
817     VulkanDescriptorSetLayoutList descriptorSetLayoutList;
818     descriptorSetLayoutList.add(descriptorSetLayout);
819 
820     VulkanPipelineLayoutCommon(descriptorSetLayoutList);
821 }
822 
VulkanPipelineLayout(const VulkanDevice & device,const VulkanDescriptorSetLayoutList & descriptorSetLayoutList)823 VulkanPipelineLayout::VulkanPipelineLayout(
824     const VulkanDevice &device,
825     const VulkanDescriptorSetLayoutList &descriptorSetLayoutList)
826     : m_device(device), m_vkPipelineLayout(VK_NULL_HANDLE)
827 {
828     VulkanPipelineLayoutCommon(descriptorSetLayoutList);
829 }
830 
~VulkanPipelineLayout()831 VulkanPipelineLayout::~VulkanPipelineLayout()
832 {
833     vkDestroyPipelineLayout(m_device, m_vkPipelineLayout, NULL);
834 }
835 
operator VkPipelineLayout() const836 VulkanPipelineLayout::operator VkPipelineLayout() const
837 {
838     return m_vkPipelineLayout;
839 }
840 
841 ///////////////////////////////////////
842 // VulkanShaderModule implementation //
843 ///////////////////////////////////////
844 
VulkanShaderModule(const VulkanShaderModule & shaderModule)845 VulkanShaderModule::VulkanShaderModule(const VulkanShaderModule &shaderModule)
846     : m_device(shaderModule.m_device),
847       m_vkShaderModule(shaderModule.m_vkShaderModule)
848 {}
849 
VulkanShaderModule(const VulkanDevice & device,const std::vector<char> & code)850 VulkanShaderModule::VulkanShaderModule(const VulkanDevice &device,
851                                        const std::vector<char> &code)
852     : m_device(device)
853 {
854 
855     VkShaderModuleCreateInfo vkShaderModuleCreateInfo = {};
856     vkShaderModuleCreateInfo.sType =
857         VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
858     vkShaderModuleCreateInfo.pNext = NULL;
859     vkShaderModuleCreateInfo.flags = 0;
860     vkShaderModuleCreateInfo.codeSize = code.size();
861     vkShaderModuleCreateInfo.pCode =
862         reinterpret_cast<const uint32_t *>(code.data());
863 
864     vkCreateShaderModule(m_device, &vkShaderModuleCreateInfo, NULL,
865                          &m_vkShaderModule);
866 }
867 
~VulkanShaderModule()868 VulkanShaderModule::~VulkanShaderModule()
869 {
870     vkDestroyShaderModule(m_device, m_vkShaderModule, NULL);
871 }
872 
operator VkShaderModule() const873 VulkanShaderModule::operator VkShaderModule() const { return m_vkShaderModule; }
874 
875 ///////////////////////////////////
876 // VulkanPipeline implementation //
877 ///////////////////////////////////
878 
VulkanPipeline(const VulkanPipeline & pipeline)879 VulkanPipeline::VulkanPipeline(const VulkanPipeline &pipeline)
880     : m_device(pipeline.m_device), m_vkPipeline(pipeline.m_vkPipeline)
881 {}
882 
VulkanPipeline(const VulkanDevice & device)883 VulkanPipeline::VulkanPipeline(const VulkanDevice &device)
884     : m_device(device), m_vkPipeline(VK_NULL_HANDLE)
885 {}
886 
~VulkanPipeline()887 VulkanPipeline::~VulkanPipeline()
888 {
889     vkDestroyPipeline(m_device, m_vkPipeline, NULL);
890 }
891 
operator VkPipeline() const892 VulkanPipeline::operator VkPipeline() const { return m_vkPipeline; }
893 
894 //////////////////////////////////////////
895 // VulkanComputePipeline implementation //
896 //////////////////////////////////////////
897 
VulkanComputePipeline(const VulkanComputePipeline & computePipeline)898 VulkanComputePipeline::VulkanComputePipeline(
899     const VulkanComputePipeline &computePipeline)
900     : VulkanPipeline(computePipeline)
901 {}
902 
VulkanComputePipeline(const VulkanDevice & device,const VulkanPipelineLayout & pipelineLayout,const VulkanShaderModule & shaderModule,const std::string & entryFuncName)903 VulkanComputePipeline::VulkanComputePipeline(
904     const VulkanDevice &device, const VulkanPipelineLayout &pipelineLayout,
905     const VulkanShaderModule &shaderModule, const std::string &entryFuncName)
906     : VulkanPipeline(device)
907 {
908     VkPipelineShaderStageCreateInfo vkPipelineShaderStageCreateInfo = {};
909     vkPipelineShaderStageCreateInfo.sType =
910         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
911     vkPipelineShaderStageCreateInfo.pNext = NULL;
912     vkPipelineShaderStageCreateInfo.flags = 0;
913     vkPipelineShaderStageCreateInfo.stage = VK_SHADER_STAGE_COMPUTE_BIT;
914     vkPipelineShaderStageCreateInfo.module = shaderModule;
915     vkPipelineShaderStageCreateInfo.pName = entryFuncName.c_str();
916     vkPipelineShaderStageCreateInfo.pSpecializationInfo = NULL;
917 
918     VkComputePipelineCreateInfo vkComputePipelineCreateInfo = {};
919     vkComputePipelineCreateInfo.sType =
920         VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
921     vkComputePipelineCreateInfo.pNext = NULL;
922     vkComputePipelineCreateInfo.flags = 0;
923     vkComputePipelineCreateInfo.stage = vkPipelineShaderStageCreateInfo;
924     vkComputePipelineCreateInfo.layout = pipelineLayout;
925     vkComputePipelineCreateInfo.basePipelineHandle = VK_NULL_HANDLE;
926     vkComputePipelineCreateInfo.basePipelineIndex = 0;
927 
928     vkCreateComputePipelines(device, VK_NULL_HANDLE, 1,
929                              &vkComputePipelineCreateInfo, NULL, &m_vkPipeline);
930 }
931 
~VulkanComputePipeline()932 VulkanComputePipeline::~VulkanComputePipeline() {}
933 
getPipelineBindPoint() const934 VulkanPipelineBindPoint VulkanComputePipeline::getPipelineBindPoint() const
935 {
936     return VULKAN_PIPELINE_BIND_POINT_COMPUTE;
937 }
938 
939 /////////////////////////////////////////
940 // VulkanDescriptorPool implementation //
941 /////////////////////////////////////////
942 
VulkanDescriptorPool(const VulkanDescriptorPool & descriptorPool)943 VulkanDescriptorPool::VulkanDescriptorPool(
944     const VulkanDescriptorPool &descriptorPool)
945     : m_device(descriptorPool.m_device),
946       m_vkDescriptorPool(descriptorPool.m_vkDescriptorPool)
947 {}
948 
VulkanDescriptorPoolCommon(const VulkanDescriptorSetLayoutBindingList & descriptorSetLayoutBindingList)949 void VulkanDescriptorPool::VulkanDescriptorPoolCommon(
950     const VulkanDescriptorSetLayoutBindingList &descriptorSetLayoutBindingList)
951 {
952     if (descriptorSetLayoutBindingList.size())
953     {
954         std::map<VkDescriptorType, uint32_t>
955             vkDescriptorTypeToDescriptorCountMap;
956 
957         for (size_t dslbIdx = 0;
958              dslbIdx < descriptorSetLayoutBindingList.size(); dslbIdx++)
959         {
960             VkDescriptorSetLayoutBinding vkDescriptorSetLayoutBinding =
961                 descriptorSetLayoutBindingList[dslbIdx];
962             if (vkDescriptorTypeToDescriptorCountMap.find(
963                     vkDescriptorSetLayoutBinding.descriptorType)
964                 == vkDescriptorTypeToDescriptorCountMap.end())
965             {
966                 vkDescriptorTypeToDescriptorCountMap
967                     [vkDescriptorSetLayoutBinding.descriptorType] = 1;
968             }
969             else
970             {
971                 vkDescriptorTypeToDescriptorCountMap
972                     [vkDescriptorSetLayoutBinding.descriptorType]++;
973             }
974         }
975 
976         std::vector<VkDescriptorPoolSize> vkDescriptorPoolSizeList;
977         std::map<VkDescriptorType, uint32_t>::iterator dtdcIt;
978         for (dtdcIt = vkDescriptorTypeToDescriptorCountMap.begin();
979              dtdcIt != vkDescriptorTypeToDescriptorCountMap.end(); ++dtdcIt)
980         {
981             VkDescriptorPoolSize vkDescriptorPoolSize = {};
982             vkDescriptorPoolSize.type = dtdcIt->first;
983             vkDescriptorPoolSize.descriptorCount = dtdcIt->second;
984 
985             vkDescriptorPoolSizeList.push_back(vkDescriptorPoolSize);
986         }
987 
988         VkDescriptorPoolCreateInfo vkDescriptorPoolCreateInfo = {};
989         vkDescriptorPoolCreateInfo.sType =
990             VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
991         vkDescriptorPoolCreateInfo.pNext = NULL;
992         vkDescriptorPoolCreateInfo.flags =
993             VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
994         vkDescriptorPoolCreateInfo.maxSets = 1;
995         vkDescriptorPoolCreateInfo.poolSizeCount =
996             (uint32_t)vkDescriptorPoolSizeList.size();
997         vkDescriptorPoolCreateInfo.pPoolSizes = vkDescriptorPoolSizeList.data();
998 
999         vkCreateDescriptorPool(m_device, &vkDescriptorPoolCreateInfo, NULL,
1000                                &m_vkDescriptorPool);
1001     }
1002 }
1003 
VulkanDescriptorPool(const VulkanDevice & device,const VulkanDescriptorSetLayoutBinding & descriptorSetLayoutBinding)1004 VulkanDescriptorPool::VulkanDescriptorPool(
1005     const VulkanDevice &device,
1006     const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding)
1007     : m_device(device), m_vkDescriptorPool(VK_NULL_HANDLE)
1008 {
1009     VulkanDescriptorSetLayoutBindingList descriptorSetLayoutBindingList;
1010     descriptorSetLayoutBindingList.add(descriptorSetLayoutBinding);
1011 
1012     VulkanDescriptorPoolCommon(descriptorSetLayoutBindingList);
1013 }
1014 
VulkanDescriptorPool(const VulkanDevice & device,const VulkanDescriptorSetLayoutBinding & descriptorSetLayoutBinding0,const VulkanDescriptorSetLayoutBinding & descriptorSetLayoutBinding1)1015 VulkanDescriptorPool::VulkanDescriptorPool(
1016     const VulkanDevice &device,
1017     const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding0,
1018     const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding1)
1019     : m_device(device), m_vkDescriptorPool(VK_NULL_HANDLE)
1020 {
1021     VulkanDescriptorSetLayoutBindingList descriptorSetLayoutBindingList;
1022     descriptorSetLayoutBindingList.add(descriptorSetLayoutBinding0);
1023     descriptorSetLayoutBindingList.add(descriptorSetLayoutBinding1);
1024 
1025     VulkanDescriptorPoolCommon(descriptorSetLayoutBindingList);
1026 }
1027 
VulkanDescriptorPool(const VulkanDevice & device,const VulkanDescriptorSetLayoutBindingList & descriptorSetLayoutBindingList)1028 VulkanDescriptorPool::VulkanDescriptorPool(
1029     const VulkanDevice &device,
1030     const VulkanDescriptorSetLayoutBindingList &descriptorSetLayoutBindingList)
1031     : m_device(device), m_vkDescriptorPool(VK_NULL_HANDLE)
1032 {
1033     VulkanDescriptorPoolCommon(descriptorSetLayoutBindingList);
1034 }
1035 
~VulkanDescriptorPool()1036 VulkanDescriptorPool::~VulkanDescriptorPool()
1037 {
1038     if (m_vkDescriptorPool != VK_NULL_HANDLE)
1039     {
1040         vkDestroyDescriptorPool(m_device, m_vkDescriptorPool, NULL);
1041     }
1042 }
1043 
operator VkDescriptorPool() const1044 VulkanDescriptorPool::operator VkDescriptorPool() const
1045 {
1046     return m_vkDescriptorPool;
1047 }
1048 
1049 ////////////////////////////////////////
1050 // VulkanDescriptorSet implementation //
1051 ////////////////////////////////////////
1052 
VulkanDescriptorSet(const VulkanDescriptorSet & descriptorSet)1053 VulkanDescriptorSet::VulkanDescriptorSet(
1054     const VulkanDescriptorSet &descriptorSet)
1055     : m_device(descriptorSet.m_device),
1056       m_descriptorPool(descriptorSet.m_descriptorPool),
1057       m_vkDescriptorSet(descriptorSet.m_vkDescriptorSet)
1058 {}
1059 
VulkanDescriptorSet(const VulkanDevice & device,const VulkanDescriptorPool & descriptorPool,const VulkanDescriptorSetLayout & descriptorSetLayout)1060 VulkanDescriptorSet::VulkanDescriptorSet(
1061     const VulkanDevice &device, const VulkanDescriptorPool &descriptorPool,
1062     const VulkanDescriptorSetLayout &descriptorSetLayout)
1063     : m_device(device), m_descriptorPool(descriptorPool),
1064       m_vkDescriptorSet(VK_NULL_HANDLE)
1065 {
1066     VkDescriptorSetLayout vkDescriptorSetLayout = descriptorSetLayout;
1067 
1068     if ((VkDescriptorPool)m_descriptorPool)
1069     {
1070         VkDescriptorSetAllocateInfo vkDescriptorSetAllocateInfo = {};
1071         vkDescriptorSetAllocateInfo.sType =
1072             VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
1073         vkDescriptorSetAllocateInfo.pNext = NULL;
1074         vkDescriptorSetAllocateInfo.descriptorPool = descriptorPool;
1075         vkDescriptorSetAllocateInfo.descriptorSetCount = 1;
1076         vkDescriptorSetAllocateInfo.pSetLayouts = &vkDescriptorSetLayout;
1077 
1078         vkAllocateDescriptorSets(m_device, &vkDescriptorSetAllocateInfo,
1079                                  &m_vkDescriptorSet);
1080     }
1081 }
1082 
~VulkanDescriptorSet()1083 VulkanDescriptorSet::~VulkanDescriptorSet()
1084 {
1085     if ((VkDescriptorPool)m_descriptorPool)
1086     {
1087         vkFreeDescriptorSets(m_device, m_descriptorPool, 1, &m_vkDescriptorSet);
1088     }
1089 }
1090 
update(uint32_t binding,const VulkanBuffer & buffer)1091 void VulkanDescriptorSet::update(uint32_t binding, const VulkanBuffer &buffer)
1092 {
1093     VkDescriptorBufferInfo vkDescriptorBufferInfo = {};
1094     vkDescriptorBufferInfo.buffer = buffer;
1095     vkDescriptorBufferInfo.offset = 0;
1096     vkDescriptorBufferInfo.range = VK_WHOLE_SIZE;
1097 
1098     VkWriteDescriptorSet vkWriteDescriptorSet = {};
1099     vkWriteDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1100     vkWriteDescriptorSet.pNext = NULL;
1101     vkWriteDescriptorSet.dstSet = m_vkDescriptorSet;
1102     vkWriteDescriptorSet.dstBinding = binding;
1103     vkWriteDescriptorSet.dstArrayElement = 0;
1104     vkWriteDescriptorSet.descriptorCount = 1;
1105     vkWriteDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1106     vkWriteDescriptorSet.pImageInfo = NULL;
1107     vkWriteDescriptorSet.pBufferInfo = &vkDescriptorBufferInfo;
1108     vkWriteDescriptorSet.pTexelBufferView = NULL;
1109 
1110     vkUpdateDescriptorSets(m_device, 1, &vkWriteDescriptorSet, 0, NULL);
1111 }
1112 
update(uint32_t binding,const VulkanImageView & imageView)1113 void VulkanDescriptorSet::update(uint32_t binding,
1114                                  const VulkanImageView &imageView)
1115 {
1116     VkDescriptorImageInfo vkDescriptorImageInfo = {};
1117     vkDescriptorImageInfo.sampler = VK_NULL_HANDLE;
1118     vkDescriptorImageInfo.imageView = imageView;
1119     vkDescriptorImageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
1120 
1121     VkWriteDescriptorSet vkWriteDescriptorSet = {};
1122     vkWriteDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1123     vkWriteDescriptorSet.pNext = NULL;
1124     vkWriteDescriptorSet.dstSet = m_vkDescriptorSet;
1125     vkWriteDescriptorSet.dstBinding = binding;
1126     vkWriteDescriptorSet.dstArrayElement = 0;
1127     vkWriteDescriptorSet.descriptorCount = 1;
1128     vkWriteDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
1129     vkWriteDescriptorSet.pImageInfo = &vkDescriptorImageInfo;
1130     vkWriteDescriptorSet.pBufferInfo = NULL;
1131     vkWriteDescriptorSet.pTexelBufferView = NULL;
1132 
1133     vkUpdateDescriptorSets(m_device, 1, &vkWriteDescriptorSet, 0, NULL);
1134 }
1135 
operator VkDescriptorSet() const1136 VulkanDescriptorSet::operator VkDescriptorSet() const
1137 {
1138     return m_vkDescriptorSet;
1139 }
1140 
1141 ///////////////////////////////////
1142 // VulkanOffset3D implementation //
1143 ///////////////////////////////////
1144 
VulkanOffset3D(const VulkanOffset3D & offset3D)1145 VulkanOffset3D::VulkanOffset3D(const VulkanOffset3D &offset3D)
1146     : m_vkOffset3D(offset3D.m_vkOffset3D)
1147 {}
1148 
VulkanOffset3D(uint32_t x,uint32_t y,uint32_t z)1149 VulkanOffset3D::VulkanOffset3D(uint32_t x, uint32_t y, uint32_t z)
1150 {
1151     m_vkOffset3D.x = x;
1152     m_vkOffset3D.y = y;
1153     m_vkOffset3D.z = z;
1154 }
1155 
~VulkanOffset3D()1156 VulkanOffset3D::~VulkanOffset3D() {}
1157 
getX() const1158 uint32_t VulkanOffset3D::getX() const { return m_vkOffset3D.x; }
1159 
getY() const1160 uint32_t VulkanOffset3D::getY() const { return m_vkOffset3D.y; }
1161 
getZ() const1162 uint32_t VulkanOffset3D::getZ() const { return m_vkOffset3D.z; }
1163 
operator VkOffset3D() const1164 VulkanOffset3D::operator VkOffset3D() const { return m_vkOffset3D; }
1165 
1166 ///////////////////////////////////
1167 // VulkanExtent3D implementation //
1168 ///////////////////////////////////
1169 
VulkanExtent3D(const VulkanExtent3D & extent3D)1170 VulkanExtent3D::VulkanExtent3D(const VulkanExtent3D &extent3D)
1171     : m_vkExtent3D(extent3D.m_vkExtent3D)
1172 {}
1173 
VulkanExtent3D(uint32_t width,uint32_t height,uint32_t depth)1174 VulkanExtent3D::VulkanExtent3D(uint32_t width, uint32_t height, uint32_t depth)
1175 {
1176     m_vkExtent3D.width = width;
1177     m_vkExtent3D.height = height;
1178     m_vkExtent3D.depth = depth;
1179 }
1180 
~VulkanExtent3D()1181 VulkanExtent3D::~VulkanExtent3D() {}
1182 
getWidth() const1183 uint32_t VulkanExtent3D::getWidth() const { return m_vkExtent3D.width; }
1184 
getHeight() const1185 uint32_t VulkanExtent3D::getHeight() const { return m_vkExtent3D.height; }
1186 
getDepth() const1187 uint32_t VulkanExtent3D::getDepth() const { return m_vkExtent3D.depth; }
1188 
operator VkExtent3D() const1189 VulkanExtent3D::operator VkExtent3D() const { return m_vkExtent3D; }
1190 
1191 //////////////////////////////////////
1192 // VulkanCommandPool implementation //
1193 //////////////////////////////////////
1194 
VulkanCommandPool(const VulkanCommandPool & commandPool)1195 VulkanCommandPool::VulkanCommandPool(const VulkanCommandPool &commandPool)
1196     : m_device(commandPool.m_device),
1197       m_vkCommandPool(commandPool.m_vkCommandPool)
1198 {}
1199 
VulkanCommandPool(const VulkanDevice & device,const VulkanQueueFamily & queueFamily)1200 VulkanCommandPool::VulkanCommandPool(const VulkanDevice &device,
1201                                      const VulkanQueueFamily &queueFamily)
1202     : m_device(device)
1203 {
1204     VkCommandPoolCreateInfo vkCommandPoolCreateInfo = {};
1205     vkCommandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
1206     vkCommandPoolCreateInfo.pNext = NULL;
1207     vkCommandPoolCreateInfo.flags =
1208         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
1209     vkCommandPoolCreateInfo.queueFamilyIndex = queueFamily;
1210 
1211     vkCreateCommandPool(m_device, &vkCommandPoolCreateInfo, NULL,
1212                         &m_vkCommandPool);
1213 }
1214 
~VulkanCommandPool()1215 VulkanCommandPool::~VulkanCommandPool()
1216 {
1217     vkDestroyCommandPool(m_device, m_vkCommandPool, NULL);
1218 }
1219 
operator VkCommandPool() const1220 VulkanCommandPool::operator VkCommandPool() const { return m_vkCommandPool; }
1221 
1222 ////////////////////////////////////////
1223 // VulkanCommandBuffer implementation //
1224 ////////////////////////////////////////
1225 
VulkanCommandBuffer(const VulkanCommandBuffer & commandBuffer)1226 VulkanCommandBuffer::VulkanCommandBuffer(
1227     const VulkanCommandBuffer &commandBuffer)
1228     : m_device(commandBuffer.m_device),
1229       m_commandPool(commandBuffer.m_commandPool),
1230       m_vkCommandBuffer(commandBuffer.m_vkCommandBuffer)
1231 {}
1232 
VulkanCommandBuffer(const VulkanDevice & device,const VulkanCommandPool & commandPool)1233 VulkanCommandBuffer::VulkanCommandBuffer(const VulkanDevice &device,
1234                                          const VulkanCommandPool &commandPool)
1235     : m_device(device), m_commandPool(commandPool)
1236 {
1237     VkCommandBufferAllocateInfo vkCommandBufferAllocateInfo = {};
1238     vkCommandBufferAllocateInfo.sType =
1239         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
1240     vkCommandBufferAllocateInfo.pNext = NULL;
1241     vkCommandBufferAllocateInfo.commandPool = commandPool;
1242     vkCommandBufferAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
1243     vkCommandBufferAllocateInfo.commandBufferCount = 1;
1244 
1245     vkAllocateCommandBuffers(m_device, &vkCommandBufferAllocateInfo,
1246                              &m_vkCommandBuffer);
1247 }
1248 
~VulkanCommandBuffer()1249 VulkanCommandBuffer::~VulkanCommandBuffer()
1250 {
1251     vkFreeCommandBuffers(m_device, m_commandPool, 1, &m_vkCommandBuffer);
1252 }
1253 
begin()1254 void VulkanCommandBuffer::begin()
1255 {
1256     VkCommandBufferBeginInfo vkCommandBufferBeginInfo = {};
1257     vkCommandBufferBeginInfo.sType =
1258         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
1259     vkCommandBufferBeginInfo.pNext = NULL;
1260     vkCommandBufferBeginInfo.flags =
1261         VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
1262     vkCommandBufferBeginInfo.pInheritanceInfo = NULL;
1263 
1264     vkBeginCommandBuffer(m_vkCommandBuffer, &vkCommandBufferBeginInfo);
1265 }
1266 
bindPipeline(const VulkanPipeline & pipeline)1267 void VulkanCommandBuffer::bindPipeline(const VulkanPipeline &pipeline)
1268 {
1269     VkPipelineBindPoint vkPipelineBindPoint =
1270         (VkPipelineBindPoint)pipeline.getPipelineBindPoint();
1271 
1272     vkCmdBindPipeline(m_vkCommandBuffer, vkPipelineBindPoint, pipeline);
1273 }
1274 
bindDescriptorSets(const VulkanPipeline & pipeline,const VulkanPipelineLayout & pipelineLayout,const VulkanDescriptorSet & descriptorSet)1275 void VulkanCommandBuffer::bindDescriptorSets(
1276     const VulkanPipeline &pipeline, const VulkanPipelineLayout &pipelineLayout,
1277     const VulkanDescriptorSet &descriptorSet)
1278 {
1279     VkPipelineBindPoint vkPipelineBindPoint =
1280         (VkPipelineBindPoint)pipeline.getPipelineBindPoint();
1281     VkDescriptorSet vkDescriptorSet = descriptorSet;
1282 
1283     vkCmdBindDescriptorSets(m_vkCommandBuffer, vkPipelineBindPoint,
1284                             pipelineLayout, 0, 1, &vkDescriptorSet, 0, NULL);
1285 }
1286 
pipelineBarrier(const VulkanImage2DList & image2DList,VulkanImageLayout oldImageLayout,VulkanImageLayout newImageLayout)1287 void VulkanCommandBuffer::pipelineBarrier(const VulkanImage2DList &image2DList,
1288                                           VulkanImageLayout oldImageLayout,
1289                                           VulkanImageLayout newImageLayout)
1290 {
1291     std::vector<VkImageMemoryBarrier> vkImageMemoryBarrierList;
1292     for (size_t i2DIdx = 0; i2DIdx < image2DList.size(); i2DIdx++)
1293     {
1294         VkImageSubresourceRange vkImageSubresourceRange = {};
1295         vkImageSubresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1296         vkImageSubresourceRange.baseMipLevel = 0;
1297         vkImageSubresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
1298         vkImageSubresourceRange.baseArrayLayer = 0;
1299         vkImageSubresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
1300 
1301         VkImageMemoryBarrier vkImageMemoryBarrier = {};
1302         vkImageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
1303         vkImageMemoryBarrier.pNext = NULL;
1304         vkImageMemoryBarrier.srcAccessMask = 0;
1305         vkImageMemoryBarrier.dstAccessMask = 0;
1306         vkImageMemoryBarrier.oldLayout = (VkImageLayout)oldImageLayout;
1307         vkImageMemoryBarrier.newLayout = (VkImageLayout)newImageLayout;
1308         vkImageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1309         vkImageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1310         vkImageMemoryBarrier.image = image2DList[i2DIdx];
1311         vkImageMemoryBarrier.subresourceRange = vkImageSubresourceRange;
1312 
1313         vkImageMemoryBarrierList.push_back(vkImageMemoryBarrier);
1314     }
1315 
1316     vkCmdPipelineBarrier(m_vkCommandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
1317                          VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, NULL, 0,
1318                          NULL, (uint32_t)vkImageMemoryBarrierList.size(),
1319                          vkImageMemoryBarrierList.data());
1320 }
1321 
dispatch(uint32_t groupCountX,uint32_t groupCountY,uint32_t groupCountZ)1322 void VulkanCommandBuffer::dispatch(uint32_t groupCountX, uint32_t groupCountY,
1323                                    uint32_t groupCountZ)
1324 {
1325     vkCmdDispatch(m_vkCommandBuffer, groupCountX, groupCountY, groupCountZ);
1326 }
1327 
fillBuffer(const VulkanBuffer & buffer,uint32_t data,uint64_t offset,uint64_t size)1328 void VulkanCommandBuffer::fillBuffer(const VulkanBuffer &buffer, uint32_t data,
1329                                      uint64_t offset, uint64_t size)
1330 {
1331     vkCmdFillBuffer(m_vkCommandBuffer, buffer, offset, size, data);
1332 }
1333 
updateBuffer(const VulkanBuffer & buffer,void * pdata,uint64_t offset,uint64_t size)1334 void VulkanCommandBuffer::updateBuffer(const VulkanBuffer &buffer, void *pdata,
1335                                        uint64_t offset, uint64_t size)
1336 {
1337     vkCmdUpdateBuffer(m_vkCommandBuffer, buffer, offset, size, pdata);
1338 }
1339 
copyBufferToImage(const VulkanBuffer & buffer,const VulkanImage & image,VulkanImageLayout imageLayout)1340 void VulkanCommandBuffer::copyBufferToImage(const VulkanBuffer &buffer,
1341                                             const VulkanImage &image,
1342                                             VulkanImageLayout imageLayout)
1343 {
1344     VkDeviceSize bufferOffset = 0;
1345 
1346     std::vector<VkBufferImageCopy> vkBufferImageCopyList;
1347     for (uint32_t mipLevel = 0; mipLevel < image.getNumMipLevels(); mipLevel++)
1348     {
1349         VulkanExtent3D extent3D = image.getExtent3D(mipLevel);
1350         size_t elementSize = getVulkanFormatElementSize(image.getFormat());
1351 
1352         VkImageSubresourceLayers vkImageSubresourceLayers = {};
1353         vkImageSubresourceLayers.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1354         vkImageSubresourceLayers.mipLevel = mipLevel;
1355         vkImageSubresourceLayers.baseArrayLayer = 0;
1356         vkImageSubresourceLayers.layerCount = image.getNumLayers();
1357 
1358         VkBufferImageCopy vkBufferImageCopy = {};
1359         vkBufferImageCopy.bufferOffset = bufferOffset;
1360         vkBufferImageCopy.bufferRowLength = 0;
1361         vkBufferImageCopy.bufferImageHeight = 0;
1362         vkBufferImageCopy.imageSubresource = vkImageSubresourceLayers;
1363         vkBufferImageCopy.imageOffset = VulkanOffset3D(0, 0, 0);
1364         vkBufferImageCopy.imageExtent = extent3D;
1365 
1366         vkBufferImageCopyList.push_back(vkBufferImageCopy);
1367 
1368         bufferOffset += extent3D.getWidth() * extent3D.getHeight()
1369             * extent3D.getDepth() * elementSize;
1370         bufferOffset =
1371             ROUND_UP(bufferOffset,
1372                      std::max(elementSize,
1373                               (size_t)VULKAN_MIN_BUFFER_OFFSET_COPY_ALIGNMENT));
1374     }
1375 
1376     vkCmdCopyBufferToImage(
1377         m_vkCommandBuffer, buffer, image, (VkImageLayout)imageLayout,
1378         (uint32_t)vkBufferImageCopyList.size(), vkBufferImageCopyList.data());
1379 }
1380 
copyBufferToImage(const VulkanBuffer & buffer,const VulkanImage & image,uint64_t bufferOffset,uint32_t mipLevel,uint32_t baseArrayLayer,uint32_t layerCount,VulkanOffset3D offset3D,VulkanExtent3D extent3D)1381 void VulkanCommandBuffer::copyBufferToImage(
1382     const VulkanBuffer &buffer, const VulkanImage &image, uint64_t bufferOffset,
1383     uint32_t mipLevel, uint32_t baseArrayLayer, uint32_t layerCount,
1384     VulkanOffset3D offset3D, VulkanExtent3D extent3D)
1385 {
1386     VkImageSubresourceLayers vkImageSubresourceLayers = {};
1387     vkImageSubresourceLayers.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1388     vkImageSubresourceLayers.mipLevel = mipLevel;
1389     vkImageSubresourceLayers.baseArrayLayer = baseArrayLayer;
1390     vkImageSubresourceLayers.layerCount = layerCount;
1391 
1392     VkExtent3D vkExtent3D = extent3D;
1393     if ((extent3D.getWidth() == 0) && (extent3D.getHeight() == 0)
1394         && (extent3D.getDepth() == 0))
1395     {
1396         vkExtent3D = image.getExtent3D(mipLevel);
1397     }
1398 
1399     VkBufferImageCopy vkBufferImageCopy = {};
1400     vkBufferImageCopy.bufferOffset = bufferOffset;
1401     vkBufferImageCopy.bufferRowLength = 0;
1402     vkBufferImageCopy.bufferImageHeight = 0;
1403     vkBufferImageCopy.imageSubresource = vkImageSubresourceLayers;
1404     vkBufferImageCopy.imageOffset = offset3D;
1405     vkBufferImageCopy.imageExtent = vkExtent3D;
1406 
1407     vkCmdCopyBufferToImage(m_vkCommandBuffer, buffer, image,
1408                            VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1,
1409                            &vkBufferImageCopy);
1410 }
1411 
copyImageToBuffer(const VulkanImage & image,const VulkanBuffer & buffer,uint64_t bufferOffset,uint32_t mipLevel,uint32_t baseArrayLayer,uint32_t layerCount,VulkanOffset3D offset3D,VulkanExtent3D extent3D)1412 void VulkanCommandBuffer::copyImageToBuffer(
1413     const VulkanImage &image, const VulkanBuffer &buffer, uint64_t bufferOffset,
1414     uint32_t mipLevel, uint32_t baseArrayLayer, uint32_t layerCount,
1415     VulkanOffset3D offset3D, VulkanExtent3D extent3D)
1416 {
1417     VkImageSubresourceLayers vkImageSubresourceLayers = {};
1418     vkImageSubresourceLayers.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1419     vkImageSubresourceLayers.mipLevel = mipLevel;
1420     vkImageSubresourceLayers.baseArrayLayer = baseArrayLayer;
1421     vkImageSubresourceLayers.layerCount = layerCount;
1422 
1423     VkExtent3D vkExtent3D = extent3D;
1424     if ((extent3D.getWidth() == 0) && (extent3D.getHeight() == 0)
1425         && (extent3D.getDepth() == 0))
1426     {
1427         vkExtent3D = image.getExtent3D(mipLevel);
1428     }
1429 
1430     VkBufferImageCopy vkBufferImageCopy = {};
1431     vkBufferImageCopy.bufferOffset = bufferOffset;
1432     vkBufferImageCopy.bufferRowLength = 0;
1433     vkBufferImageCopy.bufferImageHeight = 0;
1434     vkBufferImageCopy.imageSubresource = vkImageSubresourceLayers;
1435     vkBufferImageCopy.imageOffset = offset3D;
1436     vkBufferImageCopy.imageExtent = vkExtent3D;
1437 
1438     vkCmdCopyImageToBuffer(m_vkCommandBuffer, image, VK_IMAGE_LAYOUT_GENERAL,
1439                            buffer, 1, &vkBufferImageCopy);
1440 }
1441 
end()1442 void VulkanCommandBuffer::end() { vkEndCommandBuffer(m_vkCommandBuffer); }
1443 
operator VkCommandBuffer() const1444 VulkanCommandBuffer::operator VkCommandBuffer() const
1445 {
1446     return m_vkCommandBuffer;
1447 }
1448 
1449 /////////////////////////////////
1450 // VulkanBuffer implementation //
1451 /////////////////////////////////
1452 
VulkanBuffer(const VulkanBuffer & buffer)1453 VulkanBuffer::VulkanBuffer(const VulkanBuffer &buffer)
1454     : m_device(buffer.m_device), m_vkBuffer(buffer.m_vkBuffer),
1455       m_size(buffer.m_size), m_alignment(buffer.m_alignment),
1456       m_memoryTypeList(buffer.m_memoryTypeList)
1457 {}
1458 
VulkanBuffer(const VulkanDevice & device,uint64_t size,VulkanExternalMemoryHandleType externalMemoryHandleType,VulkanBufferUsage bufferUsage,VulkanSharingMode sharingMode,const VulkanQueueFamilyList & queueFamilyList)1459 VulkanBuffer::VulkanBuffer(
1460     const VulkanDevice &device, uint64_t size,
1461     VulkanExternalMemoryHandleType externalMemoryHandleType,
1462     VulkanBufferUsage bufferUsage, VulkanSharingMode sharingMode,
1463     const VulkanQueueFamilyList &queueFamilyList)
1464     : m_device(device), m_vkBuffer(VK_NULL_HANDLE)
1465 {
1466     std::vector<uint32_t> queueFamilyIndexList;
1467     if (queueFamilyList.size() == 0)
1468     {
1469         for (size_t qfIdx = 0;
1470              qfIdx < device.getPhysicalDevice().getQueueFamilyList().size();
1471              qfIdx++)
1472         {
1473             queueFamilyIndexList.push_back(
1474                 device.getPhysicalDevice().getQueueFamilyList()[qfIdx]);
1475         }
1476     }
1477     else
1478     {
1479         for (size_t qfIdx = 0; qfIdx < queueFamilyList.size(); qfIdx++)
1480         {
1481             queueFamilyIndexList.push_back(queueFamilyList[qfIdx]);
1482         }
1483     }
1484 
1485     VkBufferCreateInfo vkBufferCreateInfo = {};
1486     vkBufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
1487     vkBufferCreateInfo.pNext = NULL;
1488     vkBufferCreateInfo.flags = 0;
1489     vkBufferCreateInfo.size = (VkDeviceSize)size;
1490     vkBufferCreateInfo.usage = (VkBufferUsageFlags)bufferUsage;
1491     vkBufferCreateInfo.sharingMode = (VkSharingMode)sharingMode;
1492     vkBufferCreateInfo.queueFamilyIndexCount =
1493         (uint32_t)queueFamilyIndexList.size();
1494     vkBufferCreateInfo.pQueueFamilyIndices = queueFamilyIndexList.data();
1495 
1496     VkExternalMemoryBufferCreateInfo vkExternalMemoryBufferCreateInfo = {};
1497     if (externalMemoryHandleType != VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_NONE)
1498     {
1499         vkExternalMemoryBufferCreateInfo.sType =
1500             VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR;
1501         vkExternalMemoryBufferCreateInfo.pNext = NULL;
1502         vkExternalMemoryBufferCreateInfo.handleTypes =
1503             (VkExternalMemoryHandleTypeFlags)externalMemoryHandleType;
1504 
1505         vkBufferCreateInfo.pNext = &vkExternalMemoryBufferCreateInfo;
1506     }
1507 
1508     vkCreateBuffer(m_device, &vkBufferCreateInfo, NULL, &m_vkBuffer);
1509 
1510     VkMemoryRequirements vkMemoryRequirements = {};
1511     vkGetBufferMemoryRequirements(m_device, m_vkBuffer, &vkMemoryRequirements);
1512     m_size = vkMemoryRequirements.size;
1513     m_alignment = vkMemoryRequirements.alignment;
1514     const VulkanMemoryTypeList &memoryTypeList =
1515         m_device.getPhysicalDevice().getMemoryTypeList();
1516     for (size_t mtIdx = 0; mtIdx < memoryTypeList.size(); mtIdx++)
1517     {
1518         uint32_t memoryTypeIndex = memoryTypeList[mtIdx];
1519         if ((1 << memoryTypeIndex) & vkMemoryRequirements.memoryTypeBits)
1520         {
1521             m_memoryTypeList.add(memoryTypeList[mtIdx]);
1522         }
1523     }
1524 }
1525 
~VulkanBuffer()1526 VulkanBuffer::~VulkanBuffer() { vkDestroyBuffer(m_device, m_vkBuffer, NULL); }
1527 
getSize() const1528 uint64_t VulkanBuffer::getSize() const { return m_size; }
1529 
getAlignment() const1530 uint64_t VulkanBuffer::getAlignment() const { return m_alignment; }
1531 
getMemoryTypeList() const1532 const VulkanMemoryTypeList &VulkanBuffer::getMemoryTypeList() const
1533 {
1534     return m_memoryTypeList;
1535 }
1536 
operator VkBuffer() const1537 VulkanBuffer::operator VkBuffer() const { return m_vkBuffer; }
1538 
1539 ////////////////////////////////
1540 // VulkanImage implementation //
1541 ////////////////////////////////
1542 
VulkanImage(const VulkanImage & image)1543 VulkanImage::VulkanImage(const VulkanImage &image)
1544     : m_device(image.m_device), m_imageType(image.m_imageType),
1545       m_extent3D(image.m_extent3D), m_format(image.m_format),
1546       m_numMipLevels(image.m_numMipLevels), m_numLayers(image.m_numLayers),
1547       m_vkImage(image.m_vkImage), m_size(image.m_size),
1548       m_alignment(image.m_alignment), m_memoryTypeList(image.m_memoryTypeList)
1549 {}
1550 
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)1551 VulkanImage::VulkanImage(
1552     const VulkanDevice &device, VulkanImageType imageType, VulkanFormat format,
1553     const VulkanExtent3D &extent3D, uint32_t numMipLevels, uint32_t arrayLayers,
1554     VulkanExternalMemoryHandleType externalMemoryHandleType,
1555     VulkanImageCreateFlag imageCreateFlag, VulkanImageTiling imageTiling,
1556     VulkanImageUsage imageUsage, VulkanSharingMode sharingMode)
1557     : m_device(device), m_imageType(imageType), m_extent3D(extent3D),
1558       m_format(format), m_numMipLevels(numMipLevels), m_numLayers(arrayLayers),
1559       m_vkImage(VK_NULL_HANDLE)
1560 {
1561     VkImageCreateInfo vkImageCreateInfo = {};
1562     vkImageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
1563     vkImageCreateInfo.pNext = NULL;
1564     vkImageCreateInfo.flags = (VkImageCreateFlags)imageCreateFlag;
1565     vkImageCreateInfo.imageType = (VkImageType)imageType;
1566     vkImageCreateInfo.format = (VkFormat)format;
1567     vkImageCreateInfo.extent = extent3D;
1568     vkImageCreateInfo.mipLevels = numMipLevels;
1569     vkImageCreateInfo.arrayLayers = arrayLayers;
1570     vkImageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
1571     vkImageCreateInfo.tiling = (VkImageTiling)imageTiling;
1572     vkImageCreateInfo.usage = (VkImageUsageFlags)imageUsage;
1573     vkImageCreateInfo.sharingMode = (VkSharingMode)sharingMode;
1574     vkImageCreateInfo.queueFamilyIndexCount =
1575         (uint32_t)m_device.getPhysicalDevice().getQueueFamilyList().size();
1576     vkImageCreateInfo.pQueueFamilyIndices =
1577         m_device.getPhysicalDevice().getQueueFamilyList()();
1578     vkImageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
1579 
1580     VkExternalMemoryImageCreateInfo vkExternalMemoryImageCreateInfo = {};
1581     if (externalMemoryHandleType != VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_NONE)
1582     {
1583         vkExternalMemoryImageCreateInfo.sType =
1584             VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
1585         vkExternalMemoryImageCreateInfo.pNext = NULL;
1586         vkExternalMemoryImageCreateInfo.handleTypes =
1587             (VkExternalMemoryHandleTypeFlags)externalMemoryHandleType;
1588 
1589         vkImageCreateInfo.pNext = &vkExternalMemoryImageCreateInfo;
1590     }
1591 
1592     vkCreateImage(m_device, &vkImageCreateInfo, NULL, &m_vkImage);
1593     VulkanImageCreateInfo = vkImageCreateInfo;
1594     VkMemoryRequirements vkMemoryRequirements = {};
1595     vkGetImageMemoryRequirements(m_device, m_vkImage, &vkMemoryRequirements);
1596     m_size = vkMemoryRequirements.size;
1597     m_alignment = vkMemoryRequirements.alignment;
1598     const VulkanMemoryTypeList &memoryTypeList =
1599         m_device.getPhysicalDevice().getMemoryTypeList();
1600     for (size_t mtIdx = 0; mtIdx < memoryTypeList.size(); mtIdx++)
1601     {
1602         uint32_t memoryTypeIndex = memoryTypeList[mtIdx];
1603         if ((1 << memoryTypeIndex) & vkMemoryRequirements.memoryTypeBits)
1604         {
1605             m_memoryTypeList.add(memoryTypeList[mtIdx]);
1606         }
1607     }
1608 }
1609 
~VulkanImage()1610 VulkanImage::~VulkanImage() { vkDestroyImage(m_device, m_vkImage, NULL); }
1611 
getExtent3D(uint32_t mipLevel) const1612 VulkanExtent3D VulkanImage::getExtent3D(uint32_t mipLevel) const
1613 {
1614     return VulkanExtent3D(0, 0, 0);
1615 }
1616 
getFormat() const1617 VulkanFormat VulkanImage::getFormat() const { return m_format; }
1618 
getVkImageCreateInfo() const1619 VkImageCreateInfo VulkanImage::getVkImageCreateInfo() const
1620 {
1621     return VulkanImageCreateInfo;
1622 }
1623 
getNumMipLevels() const1624 uint32_t VulkanImage::getNumMipLevels() const { return m_numMipLevels; }
1625 
getNumLayers() const1626 uint32_t VulkanImage::getNumLayers() const { return m_numLayers; }
1627 
getSize() const1628 uint64_t VulkanImage::getSize() const { return m_size; }
1629 
getAlignment() const1630 uint64_t VulkanImage::getAlignment() const { return m_alignment; }
1631 
getMemoryTypeList() const1632 const VulkanMemoryTypeList &VulkanImage::getMemoryTypeList() const
1633 {
1634     return m_memoryTypeList;
1635 }
1636 
operator VkImage() const1637 VulkanImage::operator VkImage() const { return m_vkImage; }
1638 
1639 //////////////////////////////////
1640 // VulkanImage2D implementation //
1641 //////////////////////////////////
1642 
VulkanImage2D(const VulkanImage2D & image2D)1643 VulkanImage2D::VulkanImage2D(const VulkanImage2D &image2D): VulkanImage(image2D)
1644 {}
1645 
VulkanImage2D(const VulkanDevice & device,VulkanFormat format,uint32_t width,uint32_t height,uint32_t numMipLevels,VulkanExternalMemoryHandleType externalMemoryHandleType,VulkanImageCreateFlag imageCreateFlag,VulkanImageUsage imageUsage,VulkanSharingMode sharingMode)1646 VulkanImage2D::VulkanImage2D(
1647     const VulkanDevice &device, VulkanFormat format, uint32_t width,
1648     uint32_t height, uint32_t numMipLevels,
1649     VulkanExternalMemoryHandleType externalMemoryHandleType,
1650     VulkanImageCreateFlag imageCreateFlag, VulkanImageUsage imageUsage,
1651     VulkanSharingMode sharingMode)
1652     : VulkanImage(device, VULKAN_IMAGE_TYPE_2D, format,
1653                   VulkanExtent3D(width, height, 1), numMipLevels, 1,
1654                   externalMemoryHandleType, imageCreateFlag,
1655                   VULKAN_IMAGE_TILING_OPTIMAL, imageUsage, sharingMode)
1656 {}
1657 
~VulkanImage2D()1658 VulkanImage2D::~VulkanImage2D() {}
1659 
getExtent3D(uint32_t mipLevel) const1660 VulkanExtent3D VulkanImage2D::getExtent3D(uint32_t mipLevel) const
1661 {
1662     uint32_t width = std::max(m_extent3D.getWidth() >> mipLevel, uint32_t(1));
1663     uint32_t height = std::max(m_extent3D.getHeight() >> mipLevel, uint32_t(1));
1664     uint32_t depth = 1;
1665 
1666     return VulkanExtent3D(width, height, depth);
1667 }
1668 
1669 ////////////////////////////////////
1670 // VulkanImageView implementation //
1671 ////////////////////////////////////
1672 
VulkanImageView(const VulkanImageView & imageView)1673 VulkanImageView::VulkanImageView(const VulkanImageView &imageView)
1674     : m_device(imageView.m_device), m_vkImageView(imageView.m_vkImageView)
1675 {}
1676 
VulkanImageView(const VulkanDevice & device,const VulkanImage & image,VulkanImageViewType imageViewType,uint32_t baseMipLevel,uint32_t levelCount,uint32_t baseArrayLayer,uint32_t layerCount)1677 VulkanImageView::VulkanImageView(const VulkanDevice &device,
1678                                  const VulkanImage &image,
1679                                  VulkanImageViewType imageViewType,
1680                                  uint32_t baseMipLevel, uint32_t levelCount,
1681                                  uint32_t baseArrayLayer, uint32_t layerCount)
1682     : m_device(device), m_vkImageView(VK_NULL_HANDLE)
1683 {
1684     VkComponentMapping vkComponentMapping = {};
1685     vkComponentMapping.r = VK_COMPONENT_SWIZZLE_IDENTITY;
1686     vkComponentMapping.g = VK_COMPONENT_SWIZZLE_IDENTITY;
1687     vkComponentMapping.b = VK_COMPONENT_SWIZZLE_IDENTITY;
1688     vkComponentMapping.a = VK_COMPONENT_SWIZZLE_IDENTITY;
1689 
1690     VkImageSubresourceRange vkImageSubresourceRange = {};
1691     vkImageSubresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1692     vkImageSubresourceRange.baseMipLevel = baseMipLevel;
1693     vkImageSubresourceRange.levelCount = levelCount;
1694     vkImageSubresourceRange.baseArrayLayer = baseArrayLayer;
1695     vkImageSubresourceRange.layerCount = layerCount;
1696 
1697     VkImageViewCreateInfo vkImageViewCreateInfo = {};
1698     vkImageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
1699     vkImageViewCreateInfo.pNext = NULL;
1700     vkImageViewCreateInfo.flags = 0;
1701     vkImageViewCreateInfo.image = image;
1702     vkImageViewCreateInfo.viewType = (VkImageViewType)imageViewType;
1703     vkImageViewCreateInfo.format = (VkFormat)image.getFormat();
1704     vkImageViewCreateInfo.components = vkComponentMapping;
1705     vkImageViewCreateInfo.subresourceRange = vkImageSubresourceRange;
1706 
1707     vkCreateImageView(m_device, &vkImageViewCreateInfo, NULL, &m_vkImageView);
1708 }
1709 
~VulkanImageView()1710 VulkanImageView::~VulkanImageView()
1711 {
1712     vkDestroyImageView(m_device, m_vkImageView, NULL);
1713 }
1714 
operator VkImageView() const1715 VulkanImageView::operator VkImageView() const { return m_vkImageView; }
1716 
1717 ///////////////////////////////////////
1718 // VulkanDeviceMemory implementation //
1719 ///////////////////////////////////////
1720 
1721 #if defined(_WIN32) || defined(_WIN64)
1722 
1723 class WindowsSecurityAttributes {
1724 protected:
1725     SECURITY_ATTRIBUTES m_winSecurityAttributes;
1726     PSECURITY_DESCRIPTOR m_winPSecurityDescriptor;
1727 
1728 public:
1729     WindowsSecurityAttributes();
1730     SECURITY_ATTRIBUTES *operator&();
1731     ~WindowsSecurityAttributes();
1732 };
1733 
1734 
WindowsSecurityAttributes()1735 WindowsSecurityAttributes::WindowsSecurityAttributes()
1736 {
1737     m_winPSecurityDescriptor = (PSECURITY_DESCRIPTOR)calloc(
1738         1, SECURITY_DESCRIPTOR_MIN_LENGTH + 2 * sizeof(void **));
1739     // CHECK_NEQ(m_winPSecurityDescriptor, (PSECURITY_DESCRIPTOR)NULL);
1740     PSID *ppSID = (PSID *)((PBYTE)m_winPSecurityDescriptor
1741                            + SECURITY_DESCRIPTOR_MIN_LENGTH);
1742     PACL *ppACL = (PACL *)((PBYTE)ppSID + sizeof(PSID *));
1743     InitializeSecurityDescriptor(m_winPSecurityDescriptor,
1744                                  SECURITY_DESCRIPTOR_REVISION);
1745     SID_IDENTIFIER_AUTHORITY sidIdentifierAuthority =
1746         SECURITY_WORLD_SID_AUTHORITY;
1747     AllocateAndInitializeSid(&sidIdentifierAuthority, 1, SECURITY_WORLD_RID, 0,
1748                              0, 0, 0, 0, 0, 0, ppSID);
1749     EXPLICIT_ACCESS explicitAccess;
1750     ZeroMemory(&explicitAccess, sizeof(EXPLICIT_ACCESS));
1751     explicitAccess.grfAccessPermissions =
1752         STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL;
1753     explicitAccess.grfAccessMode = SET_ACCESS;
1754     explicitAccess.grfInheritance = INHERIT_ONLY;
1755     explicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
1756     explicitAccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
1757     explicitAccess.Trustee.ptstrName = (LPTSTR)*ppSID;
1758     SetEntriesInAcl(1, &explicitAccess, NULL, ppACL);
1759     SetSecurityDescriptorDacl(m_winPSecurityDescriptor, TRUE, *ppACL, FALSE);
1760     m_winSecurityAttributes.nLength = sizeof(m_winSecurityAttributes);
1761     m_winSecurityAttributes.lpSecurityDescriptor = m_winPSecurityDescriptor;
1762     m_winSecurityAttributes.bInheritHandle = TRUE;
1763 }
1764 
operator &()1765 SECURITY_ATTRIBUTES *WindowsSecurityAttributes::operator&()
1766 {
1767     return &m_winSecurityAttributes;
1768 }
1769 
~WindowsSecurityAttributes()1770 WindowsSecurityAttributes::~WindowsSecurityAttributes()
1771 {
1772     PSID *ppSID = (PSID *)((PBYTE)m_winPSecurityDescriptor
1773                            + SECURITY_DESCRIPTOR_MIN_LENGTH);
1774     PACL *ppACL = (PACL *)((PBYTE)ppSID + sizeof(PSID *));
1775     if (*ppSID)
1776     {
1777         FreeSid(*ppSID);
1778     }
1779     if (*ppACL)
1780     {
1781         LocalFree(*ppACL);
1782     }
1783     free(m_winPSecurityDescriptor);
1784 }
1785 
1786 #endif
1787 
VulkanDeviceMemory(const VulkanDeviceMemory & deviceMemory)1788 VulkanDeviceMemory::VulkanDeviceMemory(const VulkanDeviceMemory &deviceMemory)
1789     : m_device(deviceMemory.m_device),
1790       m_vkDeviceMemory(deviceMemory.m_vkDeviceMemory),
1791       m_size(deviceMemory.m_size), m_isDedicated(deviceMemory.m_isDedicated)
1792 {}
1793 
VulkanDeviceMemory(const VulkanDevice & device,uint64_t size,const VulkanMemoryType & memoryType,VulkanExternalMemoryHandleType externalMemoryHandleType,const void * name)1794 VulkanDeviceMemory::VulkanDeviceMemory(
1795     const VulkanDevice &device, uint64_t size,
1796     const VulkanMemoryType &memoryType,
1797     VulkanExternalMemoryHandleType externalMemoryHandleType, const void *name)
1798     : m_device(device), m_size(size), m_isDedicated(false)
1799 {
1800 #if defined(_WIN32) || defined(_WIN64)
1801     WindowsSecurityAttributes winSecurityAttributes;
1802 
1803     VkExportMemoryWin32HandleInfoKHR vkExportMemoryWin32HandleInfoKHR = {};
1804     vkExportMemoryWin32HandleInfoKHR.sType =
1805         VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR;
1806     vkExportMemoryWin32HandleInfoKHR.pNext = NULL;
1807     vkExportMemoryWin32HandleInfoKHR.pAttributes = &winSecurityAttributes;
1808     vkExportMemoryWin32HandleInfoKHR.dwAccess =
1809         DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE;
1810     vkExportMemoryWin32HandleInfoKHR.name = (LPCWSTR)name;
1811 
1812 #endif
1813 
1814     VkExportMemoryAllocateInfoKHR vkExportMemoryAllocateInfoKHR = {};
1815     vkExportMemoryAllocateInfoKHR.sType =
1816         VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR;
1817 #if defined(_WIN32) || defined(_WIN64)
1818     vkExportMemoryAllocateInfoKHR.pNext = externalMemoryHandleType
1819             & VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT
1820         ? &vkExportMemoryWin32HandleInfoKHR
1821         : NULL;
1822 #else
1823     vkExportMemoryAllocateInfoKHR.pNext = NULL;
1824 #endif
1825     vkExportMemoryAllocateInfoKHR.handleTypes =
1826         (VkExternalMemoryHandleTypeFlagsKHR)externalMemoryHandleType;
1827 
1828     VkMemoryAllocateInfo vkMemoryAllocateInfo = {};
1829     vkMemoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
1830     vkMemoryAllocateInfo.pNext =
1831         externalMemoryHandleType ? &vkExportMemoryAllocateInfoKHR : NULL;
1832     vkMemoryAllocateInfo.allocationSize = m_size;
1833     vkMemoryAllocateInfo.memoryTypeIndex = (uint32_t)memoryType;
1834 
1835     vkAllocateMemory(m_device, &vkMemoryAllocateInfo, NULL, &m_vkDeviceMemory);
1836 }
1837 
VulkanDeviceMemory(const VulkanDevice & device,const VulkanImage & image,const VulkanMemoryType & memoryType,VulkanExternalMemoryHandleType externalMemoryHandleType,const void * name)1838 VulkanDeviceMemory::VulkanDeviceMemory(
1839     const VulkanDevice &device, const VulkanImage &image,
1840     const VulkanMemoryType &memoryType,
1841     VulkanExternalMemoryHandleType externalMemoryHandleType, const void *name)
1842     : m_device(device), m_size(image.getSize()), m_isDedicated(true)
1843 {
1844 #if defined(_WIN32) || defined(_WIN64)
1845     WindowsSecurityAttributes winSecurityAttributes;
1846 
1847     VkExportMemoryWin32HandleInfoKHR vkExportMemoryWin32HandleInfoKHR = {};
1848     vkExportMemoryWin32HandleInfoKHR.sType =
1849         VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR;
1850     vkExportMemoryWin32HandleInfoKHR.pNext = NULL;
1851     vkExportMemoryWin32HandleInfoKHR.pAttributes = &winSecurityAttributes;
1852     vkExportMemoryWin32HandleInfoKHR.dwAccess =
1853         DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE;
1854     vkExportMemoryWin32HandleInfoKHR.name = (LPCWSTR)name;
1855 
1856 #endif
1857 
1858     VkExportMemoryAllocateInfoKHR vkExportMemoryAllocateInfoKHR = {};
1859     vkExportMemoryAllocateInfoKHR.sType =
1860         VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR;
1861 #if defined(_WIN32) || defined(_WIN64)
1862     vkExportMemoryAllocateInfoKHR.pNext = externalMemoryHandleType
1863             & VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT
1864         ? &vkExportMemoryWin32HandleInfoKHR
1865         : NULL;
1866 #else
1867     vkExportMemoryAllocateInfoKHR.pNext = NULL;
1868 #endif
1869     vkExportMemoryAllocateInfoKHR.handleTypes =
1870         (VkExternalMemoryHandleTypeFlagsKHR)externalMemoryHandleType;
1871 
1872     VkMemoryDedicatedAllocateInfo vkMemoryDedicatedAllocateInfo = {};
1873     vkMemoryDedicatedAllocateInfo.sType =
1874         VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
1875     vkMemoryDedicatedAllocateInfo.pNext =
1876         externalMemoryHandleType ? &vkExportMemoryAllocateInfoKHR : NULL;
1877     vkMemoryDedicatedAllocateInfo.image = image;
1878     vkMemoryDedicatedAllocateInfo.buffer = VK_NULL_HANDLE;
1879 
1880     VkMemoryAllocateInfo vkMemoryAllocateInfo = {};
1881     vkMemoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
1882     vkMemoryAllocateInfo.pNext = &vkMemoryDedicatedAllocateInfo;
1883     vkMemoryAllocateInfo.allocationSize = m_size;
1884     vkMemoryAllocateInfo.memoryTypeIndex = (uint32_t)memoryType;
1885 
1886     vkAllocateMemory(m_device, &vkMemoryAllocateInfo, NULL, &m_vkDeviceMemory);
1887 }
1888 
~VulkanDeviceMemory()1889 VulkanDeviceMemory::~VulkanDeviceMemory()
1890 {
1891     vkFreeMemory(m_device, m_vkDeviceMemory, NULL);
1892 }
1893 
getSize() const1894 uint64_t VulkanDeviceMemory::getSize() const { return m_size; }
1895 
1896 #ifdef _WIN32
getHandle(VulkanExternalMemoryHandleType externalMemoryHandleType) const1897 HANDLE VulkanDeviceMemory::getHandle(
1898     VulkanExternalMemoryHandleType externalMemoryHandleType) const
1899 {
1900     HANDLE handle;
1901 
1902     VkMemoryGetWin32HandleInfoKHR vkMemoryGetWin32HandleInfoKHR = {};
1903     vkMemoryGetWin32HandleInfoKHR.sType =
1904         VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR;
1905     vkMemoryGetWin32HandleInfoKHR.pNext = NULL;
1906     vkMemoryGetWin32HandleInfoKHR.memory = m_vkDeviceMemory;
1907     vkMemoryGetWin32HandleInfoKHR.handleType =
1908         (VkExternalMemoryHandleTypeFlagBitsKHR)externalMemoryHandleType;
1909 
1910     vkGetMemoryWin32HandleKHR(m_device, &vkMemoryGetWin32HandleInfoKHR,
1911                               &handle);
1912 
1913     return handle;
1914 }
1915 #else
getHandle(VulkanExternalMemoryHandleType externalMemoryHandleType) const1916 int VulkanDeviceMemory::getHandle(
1917     VulkanExternalMemoryHandleType externalMemoryHandleType) const
1918 {
1919     if (externalMemoryHandleType
1920         == VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD)
1921     {
1922         int fd;
1923 
1924         VkMemoryGetFdInfoKHR vkMemoryGetFdInfoKHR = {};
1925         vkMemoryGetFdInfoKHR.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR;
1926         vkMemoryGetFdInfoKHR.pNext = NULL;
1927         vkMemoryGetFdInfoKHR.memory = m_vkDeviceMemory;
1928         vkMemoryGetFdInfoKHR.handleType =
1929             VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
1930 
1931         vkGetMemoryFdKHR(m_device, &vkMemoryGetFdInfoKHR, &fd);
1932 
1933         return fd;
1934     }
1935     return HANDLE_ERROR;
1936 }
1937 #endif
1938 
isDedicated() const1939 bool VulkanDeviceMemory::isDedicated() const { return m_isDedicated; }
1940 
map(size_t offset,size_t size)1941 void *VulkanDeviceMemory::map(size_t offset, size_t size)
1942 {
1943     void *pData;
1944 
1945     vkMapMemory(m_device, m_vkDeviceMemory, (VkDeviceSize)offset,
1946                 (VkDeviceSize)size, 0, &pData);
1947 
1948     return pData;
1949 }
1950 
unmap()1951 void VulkanDeviceMemory::unmap() { vkUnmapMemory(m_device, m_vkDeviceMemory); }
1952 
bindBuffer(const VulkanBuffer & buffer,uint64_t offset)1953 void VulkanDeviceMemory::bindBuffer(const VulkanBuffer &buffer, uint64_t offset)
1954 {
1955     vkBindBufferMemory(m_device, buffer, m_vkDeviceMemory, offset);
1956 }
1957 
bindImage(const VulkanImage & image,uint64_t offset)1958 void VulkanDeviceMemory::bindImage(const VulkanImage &image, uint64_t offset)
1959 {
1960     vkBindImageMemory(m_device, image, m_vkDeviceMemory, offset);
1961 }
1962 
operator VkDeviceMemory() const1963 VulkanDeviceMemory::operator VkDeviceMemory() const { return m_vkDeviceMemory; }
1964 
1965 ////////////////////////////////////
1966 // VulkanSemaphore implementation //
1967 ////////////////////////////////////
1968 
VulkanSemaphore(const VulkanSemaphore & semaphore)1969 VulkanSemaphore::VulkanSemaphore(const VulkanSemaphore &semaphore)
1970     : m_device(semaphore.m_device), m_vkSemaphore(semaphore.m_vkSemaphore)
1971 {}
1972 
VulkanSemaphore(const VulkanDevice & device,VulkanExternalSemaphoreHandleType externalSemaphoreHandleType,const std::wstring name)1973 VulkanSemaphore::VulkanSemaphore(
1974     const VulkanDevice &device,
1975     VulkanExternalSemaphoreHandleType externalSemaphoreHandleType,
1976     const std::wstring name)
1977     : m_device(device), m_name(name)
1978 {
1979 #if defined(_WIN32) || defined(_WIN64)
1980     WindowsSecurityAttributes winSecurityAttributes;
1981 
1982     VkExportSemaphoreWin32HandleInfoKHR
1983         vkExportSemaphoreWin32HandleInfoKHR = {};
1984     vkExportSemaphoreWin32HandleInfoKHR.sType =
1985         VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR;
1986     vkExportSemaphoreWin32HandleInfoKHR.pNext = NULL;
1987     vkExportSemaphoreWin32HandleInfoKHR.pAttributes = &winSecurityAttributes;
1988     vkExportSemaphoreWin32HandleInfoKHR.dwAccess =
1989         DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE;
1990     vkExportSemaphoreWin32HandleInfoKHR.name =
1991         m_name.size() ? (LPCWSTR)m_name.c_str() : NULL;
1992 #endif
1993 
1994     VkExportSemaphoreCreateInfoKHR vkExportSemaphoreCreateInfoKHR = {};
1995     vkExportSemaphoreCreateInfoKHR.sType =
1996         VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR;
1997 #if defined(_WIN32) || defined(_WIN64)
1998     vkExportSemaphoreCreateInfoKHR.pNext =
1999         (externalSemaphoreHandleType
2000          & VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT)
2001         ? &vkExportSemaphoreWin32HandleInfoKHR
2002         : NULL;
2003 #else
2004     vkExportSemaphoreCreateInfoKHR.pNext = NULL;
2005 #endif
2006     vkExportSemaphoreCreateInfoKHR.handleTypes =
2007         (VkExternalSemaphoreHandleTypeFlagsKHR)externalSemaphoreHandleType;
2008 
2009     VkSemaphoreCreateInfo vkSemaphoreCreateInfo = {};
2010     vkSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
2011     vkSemaphoreCreateInfo.pNext =
2012         (externalSemaphoreHandleType
2013          != VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_NONE)
2014         ? &vkExportSemaphoreCreateInfoKHR
2015         : NULL;
2016     vkSemaphoreCreateInfo.flags = 0;
2017 
2018     vkCreateSemaphore(m_device, &vkSemaphoreCreateInfo, NULL, &m_vkSemaphore);
2019 }
2020 
~VulkanSemaphore()2021 VulkanSemaphore::~VulkanSemaphore()
2022 {
2023     vkDestroySemaphore(m_device, m_vkSemaphore, NULL);
2024 }
2025 
2026 #if defined(_WIN32) || defined(_WIN64)
getHandle(VulkanExternalSemaphoreHandleType externalSemaphoreHandleType) const2027 HANDLE VulkanSemaphore::getHandle(
2028     VulkanExternalSemaphoreHandleType externalSemaphoreHandleType) const
2029 {
2030     HANDLE handle;
2031 
2032     VkSemaphoreGetWin32HandleInfoKHR vkSemaphoreGetWin32HandleInfoKHR = {};
2033     vkSemaphoreGetWin32HandleInfoKHR.sType =
2034         VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR;
2035     vkSemaphoreGetWin32HandleInfoKHR.pNext = NULL;
2036     vkSemaphoreGetWin32HandleInfoKHR.semaphore = m_vkSemaphore;
2037     vkSemaphoreGetWin32HandleInfoKHR.handleType =
2038         (VkExternalSemaphoreHandleTypeFlagBitsKHR)externalSemaphoreHandleType;
2039 
2040     vkGetSemaphoreWin32HandleKHR(m_device, &vkSemaphoreGetWin32HandleInfoKHR,
2041                                  &handle);
2042 
2043     return handle;
2044 }
2045 #else
getHandle(VulkanExternalSemaphoreHandleType externalSemaphoreHandleType) const2046 int VulkanSemaphore::getHandle(
2047     VulkanExternalSemaphoreHandleType externalSemaphoreHandleType) const
2048 {
2049     if (externalSemaphoreHandleType
2050         == VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD)
2051     {
2052         int fd;
2053 
2054         VkSemaphoreGetFdInfoKHR vkSemaphoreGetFdInfoKHR = {};
2055         vkSemaphoreGetFdInfoKHR.sType =
2056             VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR;
2057         vkSemaphoreGetFdInfoKHR.pNext = NULL;
2058         vkSemaphoreGetFdInfoKHR.semaphore = m_vkSemaphore;
2059         vkSemaphoreGetFdInfoKHR.handleType =
2060             VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
2061 
2062         vkGetSemaphoreFdKHR(m_device, &vkSemaphoreGetFdInfoKHR, &fd);
2063 
2064         return fd;
2065     }
2066     return HANDLE_ERROR;
2067 }
2068 #endif
2069 
getName() const2070 const std::wstring &VulkanSemaphore::getName() const { return m_name; }
2071 
operator VkSemaphore() const2072 VulkanSemaphore::operator VkSemaphore() const { return m_vkSemaphore; }
2073