xref: /aosp_15_r20/external/vulkan-validation-layers/tests/vktestbinding.cpp (revision b7893ccf7851cd6a48cc5a1e965257d8a5cdcc70)
1*b7893ccfSSadaf Ebrahimi /*
2*b7893ccfSSadaf Ebrahimi  * Copyright (c) 2015-2019 The Khronos Group Inc.
3*b7893ccfSSadaf Ebrahimi  * Copyright (c) 2015-2019 Valve Corporation
4*b7893ccfSSadaf Ebrahimi  * Copyright (c) 2015-2019 LunarG, Inc.
5*b7893ccfSSadaf Ebrahimi  *
6*b7893ccfSSadaf Ebrahimi  * Licensed under the Apache License, Version 2.0 (the "License");
7*b7893ccfSSadaf Ebrahimi  * you may not use this file except in compliance with the License.
8*b7893ccfSSadaf Ebrahimi  * You may obtain a copy of the License at
9*b7893ccfSSadaf Ebrahimi  *
10*b7893ccfSSadaf Ebrahimi  *     http://www.apache.org/licenses/LICENSE-2.0
11*b7893ccfSSadaf Ebrahimi  *
12*b7893ccfSSadaf Ebrahimi  * Unless required by applicable law or agreed to in writing, software
13*b7893ccfSSadaf Ebrahimi  * distributed under the License is distributed on an "AS IS" BASIS,
14*b7893ccfSSadaf Ebrahimi  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15*b7893ccfSSadaf Ebrahimi  * See the License for the specific language governing permissions and
16*b7893ccfSSadaf Ebrahimi  * limitations under the License.
17*b7893ccfSSadaf Ebrahimi  *
18*b7893ccfSSadaf Ebrahimi  * Author: Courtney Goeltzenleuchter <[email protected]>
19*b7893ccfSSadaf Ebrahimi  * Author: Tony Barbour <[email protected]>
20*b7893ccfSSadaf Ebrahimi  */
21*b7893ccfSSadaf Ebrahimi 
22*b7893ccfSSadaf Ebrahimi #include "test_common.h"    // NOEXCEPT macro (must precede vktestbinding.h)
23*b7893ccfSSadaf Ebrahimi #include "vktestbinding.h"  // Left for clarity, no harm, already included via test_common.h
24*b7893ccfSSadaf Ebrahimi #include "vk_typemap_helper.h"
25*b7893ccfSSadaf Ebrahimi #include <algorithm>
26*b7893ccfSSadaf Ebrahimi #include <assert.h>
27*b7893ccfSSadaf Ebrahimi #include <iostream>
28*b7893ccfSSadaf Ebrahimi #include <stdarg.h>
29*b7893ccfSSadaf Ebrahimi #include <string.h>  // memset(), memcmp()
30*b7893ccfSSadaf Ebrahimi 
31*b7893ccfSSadaf Ebrahimi namespace {
32*b7893ccfSSadaf Ebrahimi 
33*b7893ccfSSadaf Ebrahimi #define NON_DISPATCHABLE_HANDLE_INIT(create_func, dev, ...)                              \
34*b7893ccfSSadaf Ebrahimi     do {                                                                                 \
35*b7893ccfSSadaf Ebrahimi         handle_type handle;                                                              \
36*b7893ccfSSadaf Ebrahimi         if (EXPECT(create_func(dev.handle(), __VA_ARGS__, NULL, &handle) == VK_SUCCESS)) \
37*b7893ccfSSadaf Ebrahimi             NonDispHandle::init(dev.handle(), handle);                                   \
38*b7893ccfSSadaf Ebrahimi     } while (0)
39*b7893ccfSSadaf Ebrahimi 
40*b7893ccfSSadaf Ebrahimi #define NON_DISPATCHABLE_HANDLE_DTOR(cls, destroy_func)            \
41*b7893ccfSSadaf Ebrahimi     cls::~cls() {                                                  \
42*b7893ccfSSadaf Ebrahimi         if (initialized()) destroy_func(device(), handle(), NULL); \
43*b7893ccfSSadaf Ebrahimi     }
44*b7893ccfSSadaf Ebrahimi 
45*b7893ccfSSadaf Ebrahimi #define STRINGIFY(x) #x
46*b7893ccfSSadaf Ebrahimi #define EXPECT(expr) ((expr) ? true : expect_failure(STRINGIFY(expr), __FILE__, __LINE__, __FUNCTION__))
47*b7893ccfSSadaf Ebrahimi 
48*b7893ccfSSadaf Ebrahimi vk_testing::ErrorCallback error_callback;
49*b7893ccfSSadaf Ebrahimi 
expect_failure(const char * expr,const char * file,unsigned int line,const char * function)50*b7893ccfSSadaf Ebrahimi bool expect_failure(const char *expr, const char *file, unsigned int line, const char *function) {
51*b7893ccfSSadaf Ebrahimi     if (error_callback) {
52*b7893ccfSSadaf Ebrahimi         error_callback(expr, file, line, function);
53*b7893ccfSSadaf Ebrahimi     } else {
54*b7893ccfSSadaf Ebrahimi         std::cerr << file << ":" << line << ": " << function << ": Expectation `" << expr << "' failed.\n";
55*b7893ccfSSadaf Ebrahimi     }
56*b7893ccfSSadaf Ebrahimi 
57*b7893ccfSSadaf Ebrahimi     return false;
58*b7893ccfSSadaf Ebrahimi }
59*b7893ccfSSadaf Ebrahimi 
60*b7893ccfSSadaf Ebrahimi }  // namespace
61*b7893ccfSSadaf Ebrahimi 
62*b7893ccfSSadaf Ebrahimi namespace vk_testing {
63*b7893ccfSSadaf Ebrahimi 
set_error_callback(ErrorCallback callback)64*b7893ccfSSadaf Ebrahimi void set_error_callback(ErrorCallback callback) { error_callback = callback; }
65*b7893ccfSSadaf Ebrahimi 
properties() const66*b7893ccfSSadaf Ebrahimi VkPhysicalDeviceProperties PhysicalDevice::properties() const {
67*b7893ccfSSadaf Ebrahimi     VkPhysicalDeviceProperties info;
68*b7893ccfSSadaf Ebrahimi 
69*b7893ccfSSadaf Ebrahimi     vkGetPhysicalDeviceProperties(handle(), &info);
70*b7893ccfSSadaf Ebrahimi 
71*b7893ccfSSadaf Ebrahimi     return info;
72*b7893ccfSSadaf Ebrahimi }
73*b7893ccfSSadaf Ebrahimi 
queue_properties() const74*b7893ccfSSadaf Ebrahimi std::vector<VkQueueFamilyProperties> PhysicalDevice::queue_properties() const {
75*b7893ccfSSadaf Ebrahimi     std::vector<VkQueueFamilyProperties> info;
76*b7893ccfSSadaf Ebrahimi     uint32_t count;
77*b7893ccfSSadaf Ebrahimi 
78*b7893ccfSSadaf Ebrahimi     // Call once with NULL data to receive count
79*b7893ccfSSadaf Ebrahimi     vkGetPhysicalDeviceQueueFamilyProperties(handle(), &count, NULL);
80*b7893ccfSSadaf Ebrahimi     info.resize(count);
81*b7893ccfSSadaf Ebrahimi     vkGetPhysicalDeviceQueueFamilyProperties(handle(), &count, info.data());
82*b7893ccfSSadaf Ebrahimi 
83*b7893ccfSSadaf Ebrahimi     return info;
84*b7893ccfSSadaf Ebrahimi }
85*b7893ccfSSadaf Ebrahimi 
memory_properties() const86*b7893ccfSSadaf Ebrahimi VkPhysicalDeviceMemoryProperties PhysicalDevice::memory_properties() const {
87*b7893ccfSSadaf Ebrahimi     VkPhysicalDeviceMemoryProperties info;
88*b7893ccfSSadaf Ebrahimi 
89*b7893ccfSSadaf Ebrahimi     vkGetPhysicalDeviceMemoryProperties(handle(), &info);
90*b7893ccfSSadaf Ebrahimi 
91*b7893ccfSSadaf Ebrahimi     return info;
92*b7893ccfSSadaf Ebrahimi }
93*b7893ccfSSadaf Ebrahimi 
features() const94*b7893ccfSSadaf Ebrahimi VkPhysicalDeviceFeatures PhysicalDevice::features() const {
95*b7893ccfSSadaf Ebrahimi     VkPhysicalDeviceFeatures features;
96*b7893ccfSSadaf Ebrahimi     vkGetPhysicalDeviceFeatures(handle(), &features);
97*b7893ccfSSadaf Ebrahimi     return features;
98*b7893ccfSSadaf Ebrahimi }
99*b7893ccfSSadaf Ebrahimi 
100*b7893ccfSSadaf Ebrahimi /*
101*b7893ccfSSadaf Ebrahimi  * Return list of Global layers available
102*b7893ccfSSadaf Ebrahimi  */
GetGlobalLayers()103*b7893ccfSSadaf Ebrahimi std::vector<VkLayerProperties> GetGlobalLayers() {
104*b7893ccfSSadaf Ebrahimi     VkResult err;
105*b7893ccfSSadaf Ebrahimi     std::vector<VkLayerProperties> layers;
106*b7893ccfSSadaf Ebrahimi     uint32_t layer_count;
107*b7893ccfSSadaf Ebrahimi 
108*b7893ccfSSadaf Ebrahimi     do {
109*b7893ccfSSadaf Ebrahimi         layer_count = 0;
110*b7893ccfSSadaf Ebrahimi         err = vkEnumerateInstanceLayerProperties(&layer_count, NULL);
111*b7893ccfSSadaf Ebrahimi 
112*b7893ccfSSadaf Ebrahimi         if (err == VK_SUCCESS) {
113*b7893ccfSSadaf Ebrahimi             layers.reserve(layer_count);
114*b7893ccfSSadaf Ebrahimi             err = vkEnumerateInstanceLayerProperties(&layer_count, layers.data());
115*b7893ccfSSadaf Ebrahimi         }
116*b7893ccfSSadaf Ebrahimi     } while (err == VK_INCOMPLETE);
117*b7893ccfSSadaf Ebrahimi 
118*b7893ccfSSadaf Ebrahimi     assert(err == VK_SUCCESS);
119*b7893ccfSSadaf Ebrahimi 
120*b7893ccfSSadaf Ebrahimi     return layers;
121*b7893ccfSSadaf Ebrahimi }
122*b7893ccfSSadaf Ebrahimi 
123*b7893ccfSSadaf Ebrahimi /*
124*b7893ccfSSadaf Ebrahimi  * Return list of Global extensions provided by the ICD / Loader
125*b7893ccfSSadaf Ebrahimi  */
GetGlobalExtensions()126*b7893ccfSSadaf Ebrahimi std::vector<VkExtensionProperties> GetGlobalExtensions() { return GetGlobalExtensions(NULL); }
127*b7893ccfSSadaf Ebrahimi 
128*b7893ccfSSadaf Ebrahimi /*
129*b7893ccfSSadaf Ebrahimi  * Return list of Global extensions provided by the specified layer
130*b7893ccfSSadaf Ebrahimi  * If pLayerName is NULL, will return extensions implemented by the loader /
131*b7893ccfSSadaf Ebrahimi  * ICDs
132*b7893ccfSSadaf Ebrahimi  */
GetGlobalExtensions(const char * pLayerName)133*b7893ccfSSadaf Ebrahimi std::vector<VkExtensionProperties> GetGlobalExtensions(const char *pLayerName) {
134*b7893ccfSSadaf Ebrahimi     std::vector<VkExtensionProperties> exts;
135*b7893ccfSSadaf Ebrahimi     uint32_t ext_count;
136*b7893ccfSSadaf Ebrahimi     VkResult err;
137*b7893ccfSSadaf Ebrahimi 
138*b7893ccfSSadaf Ebrahimi     do {
139*b7893ccfSSadaf Ebrahimi         ext_count = 0;
140*b7893ccfSSadaf Ebrahimi         err = vkEnumerateInstanceExtensionProperties(pLayerName, &ext_count, NULL);
141*b7893ccfSSadaf Ebrahimi 
142*b7893ccfSSadaf Ebrahimi         if (err == VK_SUCCESS) {
143*b7893ccfSSadaf Ebrahimi             exts.resize(ext_count);
144*b7893ccfSSadaf Ebrahimi             err = vkEnumerateInstanceExtensionProperties(pLayerName, &ext_count, exts.data());
145*b7893ccfSSadaf Ebrahimi         }
146*b7893ccfSSadaf Ebrahimi     } while (err == VK_INCOMPLETE);
147*b7893ccfSSadaf Ebrahimi 
148*b7893ccfSSadaf Ebrahimi     assert(err == VK_SUCCESS);
149*b7893ccfSSadaf Ebrahimi 
150*b7893ccfSSadaf Ebrahimi     return exts;
151*b7893ccfSSadaf Ebrahimi }
152*b7893ccfSSadaf Ebrahimi 
153*b7893ccfSSadaf Ebrahimi /*
154*b7893ccfSSadaf Ebrahimi  * Return list of PhysicalDevice extensions provided by the ICD / Loader
155*b7893ccfSSadaf Ebrahimi  */
extensions() const156*b7893ccfSSadaf Ebrahimi std::vector<VkExtensionProperties> PhysicalDevice::extensions() const { return extensions(NULL); }
157*b7893ccfSSadaf Ebrahimi 
158*b7893ccfSSadaf Ebrahimi /*
159*b7893ccfSSadaf Ebrahimi  * Return list of PhysicalDevice extensions provided by the specified layer
160*b7893ccfSSadaf Ebrahimi  * If pLayerName is NULL, will return extensions for ICD / loader.
161*b7893ccfSSadaf Ebrahimi  */
extensions(const char * pLayerName) const162*b7893ccfSSadaf Ebrahimi std::vector<VkExtensionProperties> PhysicalDevice::extensions(const char *pLayerName) const {
163*b7893ccfSSadaf Ebrahimi     std::vector<VkExtensionProperties> exts;
164*b7893ccfSSadaf Ebrahimi     VkResult err;
165*b7893ccfSSadaf Ebrahimi 
166*b7893ccfSSadaf Ebrahimi     do {
167*b7893ccfSSadaf Ebrahimi         uint32_t extCount = 0;
168*b7893ccfSSadaf Ebrahimi         err = vkEnumerateDeviceExtensionProperties(handle(), pLayerName, &extCount, NULL);
169*b7893ccfSSadaf Ebrahimi 
170*b7893ccfSSadaf Ebrahimi         if (err == VK_SUCCESS) {
171*b7893ccfSSadaf Ebrahimi             exts.resize(extCount);
172*b7893ccfSSadaf Ebrahimi             err = vkEnumerateDeviceExtensionProperties(handle(), pLayerName, &extCount, exts.data());
173*b7893ccfSSadaf Ebrahimi         }
174*b7893ccfSSadaf Ebrahimi     } while (err == VK_INCOMPLETE);
175*b7893ccfSSadaf Ebrahimi 
176*b7893ccfSSadaf Ebrahimi     assert(err == VK_SUCCESS);
177*b7893ccfSSadaf Ebrahimi 
178*b7893ccfSSadaf Ebrahimi     return exts;
179*b7893ccfSSadaf Ebrahimi }
180*b7893ccfSSadaf Ebrahimi 
set_memory_type(const uint32_t type_bits,VkMemoryAllocateInfo * info,const VkFlags properties,const VkFlags forbid) const181*b7893ccfSSadaf Ebrahimi bool PhysicalDevice::set_memory_type(const uint32_t type_bits, VkMemoryAllocateInfo *info, const VkFlags properties,
182*b7893ccfSSadaf Ebrahimi                                      const VkFlags forbid) const {
183*b7893ccfSSadaf Ebrahimi     uint32_t type_mask = type_bits;
184*b7893ccfSSadaf Ebrahimi     // Search memtypes to find first index with those properties
185*b7893ccfSSadaf Ebrahimi     for (uint32_t i = 0; i < memory_properties_.memoryTypeCount; i++) {
186*b7893ccfSSadaf Ebrahimi         if ((type_mask & 1) == 1) {
187*b7893ccfSSadaf Ebrahimi             // Type is available, does it match user properties?
188*b7893ccfSSadaf Ebrahimi             if ((memory_properties_.memoryTypes[i].propertyFlags & properties) == properties &&
189*b7893ccfSSadaf Ebrahimi                 (memory_properties_.memoryTypes[i].propertyFlags & forbid) == 0) {
190*b7893ccfSSadaf Ebrahimi                 info->memoryTypeIndex = i;
191*b7893ccfSSadaf Ebrahimi                 return true;
192*b7893ccfSSadaf Ebrahimi             }
193*b7893ccfSSadaf Ebrahimi         }
194*b7893ccfSSadaf Ebrahimi         type_mask >>= 1;
195*b7893ccfSSadaf Ebrahimi     }
196*b7893ccfSSadaf Ebrahimi     // No memory types matched, return failure
197*b7893ccfSSadaf Ebrahimi     return false;
198*b7893ccfSSadaf Ebrahimi }
199*b7893ccfSSadaf Ebrahimi 
200*b7893ccfSSadaf Ebrahimi /*
201*b7893ccfSSadaf Ebrahimi  * Return list of PhysicalDevice layers
202*b7893ccfSSadaf Ebrahimi  */
layers() const203*b7893ccfSSadaf Ebrahimi std::vector<VkLayerProperties> PhysicalDevice::layers() const {
204*b7893ccfSSadaf Ebrahimi     std::vector<VkLayerProperties> layer_props;
205*b7893ccfSSadaf Ebrahimi     VkResult err;
206*b7893ccfSSadaf Ebrahimi 
207*b7893ccfSSadaf Ebrahimi     do {
208*b7893ccfSSadaf Ebrahimi         uint32_t layer_count = 0;
209*b7893ccfSSadaf Ebrahimi         err = vkEnumerateDeviceLayerProperties(handle(), &layer_count, NULL);
210*b7893ccfSSadaf Ebrahimi 
211*b7893ccfSSadaf Ebrahimi         if (err == VK_SUCCESS) {
212*b7893ccfSSadaf Ebrahimi             layer_props.reserve(layer_count);
213*b7893ccfSSadaf Ebrahimi             err = vkEnumerateDeviceLayerProperties(handle(), &layer_count, layer_props.data());
214*b7893ccfSSadaf Ebrahimi         }
215*b7893ccfSSadaf Ebrahimi     } while (err == VK_INCOMPLETE);
216*b7893ccfSSadaf Ebrahimi 
217*b7893ccfSSadaf Ebrahimi     assert(err == VK_SUCCESS);
218*b7893ccfSSadaf Ebrahimi 
219*b7893ccfSSadaf Ebrahimi     return layer_props;
220*b7893ccfSSadaf Ebrahimi }
221*b7893ccfSSadaf Ebrahimi 
QueueCreateInfoArray(const std::vector<VkQueueFamilyProperties> & queue_props)222*b7893ccfSSadaf Ebrahimi QueueCreateInfoArray::QueueCreateInfoArray(const std::vector<VkQueueFamilyProperties> &queue_props)
223*b7893ccfSSadaf Ebrahimi     : queue_info_(), queue_priorities_() {
224*b7893ccfSSadaf Ebrahimi     queue_info_.reserve(queue_props.size());
225*b7893ccfSSadaf Ebrahimi 
226*b7893ccfSSadaf Ebrahimi     for (uint32_t i = 0; i < (uint32_t)queue_props.size(); ++i) {
227*b7893ccfSSadaf Ebrahimi         if (queue_props[i].queueCount > 0) {
228*b7893ccfSSadaf Ebrahimi             VkDeviceQueueCreateInfo qi = {};
229*b7893ccfSSadaf Ebrahimi             qi.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
230*b7893ccfSSadaf Ebrahimi             qi.pNext = NULL;
231*b7893ccfSSadaf Ebrahimi             qi.queueFamilyIndex = i;
232*b7893ccfSSadaf Ebrahimi             qi.queueCount = queue_props[i].queueCount;
233*b7893ccfSSadaf Ebrahimi             queue_priorities_.emplace_back(qi.queueCount, 0.0f);
234*b7893ccfSSadaf Ebrahimi             qi.pQueuePriorities = queue_priorities_[i].data();
235*b7893ccfSSadaf Ebrahimi             queue_info_.push_back(qi);
236*b7893ccfSSadaf Ebrahimi         }
237*b7893ccfSSadaf Ebrahimi     }
238*b7893ccfSSadaf Ebrahimi }
239*b7893ccfSSadaf Ebrahimi 
~Device()240*b7893ccfSSadaf Ebrahimi Device::~Device() {
241*b7893ccfSSadaf Ebrahimi     if (!initialized()) return;
242*b7893ccfSSadaf Ebrahimi 
243*b7893ccfSSadaf Ebrahimi     vkDestroyDevice(handle(), NULL);
244*b7893ccfSSadaf Ebrahimi }
245*b7893ccfSSadaf Ebrahimi 
init(std::vector<const char * > & extensions,VkPhysicalDeviceFeatures * features,void * create_device_pnext)246*b7893ccfSSadaf Ebrahimi void Device::init(std::vector<const char *> &extensions, VkPhysicalDeviceFeatures *features, void *create_device_pnext) {
247*b7893ccfSSadaf Ebrahimi     // request all queues
248*b7893ccfSSadaf Ebrahimi     const std::vector<VkQueueFamilyProperties> queue_props = phy_.queue_properties();
249*b7893ccfSSadaf Ebrahimi     QueueCreateInfoArray queue_info(phy_.queue_properties());
250*b7893ccfSSadaf Ebrahimi     for (uint32_t i = 0; i < (uint32_t)queue_props.size(); i++) {
251*b7893ccfSSadaf Ebrahimi         if (queue_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
252*b7893ccfSSadaf Ebrahimi             graphics_queue_node_index_ = i;
253*b7893ccfSSadaf Ebrahimi             break;
254*b7893ccfSSadaf Ebrahimi         }
255*b7893ccfSSadaf Ebrahimi     }
256*b7893ccfSSadaf Ebrahimi     // Only request creation with queuefamilies that have at least one queue
257*b7893ccfSSadaf Ebrahimi     std::vector<VkDeviceQueueCreateInfo> create_queue_infos;
258*b7893ccfSSadaf Ebrahimi     auto qci = queue_info.data();
259*b7893ccfSSadaf Ebrahimi     for (uint32_t j = 0; j < queue_info.size(); ++j) {
260*b7893ccfSSadaf Ebrahimi         if (qci[j].queueCount) {
261*b7893ccfSSadaf Ebrahimi             create_queue_infos.push_back(qci[j]);
262*b7893ccfSSadaf Ebrahimi         }
263*b7893ccfSSadaf Ebrahimi     }
264*b7893ccfSSadaf Ebrahimi 
265*b7893ccfSSadaf Ebrahimi     enabled_extensions_ = extensions;
266*b7893ccfSSadaf Ebrahimi 
267*b7893ccfSSadaf Ebrahimi     VkDeviceCreateInfo dev_info = {};
268*b7893ccfSSadaf Ebrahimi     dev_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
269*b7893ccfSSadaf Ebrahimi     dev_info.pNext = create_device_pnext;
270*b7893ccfSSadaf Ebrahimi     dev_info.queueCreateInfoCount = create_queue_infos.size();
271*b7893ccfSSadaf Ebrahimi     dev_info.pQueueCreateInfos = create_queue_infos.data();
272*b7893ccfSSadaf Ebrahimi     dev_info.enabledLayerCount = 0;
273*b7893ccfSSadaf Ebrahimi     dev_info.ppEnabledLayerNames = NULL;
274*b7893ccfSSadaf Ebrahimi     dev_info.enabledExtensionCount = extensions.size();
275*b7893ccfSSadaf Ebrahimi     dev_info.ppEnabledExtensionNames = extensions.data();
276*b7893ccfSSadaf Ebrahimi 
277*b7893ccfSSadaf Ebrahimi     VkPhysicalDeviceFeatures all_features;
278*b7893ccfSSadaf Ebrahimi     // Let VkPhysicalDeviceFeatures2 take priority over VkPhysicalDeviceFeatures,
279*b7893ccfSSadaf Ebrahimi     // since it supports extensions
280*b7893ccfSSadaf Ebrahimi 
281*b7893ccfSSadaf Ebrahimi     if (!(lvl_find_in_chain<VkPhysicalDeviceFeatures2>(dev_info.pNext))) {
282*b7893ccfSSadaf Ebrahimi         if (features) {
283*b7893ccfSSadaf Ebrahimi             dev_info.pEnabledFeatures = features;
284*b7893ccfSSadaf Ebrahimi         } else {
285*b7893ccfSSadaf Ebrahimi             // request all supportable features enabled
286*b7893ccfSSadaf Ebrahimi             all_features = phy().features();
287*b7893ccfSSadaf Ebrahimi             dev_info.pEnabledFeatures = &all_features;
288*b7893ccfSSadaf Ebrahimi         }
289*b7893ccfSSadaf Ebrahimi     }
290*b7893ccfSSadaf Ebrahimi 
291*b7893ccfSSadaf Ebrahimi     init(dev_info);
292*b7893ccfSSadaf Ebrahimi }
293*b7893ccfSSadaf Ebrahimi 
init(const VkDeviceCreateInfo & info)294*b7893ccfSSadaf Ebrahimi void Device::init(const VkDeviceCreateInfo &info) {
295*b7893ccfSSadaf Ebrahimi     VkDevice dev;
296*b7893ccfSSadaf Ebrahimi 
297*b7893ccfSSadaf Ebrahimi     if (EXPECT(vkCreateDevice(phy_.handle(), &info, NULL, &dev) == VK_SUCCESS)) Handle::init(dev);
298*b7893ccfSSadaf Ebrahimi 
299*b7893ccfSSadaf Ebrahimi     init_queues();
300*b7893ccfSSadaf Ebrahimi     init_formats();
301*b7893ccfSSadaf Ebrahimi }
302*b7893ccfSSadaf Ebrahimi 
init_queues()303*b7893ccfSSadaf Ebrahimi void Device::init_queues() {
304*b7893ccfSSadaf Ebrahimi     uint32_t queue_node_count;
305*b7893ccfSSadaf Ebrahimi 
306*b7893ccfSSadaf Ebrahimi     // Call with NULL data to get count
307*b7893ccfSSadaf Ebrahimi     vkGetPhysicalDeviceQueueFamilyProperties(phy_.handle(), &queue_node_count, NULL);
308*b7893ccfSSadaf Ebrahimi     EXPECT(queue_node_count >= 1);
309*b7893ccfSSadaf Ebrahimi 
310*b7893ccfSSadaf Ebrahimi     VkQueueFamilyProperties *queue_props = new VkQueueFamilyProperties[queue_node_count];
311*b7893ccfSSadaf Ebrahimi 
312*b7893ccfSSadaf Ebrahimi     vkGetPhysicalDeviceQueueFamilyProperties(phy_.handle(), &queue_node_count, queue_props);
313*b7893ccfSSadaf Ebrahimi 
314*b7893ccfSSadaf Ebrahimi     queue_families_.resize(queue_node_count);
315*b7893ccfSSadaf Ebrahimi     for (uint32_t i = 0; i < queue_node_count; i++) {
316*b7893ccfSSadaf Ebrahimi         VkQueue queue;
317*b7893ccfSSadaf Ebrahimi 
318*b7893ccfSSadaf Ebrahimi         QueueFamilyQueues &queue_storage = queue_families_[i];
319*b7893ccfSSadaf Ebrahimi         queue_storage.reserve(queue_props[i].queueCount);
320*b7893ccfSSadaf Ebrahimi         for (uint32_t j = 0; j < queue_props[i].queueCount; j++) {
321*b7893ccfSSadaf Ebrahimi             // TODO: Need to add support for separate MEMMGR and work queues,
322*b7893ccfSSadaf Ebrahimi             // including synchronization
323*b7893ccfSSadaf Ebrahimi             vkGetDeviceQueue(handle(), i, j, &queue);
324*b7893ccfSSadaf Ebrahimi 
325*b7893ccfSSadaf Ebrahimi             // Store single copy of the queue object that will self destruct
326*b7893ccfSSadaf Ebrahimi             queue_storage.emplace_back(new Queue(queue, i));
327*b7893ccfSSadaf Ebrahimi 
328*b7893ccfSSadaf Ebrahimi             if (queue_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
329*b7893ccfSSadaf Ebrahimi                 queues_[GRAPHICS].push_back(queue_storage.back().get());
330*b7893ccfSSadaf Ebrahimi             }
331*b7893ccfSSadaf Ebrahimi 
332*b7893ccfSSadaf Ebrahimi             if (queue_props[i].queueFlags & VK_QUEUE_COMPUTE_BIT) {
333*b7893ccfSSadaf Ebrahimi                 queues_[COMPUTE].push_back(queue_storage.back().get());
334*b7893ccfSSadaf Ebrahimi             }
335*b7893ccfSSadaf Ebrahimi 
336*b7893ccfSSadaf Ebrahimi             if (queue_props[i].queueFlags & VK_QUEUE_TRANSFER_BIT) {
337*b7893ccfSSadaf Ebrahimi                 queues_[DMA].push_back(queue_storage.back().get());
338*b7893ccfSSadaf Ebrahimi             }
339*b7893ccfSSadaf Ebrahimi         }
340*b7893ccfSSadaf Ebrahimi     }
341*b7893ccfSSadaf Ebrahimi 
342*b7893ccfSSadaf Ebrahimi     delete[] queue_props;
343*b7893ccfSSadaf Ebrahimi 
344*b7893ccfSSadaf Ebrahimi     EXPECT(!queues_[GRAPHICS].empty() || !queues_[COMPUTE].empty());
345*b7893ccfSSadaf Ebrahimi }
queue_family_queues(uint32_t queue_family) const346*b7893ccfSSadaf Ebrahimi const Device::QueueFamilyQueues &Device::queue_family_queues(uint32_t queue_family) const {
347*b7893ccfSSadaf Ebrahimi     assert(queue_family < queue_families_.size());
348*b7893ccfSSadaf Ebrahimi     return queue_families_[queue_family];
349*b7893ccfSSadaf Ebrahimi }
350*b7893ccfSSadaf Ebrahimi 
init_formats()351*b7893ccfSSadaf Ebrahimi void Device::init_formats() {
352*b7893ccfSSadaf Ebrahimi     for (int f = VK_FORMAT_BEGIN_RANGE; f <= VK_FORMAT_END_RANGE; f++) {
353*b7893ccfSSadaf Ebrahimi         const VkFormat fmt = static_cast<VkFormat>(f);
354*b7893ccfSSadaf Ebrahimi         const VkFormatProperties props = format_properties(fmt);
355*b7893ccfSSadaf Ebrahimi 
356*b7893ccfSSadaf Ebrahimi         if (props.linearTilingFeatures) {
357*b7893ccfSSadaf Ebrahimi             const Format tmp = {fmt, VK_IMAGE_TILING_LINEAR, props.linearTilingFeatures};
358*b7893ccfSSadaf Ebrahimi             formats_.push_back(tmp);
359*b7893ccfSSadaf Ebrahimi         }
360*b7893ccfSSadaf Ebrahimi 
361*b7893ccfSSadaf Ebrahimi         if (props.optimalTilingFeatures) {
362*b7893ccfSSadaf Ebrahimi             const Format tmp = {fmt, VK_IMAGE_TILING_OPTIMAL, props.optimalTilingFeatures};
363*b7893ccfSSadaf Ebrahimi             formats_.push_back(tmp);
364*b7893ccfSSadaf Ebrahimi         }
365*b7893ccfSSadaf Ebrahimi     }
366*b7893ccfSSadaf Ebrahimi 
367*b7893ccfSSadaf Ebrahimi     EXPECT(!formats_.empty());
368*b7893ccfSSadaf Ebrahimi }
369*b7893ccfSSadaf Ebrahimi 
IsEnabledExtension(const char * extension)370*b7893ccfSSadaf Ebrahimi bool Device::IsEnabledExtension(const char *extension) {
371*b7893ccfSSadaf Ebrahimi     const auto is_x = [&extension](const char *enabled_extension) { return strcmp(extension, enabled_extension) == 0; };
372*b7893ccfSSadaf Ebrahimi     return std::any_of(enabled_extensions_.begin(), enabled_extensions_.end(), is_x);
373*b7893ccfSSadaf Ebrahimi }
374*b7893ccfSSadaf Ebrahimi 
format_properties(VkFormat format)375*b7893ccfSSadaf Ebrahimi VkFormatProperties Device::format_properties(VkFormat format) {
376*b7893ccfSSadaf Ebrahimi     VkFormatProperties data;
377*b7893ccfSSadaf Ebrahimi     vkGetPhysicalDeviceFormatProperties(phy().handle(), format, &data);
378*b7893ccfSSadaf Ebrahimi 
379*b7893ccfSSadaf Ebrahimi     return data;
380*b7893ccfSSadaf Ebrahimi }
381*b7893ccfSSadaf Ebrahimi 
wait()382*b7893ccfSSadaf Ebrahimi void Device::wait() { EXPECT(vkDeviceWaitIdle(handle()) == VK_SUCCESS); }
383*b7893ccfSSadaf Ebrahimi 
wait(const std::vector<const Fence * > & fences,bool wait_all,uint64_t timeout)384*b7893ccfSSadaf Ebrahimi VkResult Device::wait(const std::vector<const Fence *> &fences, bool wait_all, uint64_t timeout) {
385*b7893ccfSSadaf Ebrahimi     const std::vector<VkFence> fence_handles = MakeVkHandles<VkFence>(fences);
386*b7893ccfSSadaf Ebrahimi     VkResult err = vkWaitForFences(handle(), fence_handles.size(), fence_handles.data(), wait_all, timeout);
387*b7893ccfSSadaf Ebrahimi     EXPECT(err == VK_SUCCESS || err == VK_TIMEOUT);
388*b7893ccfSSadaf Ebrahimi 
389*b7893ccfSSadaf Ebrahimi     return err;
390*b7893ccfSSadaf Ebrahimi }
391*b7893ccfSSadaf Ebrahimi 
update_descriptor_sets(const std::vector<VkWriteDescriptorSet> & writes,const std::vector<VkCopyDescriptorSet> & copies)392*b7893ccfSSadaf Ebrahimi void Device::update_descriptor_sets(const std::vector<VkWriteDescriptorSet> &writes,
393*b7893ccfSSadaf Ebrahimi                                     const std::vector<VkCopyDescriptorSet> &copies) {
394*b7893ccfSSadaf Ebrahimi     vkUpdateDescriptorSets(handle(), writes.size(), writes.data(), copies.size(), copies.data());
395*b7893ccfSSadaf Ebrahimi }
396*b7893ccfSSadaf Ebrahimi 
submit(const std::vector<const CommandBuffer * > & cmds,const Fence & fence,bool expect_success)397*b7893ccfSSadaf Ebrahimi VkResult Queue::submit(const std::vector<const CommandBuffer *> &cmds, const Fence &fence, bool expect_success) {
398*b7893ccfSSadaf Ebrahimi     const std::vector<VkCommandBuffer> cmd_handles = MakeVkHandles<VkCommandBuffer>(cmds);
399*b7893ccfSSadaf Ebrahimi     VkSubmitInfo submit_info;
400*b7893ccfSSadaf Ebrahimi     submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
401*b7893ccfSSadaf Ebrahimi     submit_info.pNext = NULL;
402*b7893ccfSSadaf Ebrahimi     submit_info.waitSemaphoreCount = 0;
403*b7893ccfSSadaf Ebrahimi     submit_info.pWaitSemaphores = NULL;
404*b7893ccfSSadaf Ebrahimi     submit_info.pWaitDstStageMask = NULL;
405*b7893ccfSSadaf Ebrahimi     submit_info.commandBufferCount = (uint32_t)cmd_handles.size();
406*b7893ccfSSadaf Ebrahimi     submit_info.pCommandBuffers = cmd_handles.data();
407*b7893ccfSSadaf Ebrahimi     submit_info.signalSemaphoreCount = 0;
408*b7893ccfSSadaf Ebrahimi     submit_info.pSignalSemaphores = NULL;
409*b7893ccfSSadaf Ebrahimi 
410*b7893ccfSSadaf Ebrahimi     VkResult result = vkQueueSubmit(handle(), 1, &submit_info, fence.handle());
411*b7893ccfSSadaf Ebrahimi     if (expect_success) EXPECT(result == VK_SUCCESS);
412*b7893ccfSSadaf Ebrahimi     return result;
413*b7893ccfSSadaf Ebrahimi }
414*b7893ccfSSadaf Ebrahimi 
submit(const CommandBuffer & cmd,const Fence & fence,bool expect_success)415*b7893ccfSSadaf Ebrahimi VkResult Queue::submit(const CommandBuffer &cmd, const Fence &fence, bool expect_success) {
416*b7893ccfSSadaf Ebrahimi     return submit(std::vector<const CommandBuffer *>(1, &cmd), fence, expect_success);
417*b7893ccfSSadaf Ebrahimi }
418*b7893ccfSSadaf Ebrahimi 
submit(const CommandBuffer & cmd,bool expect_success)419*b7893ccfSSadaf Ebrahimi VkResult Queue::submit(const CommandBuffer &cmd, bool expect_success) {
420*b7893ccfSSadaf Ebrahimi     Fence fence;
421*b7893ccfSSadaf Ebrahimi     return submit(cmd, fence);
422*b7893ccfSSadaf Ebrahimi }
423*b7893ccfSSadaf Ebrahimi 
wait()424*b7893ccfSSadaf Ebrahimi VkResult Queue::wait() {
425*b7893ccfSSadaf Ebrahimi     VkResult result = vkQueueWaitIdle(handle());
426*b7893ccfSSadaf Ebrahimi     EXPECT(result == VK_SUCCESS);
427*b7893ccfSSadaf Ebrahimi     return result;
428*b7893ccfSSadaf Ebrahimi }
429*b7893ccfSSadaf Ebrahimi 
~DeviceMemory()430*b7893ccfSSadaf Ebrahimi DeviceMemory::~DeviceMemory() {
431*b7893ccfSSadaf Ebrahimi     if (initialized()) vkFreeMemory(device(), handle(), NULL);
432*b7893ccfSSadaf Ebrahimi }
433*b7893ccfSSadaf Ebrahimi 
init(const Device & dev,const VkMemoryAllocateInfo & info)434*b7893ccfSSadaf Ebrahimi void DeviceMemory::init(const Device &dev, const VkMemoryAllocateInfo &info) {
435*b7893ccfSSadaf Ebrahimi     NON_DISPATCHABLE_HANDLE_INIT(vkAllocateMemory, dev, &info);
436*b7893ccfSSadaf Ebrahimi }
437*b7893ccfSSadaf Ebrahimi 
map(VkFlags flags) const438*b7893ccfSSadaf Ebrahimi const void *DeviceMemory::map(VkFlags flags) const {
439*b7893ccfSSadaf Ebrahimi     void *data;
440*b7893ccfSSadaf Ebrahimi     if (!EXPECT(vkMapMemory(device(), handle(), 0, VK_WHOLE_SIZE, flags, &data) == VK_SUCCESS)) data = NULL;
441*b7893ccfSSadaf Ebrahimi 
442*b7893ccfSSadaf Ebrahimi     return data;
443*b7893ccfSSadaf Ebrahimi }
444*b7893ccfSSadaf Ebrahimi 
map(VkFlags flags)445*b7893ccfSSadaf Ebrahimi void *DeviceMemory::map(VkFlags flags) {
446*b7893ccfSSadaf Ebrahimi     void *data;
447*b7893ccfSSadaf Ebrahimi     if (!EXPECT(vkMapMemory(device(), handle(), 0, VK_WHOLE_SIZE, flags, &data) == VK_SUCCESS)) data = NULL;
448*b7893ccfSSadaf Ebrahimi 
449*b7893ccfSSadaf Ebrahimi     return data;
450*b7893ccfSSadaf Ebrahimi }
451*b7893ccfSSadaf Ebrahimi 
unmap() const452*b7893ccfSSadaf Ebrahimi void DeviceMemory::unmap() const { vkUnmapMemory(device(), handle()); }
453*b7893ccfSSadaf Ebrahimi 
get_resource_alloc_info(const Device & dev,const VkMemoryRequirements & reqs,VkMemoryPropertyFlags mem_props)454*b7893ccfSSadaf Ebrahimi VkMemoryAllocateInfo DeviceMemory::get_resource_alloc_info(const Device &dev, const VkMemoryRequirements &reqs,
455*b7893ccfSSadaf Ebrahimi                                                            VkMemoryPropertyFlags mem_props) {
456*b7893ccfSSadaf Ebrahimi     // Find appropriate memory type for given reqs
457*b7893ccfSSadaf Ebrahimi     VkPhysicalDeviceMemoryProperties dev_mem_props = dev.phy().memory_properties();
458*b7893ccfSSadaf Ebrahimi     uint32_t mem_type_index = 0;
459*b7893ccfSSadaf Ebrahimi     for (mem_type_index = 0; mem_type_index < dev_mem_props.memoryTypeCount; ++mem_type_index) {
460*b7893ccfSSadaf Ebrahimi         if (mem_props == (mem_props & dev_mem_props.memoryTypes[mem_type_index].propertyFlags)) break;
461*b7893ccfSSadaf Ebrahimi     }
462*b7893ccfSSadaf Ebrahimi     // If we exceeded types, then this device doesn't have the memory we need
463*b7893ccfSSadaf Ebrahimi     assert(mem_type_index < dev_mem_props.memoryTypeCount);
464*b7893ccfSSadaf Ebrahimi     VkMemoryAllocateInfo info = alloc_info(reqs.size, mem_type_index);
465*b7893ccfSSadaf Ebrahimi     EXPECT(dev.phy().set_memory_type(reqs.memoryTypeBits, &info, mem_props));
466*b7893ccfSSadaf Ebrahimi     return info;
467*b7893ccfSSadaf Ebrahimi }
468*b7893ccfSSadaf Ebrahimi 
NON_DISPATCHABLE_HANDLE_DTOR(Fence,vkDestroyFence)469*b7893ccfSSadaf Ebrahimi NON_DISPATCHABLE_HANDLE_DTOR(Fence, vkDestroyFence)
470*b7893ccfSSadaf Ebrahimi 
471*b7893ccfSSadaf Ebrahimi void Fence::init(const Device &dev, const VkFenceCreateInfo &info) { NON_DISPATCHABLE_HANDLE_INIT(vkCreateFence, dev, &info); }
472*b7893ccfSSadaf Ebrahimi 
wait(VkBool32 wait_all,uint64_t timeout) const473*b7893ccfSSadaf Ebrahimi VkResult Fence::wait(VkBool32 wait_all, uint64_t timeout) const {
474*b7893ccfSSadaf Ebrahimi     VkFence fence = handle();
475*b7893ccfSSadaf Ebrahimi     return vkWaitForFences(device(), 1, &fence, wait_all, timeout);
476*b7893ccfSSadaf Ebrahimi }
477*b7893ccfSSadaf Ebrahimi 
NON_DISPATCHABLE_HANDLE_DTOR(Semaphore,vkDestroySemaphore)478*b7893ccfSSadaf Ebrahimi NON_DISPATCHABLE_HANDLE_DTOR(Semaphore, vkDestroySemaphore)
479*b7893ccfSSadaf Ebrahimi 
480*b7893ccfSSadaf Ebrahimi void Semaphore::init(const Device &dev, const VkSemaphoreCreateInfo &info) {
481*b7893ccfSSadaf Ebrahimi     NON_DISPATCHABLE_HANDLE_INIT(vkCreateSemaphore, dev, &info);
482*b7893ccfSSadaf Ebrahimi }
483*b7893ccfSSadaf Ebrahimi 
NON_DISPATCHABLE_HANDLE_DTOR(Event,vkDestroyEvent)484*b7893ccfSSadaf Ebrahimi NON_DISPATCHABLE_HANDLE_DTOR(Event, vkDestroyEvent)
485*b7893ccfSSadaf Ebrahimi 
486*b7893ccfSSadaf Ebrahimi void Event::init(const Device &dev, const VkEventCreateInfo &info) { NON_DISPATCHABLE_HANDLE_INIT(vkCreateEvent, dev, &info); }
487*b7893ccfSSadaf Ebrahimi 
set()488*b7893ccfSSadaf Ebrahimi void Event::set() { EXPECT(vkSetEvent(device(), handle()) == VK_SUCCESS); }
489*b7893ccfSSadaf Ebrahimi 
reset()490*b7893ccfSSadaf Ebrahimi void Event::reset() { EXPECT(vkResetEvent(device(), handle()) == VK_SUCCESS); }
491*b7893ccfSSadaf Ebrahimi 
NON_DISPATCHABLE_HANDLE_DTOR(QueryPool,vkDestroyQueryPool)492*b7893ccfSSadaf Ebrahimi NON_DISPATCHABLE_HANDLE_DTOR(QueryPool, vkDestroyQueryPool)
493*b7893ccfSSadaf Ebrahimi 
494*b7893ccfSSadaf Ebrahimi void QueryPool::init(const Device &dev, const VkQueryPoolCreateInfo &info) {
495*b7893ccfSSadaf Ebrahimi     NON_DISPATCHABLE_HANDLE_INIT(vkCreateQueryPool, dev, &info);
496*b7893ccfSSadaf Ebrahimi }
497*b7893ccfSSadaf Ebrahimi 
results(uint32_t first,uint32_t count,size_t size,void * data,size_t stride)498*b7893ccfSSadaf Ebrahimi VkResult QueryPool::results(uint32_t first, uint32_t count, size_t size, void *data, size_t stride) {
499*b7893ccfSSadaf Ebrahimi     VkResult err = vkGetQueryPoolResults(device(), handle(), first, count, size, data, stride, 0);
500*b7893ccfSSadaf Ebrahimi     EXPECT(err == VK_SUCCESS || err == VK_NOT_READY);
501*b7893ccfSSadaf Ebrahimi 
502*b7893ccfSSadaf Ebrahimi     return err;
503*b7893ccfSSadaf Ebrahimi }
504*b7893ccfSSadaf Ebrahimi 
NON_DISPATCHABLE_HANDLE_DTOR(Buffer,vkDestroyBuffer)505*b7893ccfSSadaf Ebrahimi NON_DISPATCHABLE_HANDLE_DTOR(Buffer, vkDestroyBuffer)
506*b7893ccfSSadaf Ebrahimi 
507*b7893ccfSSadaf Ebrahimi void Buffer::init(const Device &dev, const VkBufferCreateInfo &info, VkMemoryPropertyFlags mem_props) {
508*b7893ccfSSadaf Ebrahimi     init_no_mem(dev, info);
509*b7893ccfSSadaf Ebrahimi 
510*b7893ccfSSadaf Ebrahimi     internal_mem_.init(dev, DeviceMemory::get_resource_alloc_info(dev, memory_requirements(), mem_props));
511*b7893ccfSSadaf Ebrahimi     bind_memory(internal_mem_, 0);
512*b7893ccfSSadaf Ebrahimi }
513*b7893ccfSSadaf Ebrahimi 
init_no_mem(const Device & dev,const VkBufferCreateInfo & info)514*b7893ccfSSadaf Ebrahimi void Buffer::init_no_mem(const Device &dev, const VkBufferCreateInfo &info) {
515*b7893ccfSSadaf Ebrahimi     NON_DISPATCHABLE_HANDLE_INIT(vkCreateBuffer, dev, &info);
516*b7893ccfSSadaf Ebrahimi     create_info_ = info;
517*b7893ccfSSadaf Ebrahimi }
518*b7893ccfSSadaf Ebrahimi 
memory_requirements() const519*b7893ccfSSadaf Ebrahimi VkMemoryRequirements Buffer::memory_requirements() const {
520*b7893ccfSSadaf Ebrahimi     VkMemoryRequirements reqs;
521*b7893ccfSSadaf Ebrahimi 
522*b7893ccfSSadaf Ebrahimi     vkGetBufferMemoryRequirements(device(), handle(), &reqs);
523*b7893ccfSSadaf Ebrahimi 
524*b7893ccfSSadaf Ebrahimi     return reqs;
525*b7893ccfSSadaf Ebrahimi }
526*b7893ccfSSadaf Ebrahimi 
bind_memory(const DeviceMemory & mem,VkDeviceSize mem_offset)527*b7893ccfSSadaf Ebrahimi void Buffer::bind_memory(const DeviceMemory &mem, VkDeviceSize mem_offset) {
528*b7893ccfSSadaf Ebrahimi     EXPECT(vkBindBufferMemory(device(), handle(), mem.handle(), mem_offset) == VK_SUCCESS);
529*b7893ccfSSadaf Ebrahimi }
530*b7893ccfSSadaf Ebrahimi 
NON_DISPATCHABLE_HANDLE_DTOR(BufferView,vkDestroyBufferView)531*b7893ccfSSadaf Ebrahimi NON_DISPATCHABLE_HANDLE_DTOR(BufferView, vkDestroyBufferView)
532*b7893ccfSSadaf Ebrahimi 
533*b7893ccfSSadaf Ebrahimi void BufferView::init(const Device &dev, const VkBufferViewCreateInfo &info) {
534*b7893ccfSSadaf Ebrahimi     NON_DISPATCHABLE_HANDLE_INIT(vkCreateBufferView, dev, &info);
535*b7893ccfSSadaf Ebrahimi }
536*b7893ccfSSadaf Ebrahimi 
NON_DISPATCHABLE_HANDLE_DTOR(Image,vkDestroyImage)537*b7893ccfSSadaf Ebrahimi NON_DISPATCHABLE_HANDLE_DTOR(Image, vkDestroyImage)
538*b7893ccfSSadaf Ebrahimi 
539*b7893ccfSSadaf Ebrahimi void Image::init(const Device &dev, const VkImageCreateInfo &info, VkMemoryPropertyFlags mem_props) {
540*b7893ccfSSadaf Ebrahimi     init_no_mem(dev, info);
541*b7893ccfSSadaf Ebrahimi 
542*b7893ccfSSadaf Ebrahimi     if (initialized()) {
543*b7893ccfSSadaf Ebrahimi         internal_mem_.init(dev, DeviceMemory::get_resource_alloc_info(dev, memory_requirements(), mem_props));
544*b7893ccfSSadaf Ebrahimi         bind_memory(internal_mem_, 0);
545*b7893ccfSSadaf Ebrahimi     }
546*b7893ccfSSadaf Ebrahimi }
547*b7893ccfSSadaf Ebrahimi 
init_no_mem(const Device & dev,const VkImageCreateInfo & info)548*b7893ccfSSadaf Ebrahimi void Image::init_no_mem(const Device &dev, const VkImageCreateInfo &info) {
549*b7893ccfSSadaf Ebrahimi     NON_DISPATCHABLE_HANDLE_INIT(vkCreateImage, dev, &info);
550*b7893ccfSSadaf Ebrahimi     if (initialized()) {
551*b7893ccfSSadaf Ebrahimi         init_info(dev, info);
552*b7893ccfSSadaf Ebrahimi     }
553*b7893ccfSSadaf Ebrahimi }
554*b7893ccfSSadaf Ebrahimi 
init_info(const Device & dev,const VkImageCreateInfo & info)555*b7893ccfSSadaf Ebrahimi void Image::init_info(const Device &dev, const VkImageCreateInfo &info) {
556*b7893ccfSSadaf Ebrahimi     create_info_ = info;
557*b7893ccfSSadaf Ebrahimi 
558*b7893ccfSSadaf Ebrahimi     for (std::vector<Device::Format>::const_iterator it = dev.formats().begin(); it != dev.formats().end(); it++) {
559*b7893ccfSSadaf Ebrahimi         if (memcmp(&it->format, &create_info_.format, sizeof(it->format)) == 0 && it->tiling == create_info_.tiling) {
560*b7893ccfSSadaf Ebrahimi             format_features_ = it->features;
561*b7893ccfSSadaf Ebrahimi             break;
562*b7893ccfSSadaf Ebrahimi         }
563*b7893ccfSSadaf Ebrahimi     }
564*b7893ccfSSadaf Ebrahimi }
565*b7893ccfSSadaf Ebrahimi 
memory_requirements() const566*b7893ccfSSadaf Ebrahimi VkMemoryRequirements Image::memory_requirements() const {
567*b7893ccfSSadaf Ebrahimi     VkMemoryRequirements reqs;
568*b7893ccfSSadaf Ebrahimi 
569*b7893ccfSSadaf Ebrahimi     vkGetImageMemoryRequirements(device(), handle(), &reqs);
570*b7893ccfSSadaf Ebrahimi 
571*b7893ccfSSadaf Ebrahimi     return reqs;
572*b7893ccfSSadaf Ebrahimi }
573*b7893ccfSSadaf Ebrahimi 
bind_memory(const DeviceMemory & mem,VkDeviceSize mem_offset)574*b7893ccfSSadaf Ebrahimi void Image::bind_memory(const DeviceMemory &mem, VkDeviceSize mem_offset) {
575*b7893ccfSSadaf Ebrahimi     EXPECT(vkBindImageMemory(device(), handle(), mem.handle(), mem_offset) == VK_SUCCESS);
576*b7893ccfSSadaf Ebrahimi }
577*b7893ccfSSadaf Ebrahimi 
subresource_layout(const VkImageSubresource & subres) const578*b7893ccfSSadaf Ebrahimi VkSubresourceLayout Image::subresource_layout(const VkImageSubresource &subres) const {
579*b7893ccfSSadaf Ebrahimi     VkSubresourceLayout data;
580*b7893ccfSSadaf Ebrahimi     size_t size = sizeof(data);
581*b7893ccfSSadaf Ebrahimi     vkGetImageSubresourceLayout(device(), handle(), &subres, &data);
582*b7893ccfSSadaf Ebrahimi     if (size != sizeof(data)) memset(&data, 0, sizeof(data));
583*b7893ccfSSadaf Ebrahimi 
584*b7893ccfSSadaf Ebrahimi     return data;
585*b7893ccfSSadaf Ebrahimi }
586*b7893ccfSSadaf Ebrahimi 
subresource_layout(const VkImageSubresourceLayers & subrescopy) const587*b7893ccfSSadaf Ebrahimi VkSubresourceLayout Image::subresource_layout(const VkImageSubresourceLayers &subrescopy) const {
588*b7893ccfSSadaf Ebrahimi     VkSubresourceLayout data;
589*b7893ccfSSadaf Ebrahimi     VkImageSubresource subres = subresource(subrescopy.aspectMask, subrescopy.mipLevel, subrescopy.baseArrayLayer);
590*b7893ccfSSadaf Ebrahimi     size_t size = sizeof(data);
591*b7893ccfSSadaf Ebrahimi     vkGetImageSubresourceLayout(device(), handle(), &subres, &data);
592*b7893ccfSSadaf Ebrahimi     if (size != sizeof(data)) memset(&data, 0, sizeof(data));
593*b7893ccfSSadaf Ebrahimi 
594*b7893ccfSSadaf Ebrahimi     return data;
595*b7893ccfSSadaf Ebrahimi }
596*b7893ccfSSadaf Ebrahimi 
transparent() const597*b7893ccfSSadaf Ebrahimi bool Image::transparent() const {
598*b7893ccfSSadaf Ebrahimi     return (create_info_.tiling == VK_IMAGE_TILING_LINEAR && create_info_.samples == VK_SAMPLE_COUNT_1_BIT &&
599*b7893ccfSSadaf Ebrahimi             !(create_info_.usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)));
600*b7893ccfSSadaf Ebrahimi }
601*b7893ccfSSadaf Ebrahimi 
NON_DISPATCHABLE_HANDLE_DTOR(ImageView,vkDestroyImageView)602*b7893ccfSSadaf Ebrahimi NON_DISPATCHABLE_HANDLE_DTOR(ImageView, vkDestroyImageView)
603*b7893ccfSSadaf Ebrahimi 
604*b7893ccfSSadaf Ebrahimi void ImageView::init(const Device &dev, const VkImageViewCreateInfo &info) {
605*b7893ccfSSadaf Ebrahimi     NON_DISPATCHABLE_HANDLE_INIT(vkCreateImageView, dev, &info);
606*b7893ccfSSadaf Ebrahimi }
607*b7893ccfSSadaf Ebrahimi 
~AccelerationStructure()608*b7893ccfSSadaf Ebrahimi AccelerationStructure::~AccelerationStructure() {
609*b7893ccfSSadaf Ebrahimi     if (initialized()) {
610*b7893ccfSSadaf Ebrahimi         PFN_vkDestroyAccelerationStructureNV vkDestroyAccelerationStructureNV =
611*b7893ccfSSadaf Ebrahimi             (PFN_vkDestroyAccelerationStructureNV)vkGetDeviceProcAddr(device(), "vkDestroyAccelerationStructureNV");
612*b7893ccfSSadaf Ebrahimi         assert(vkDestroyAccelerationStructureNV != nullptr);
613*b7893ccfSSadaf Ebrahimi 
614*b7893ccfSSadaf Ebrahimi         vkDestroyAccelerationStructureNV(device(), handle(), nullptr);
615*b7893ccfSSadaf Ebrahimi     }
616*b7893ccfSSadaf Ebrahimi }
617*b7893ccfSSadaf Ebrahimi 
memory_requirements() const618*b7893ccfSSadaf Ebrahimi VkMemoryRequirements2 AccelerationStructure::memory_requirements() const {
619*b7893ccfSSadaf Ebrahimi     PFN_vkGetAccelerationStructureMemoryRequirementsNV vkGetAccelerationStructureMemoryRequirementsNV =
620*b7893ccfSSadaf Ebrahimi         (PFN_vkGetAccelerationStructureMemoryRequirementsNV)vkGetDeviceProcAddr(device(),
621*b7893ccfSSadaf Ebrahimi                                                                                 "vkGetAccelerationStructureMemoryRequirementsNV");
622*b7893ccfSSadaf Ebrahimi     assert(vkGetAccelerationStructureMemoryRequirementsNV != nullptr);
623*b7893ccfSSadaf Ebrahimi 
624*b7893ccfSSadaf Ebrahimi     VkAccelerationStructureMemoryRequirementsInfoNV memoryRequirementsInfo = {};
625*b7893ccfSSadaf Ebrahimi     memoryRequirementsInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
626*b7893ccfSSadaf Ebrahimi     memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV;
627*b7893ccfSSadaf Ebrahimi     memoryRequirementsInfo.accelerationStructure = handle();
628*b7893ccfSSadaf Ebrahimi 
629*b7893ccfSSadaf Ebrahimi     VkMemoryRequirements2 memoryRequirements = {};
630*b7893ccfSSadaf Ebrahimi     vkGetAccelerationStructureMemoryRequirementsNV(device(), &memoryRequirementsInfo, &memoryRequirements);
631*b7893ccfSSadaf Ebrahimi     return memoryRequirements;
632*b7893ccfSSadaf Ebrahimi }
633*b7893ccfSSadaf Ebrahimi 
build_scratch_memory_requirements() const634*b7893ccfSSadaf Ebrahimi VkMemoryRequirements2 AccelerationStructure::build_scratch_memory_requirements() const {
635*b7893ccfSSadaf Ebrahimi     PFN_vkGetAccelerationStructureMemoryRequirementsNV vkGetAccelerationStructureMemoryRequirementsNV =
636*b7893ccfSSadaf Ebrahimi         (PFN_vkGetAccelerationStructureMemoryRequirementsNV)vkGetDeviceProcAddr(device(),
637*b7893ccfSSadaf Ebrahimi                                                                                 "vkGetAccelerationStructureMemoryRequirementsNV");
638*b7893ccfSSadaf Ebrahimi     assert(vkGetAccelerationStructureMemoryRequirementsNV != nullptr);
639*b7893ccfSSadaf Ebrahimi 
640*b7893ccfSSadaf Ebrahimi     VkAccelerationStructureMemoryRequirementsInfoNV memoryRequirementsInfo = {};
641*b7893ccfSSadaf Ebrahimi     memoryRequirementsInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
642*b7893ccfSSadaf Ebrahimi     memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV;
643*b7893ccfSSadaf Ebrahimi     memoryRequirementsInfo.accelerationStructure = handle();
644*b7893ccfSSadaf Ebrahimi 
645*b7893ccfSSadaf Ebrahimi     VkMemoryRequirements2 memoryRequirements = {};
646*b7893ccfSSadaf Ebrahimi     vkGetAccelerationStructureMemoryRequirementsNV(device(), &memoryRequirementsInfo, &memoryRequirements);
647*b7893ccfSSadaf Ebrahimi     return memoryRequirements;
648*b7893ccfSSadaf Ebrahimi }
649*b7893ccfSSadaf Ebrahimi 
init(const Device & dev,const VkAccelerationStructureCreateInfoNV & info,bool init_memory)650*b7893ccfSSadaf Ebrahimi void AccelerationStructure::init(const Device &dev, const VkAccelerationStructureCreateInfoNV &info, bool init_memory) {
651*b7893ccfSSadaf Ebrahimi     PFN_vkCreateAccelerationStructureNV vkCreateAccelerationStructureNV =
652*b7893ccfSSadaf Ebrahimi         (PFN_vkCreateAccelerationStructureNV)vkGetDeviceProcAddr(dev.handle(), "vkCreateAccelerationStructureNV");
653*b7893ccfSSadaf Ebrahimi     assert(vkCreateAccelerationStructureNV != nullptr);
654*b7893ccfSSadaf Ebrahimi 
655*b7893ccfSSadaf Ebrahimi     NON_DISPATCHABLE_HANDLE_INIT(vkCreateAccelerationStructureNV, dev, &info);
656*b7893ccfSSadaf Ebrahimi 
657*b7893ccfSSadaf Ebrahimi     info_ = info.info;
658*b7893ccfSSadaf Ebrahimi 
659*b7893ccfSSadaf Ebrahimi     if (init_memory) {
660*b7893ccfSSadaf Ebrahimi         memory_.init(dev, DeviceMemory::get_resource_alloc_info(dev, memory_requirements().memoryRequirements,
661*b7893ccfSSadaf Ebrahimi                                                                 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
662*b7893ccfSSadaf Ebrahimi 
663*b7893ccfSSadaf Ebrahimi         PFN_vkBindAccelerationStructureMemoryNV vkBindAccelerationStructureMemoryNV =
664*b7893ccfSSadaf Ebrahimi             (PFN_vkBindAccelerationStructureMemoryNV)vkGetDeviceProcAddr(dev.handle(), "vkBindAccelerationStructureMemoryNV");
665*b7893ccfSSadaf Ebrahimi         assert(vkBindAccelerationStructureMemoryNV != nullptr);
666*b7893ccfSSadaf Ebrahimi 
667*b7893ccfSSadaf Ebrahimi         VkBindAccelerationStructureMemoryInfoNV bind_info = {};
668*b7893ccfSSadaf Ebrahimi         bind_info.sType = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV;
669*b7893ccfSSadaf Ebrahimi         bind_info.accelerationStructure = handle();
670*b7893ccfSSadaf Ebrahimi         bind_info.memory = memory_.handle();
671*b7893ccfSSadaf Ebrahimi         EXPECT(vkBindAccelerationStructureMemoryNV(dev.handle(), 1, &bind_info) == VK_SUCCESS);
672*b7893ccfSSadaf Ebrahimi 
673*b7893ccfSSadaf Ebrahimi         PFN_vkGetAccelerationStructureHandleNV vkGetAccelerationStructureHandleNV =
674*b7893ccfSSadaf Ebrahimi             (PFN_vkGetAccelerationStructureHandleNV)vkGetDeviceProcAddr(dev.handle(), "vkGetAccelerationStructureHandleNV");
675*b7893ccfSSadaf Ebrahimi         assert(vkGetAccelerationStructureHandleNV != nullptr);
676*b7893ccfSSadaf Ebrahimi         EXPECT(vkGetAccelerationStructureHandleNV(dev.handle(), handle(), sizeof(uint64_t), &opaque_handle_) == VK_SUCCESS);
677*b7893ccfSSadaf Ebrahimi     }
678*b7893ccfSSadaf Ebrahimi }
679*b7893ccfSSadaf Ebrahimi 
create_scratch_buffer(const Device & dev,Buffer * buffer)680*b7893ccfSSadaf Ebrahimi void AccelerationStructure::create_scratch_buffer(const Device &dev, Buffer *buffer) {
681*b7893ccfSSadaf Ebrahimi     VkMemoryRequirements scratch_buffer_memory_requirements = build_scratch_memory_requirements().memoryRequirements;
682*b7893ccfSSadaf Ebrahimi 
683*b7893ccfSSadaf Ebrahimi     VkBufferCreateInfo create_info = {};
684*b7893ccfSSadaf Ebrahimi     create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
685*b7893ccfSSadaf Ebrahimi     create_info.size = scratch_buffer_memory_requirements.size;
686*b7893ccfSSadaf Ebrahimi     create_info.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
687*b7893ccfSSadaf Ebrahimi     return buffer->init(dev, create_info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
688*b7893ccfSSadaf Ebrahimi }
689*b7893ccfSSadaf Ebrahimi 
NON_DISPATCHABLE_HANDLE_DTOR(ShaderModule,vkDestroyShaderModule)690*b7893ccfSSadaf Ebrahimi NON_DISPATCHABLE_HANDLE_DTOR(ShaderModule, vkDestroyShaderModule)
691*b7893ccfSSadaf Ebrahimi 
692*b7893ccfSSadaf Ebrahimi void ShaderModule::init(const Device &dev, const VkShaderModuleCreateInfo &info) {
693*b7893ccfSSadaf Ebrahimi     NON_DISPATCHABLE_HANDLE_INIT(vkCreateShaderModule, dev, &info);
694*b7893ccfSSadaf Ebrahimi }
695*b7893ccfSSadaf Ebrahimi 
init_try(const Device & dev,const VkShaderModuleCreateInfo & info)696*b7893ccfSSadaf Ebrahimi VkResult ShaderModule::init_try(const Device &dev, const VkShaderModuleCreateInfo &info) {
697*b7893ccfSSadaf Ebrahimi     VkShaderModule mod;
698*b7893ccfSSadaf Ebrahimi 
699*b7893ccfSSadaf Ebrahimi     VkResult err = vkCreateShaderModule(dev.handle(), &info, NULL, &mod);
700*b7893ccfSSadaf Ebrahimi     if (err == VK_SUCCESS) NonDispHandle::init(dev.handle(), mod);
701*b7893ccfSSadaf Ebrahimi 
702*b7893ccfSSadaf Ebrahimi     return err;
703*b7893ccfSSadaf Ebrahimi }
704*b7893ccfSSadaf Ebrahimi 
NON_DISPATCHABLE_HANDLE_DTOR(Pipeline,vkDestroyPipeline)705*b7893ccfSSadaf Ebrahimi NON_DISPATCHABLE_HANDLE_DTOR(Pipeline, vkDestroyPipeline)
706*b7893ccfSSadaf Ebrahimi 
707*b7893ccfSSadaf Ebrahimi void Pipeline::init(const Device &dev, const VkGraphicsPipelineCreateInfo &info) {
708*b7893ccfSSadaf Ebrahimi     VkPipelineCache cache;
709*b7893ccfSSadaf Ebrahimi     VkPipelineCacheCreateInfo ci;
710*b7893ccfSSadaf Ebrahimi     memset((void *)&ci, 0, sizeof(VkPipelineCacheCreateInfo));
711*b7893ccfSSadaf Ebrahimi     ci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
712*b7893ccfSSadaf Ebrahimi     VkResult err = vkCreatePipelineCache(dev.handle(), &ci, NULL, &cache);
713*b7893ccfSSadaf Ebrahimi     if (err == VK_SUCCESS) {
714*b7893ccfSSadaf Ebrahimi         NON_DISPATCHABLE_HANDLE_INIT(vkCreateGraphicsPipelines, dev, cache, 1, &info);
715*b7893ccfSSadaf Ebrahimi         vkDestroyPipelineCache(dev.handle(), cache, NULL);
716*b7893ccfSSadaf Ebrahimi     }
717*b7893ccfSSadaf Ebrahimi }
718*b7893ccfSSadaf Ebrahimi 
init_try(const Device & dev,const VkGraphicsPipelineCreateInfo & info)719*b7893ccfSSadaf Ebrahimi VkResult Pipeline::init_try(const Device &dev, const VkGraphicsPipelineCreateInfo &info) {
720*b7893ccfSSadaf Ebrahimi     VkPipeline pipe;
721*b7893ccfSSadaf Ebrahimi     VkPipelineCache cache;
722*b7893ccfSSadaf Ebrahimi     VkPipelineCacheCreateInfo ci;
723*b7893ccfSSadaf Ebrahimi     memset((void *)&ci, 0, sizeof(VkPipelineCacheCreateInfo));
724*b7893ccfSSadaf Ebrahimi     ci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
725*b7893ccfSSadaf Ebrahimi     VkResult err = vkCreatePipelineCache(dev.handle(), &ci, NULL, &cache);
726*b7893ccfSSadaf Ebrahimi     EXPECT(err == VK_SUCCESS);
727*b7893ccfSSadaf Ebrahimi     if (err == VK_SUCCESS) {
728*b7893ccfSSadaf Ebrahimi         err = vkCreateGraphicsPipelines(dev.handle(), cache, 1, &info, NULL, &pipe);
729*b7893ccfSSadaf Ebrahimi         if (err == VK_SUCCESS) {
730*b7893ccfSSadaf Ebrahimi             NonDispHandle::init(dev.handle(), pipe);
731*b7893ccfSSadaf Ebrahimi         }
732*b7893ccfSSadaf Ebrahimi         vkDestroyPipelineCache(dev.handle(), cache, NULL);
733*b7893ccfSSadaf Ebrahimi     }
734*b7893ccfSSadaf Ebrahimi 
735*b7893ccfSSadaf Ebrahimi     return err;
736*b7893ccfSSadaf Ebrahimi }
737*b7893ccfSSadaf Ebrahimi 
init(const Device & dev,const VkComputePipelineCreateInfo & info)738*b7893ccfSSadaf Ebrahimi void Pipeline::init(const Device &dev, const VkComputePipelineCreateInfo &info) {
739*b7893ccfSSadaf Ebrahimi     VkPipelineCache cache;
740*b7893ccfSSadaf Ebrahimi     VkPipelineCacheCreateInfo ci;
741*b7893ccfSSadaf Ebrahimi     memset((void *)&ci, 0, sizeof(VkPipelineCacheCreateInfo));
742*b7893ccfSSadaf Ebrahimi     ci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
743*b7893ccfSSadaf Ebrahimi     VkResult err = vkCreatePipelineCache(dev.handle(), &ci, NULL, &cache);
744*b7893ccfSSadaf Ebrahimi     if (err == VK_SUCCESS) {
745*b7893ccfSSadaf Ebrahimi         NON_DISPATCHABLE_HANDLE_INIT(vkCreateComputePipelines, dev, cache, 1, &info);
746*b7893ccfSSadaf Ebrahimi         vkDestroyPipelineCache(dev.handle(), cache, NULL);
747*b7893ccfSSadaf Ebrahimi     }
748*b7893ccfSSadaf Ebrahimi }
749*b7893ccfSSadaf Ebrahimi 
NON_DISPATCHABLE_HANDLE_DTOR(PipelineLayout,vkDestroyPipelineLayout)750*b7893ccfSSadaf Ebrahimi NON_DISPATCHABLE_HANDLE_DTOR(PipelineLayout, vkDestroyPipelineLayout)
751*b7893ccfSSadaf Ebrahimi 
752*b7893ccfSSadaf Ebrahimi void PipelineLayout::init(const Device &dev, VkPipelineLayoutCreateInfo &info,
753*b7893ccfSSadaf Ebrahimi                           const std::vector<const DescriptorSetLayout *> &layouts) {
754*b7893ccfSSadaf Ebrahimi     const std::vector<VkDescriptorSetLayout> layout_handles = MakeVkHandles<VkDescriptorSetLayout>(layouts);
755*b7893ccfSSadaf Ebrahimi     info.setLayoutCount = layout_handles.size();
756*b7893ccfSSadaf Ebrahimi     info.pSetLayouts = layout_handles.data();
757*b7893ccfSSadaf Ebrahimi 
758*b7893ccfSSadaf Ebrahimi     NON_DISPATCHABLE_HANDLE_INIT(vkCreatePipelineLayout, dev, &info);
759*b7893ccfSSadaf Ebrahimi }
760*b7893ccfSSadaf Ebrahimi 
NON_DISPATCHABLE_HANDLE_DTOR(Sampler,vkDestroySampler)761*b7893ccfSSadaf Ebrahimi NON_DISPATCHABLE_HANDLE_DTOR(Sampler, vkDestroySampler)
762*b7893ccfSSadaf Ebrahimi 
763*b7893ccfSSadaf Ebrahimi void Sampler::init(const Device &dev, const VkSamplerCreateInfo &info) {
764*b7893ccfSSadaf Ebrahimi     NON_DISPATCHABLE_HANDLE_INIT(vkCreateSampler, dev, &info);
765*b7893ccfSSadaf Ebrahimi }
766*b7893ccfSSadaf Ebrahimi 
NON_DISPATCHABLE_HANDLE_DTOR(DescriptorSetLayout,vkDestroyDescriptorSetLayout)767*b7893ccfSSadaf Ebrahimi NON_DISPATCHABLE_HANDLE_DTOR(DescriptorSetLayout, vkDestroyDescriptorSetLayout)
768*b7893ccfSSadaf Ebrahimi 
769*b7893ccfSSadaf Ebrahimi void DescriptorSetLayout::init(const Device &dev, const VkDescriptorSetLayoutCreateInfo &info) {
770*b7893ccfSSadaf Ebrahimi     NON_DISPATCHABLE_HANDLE_INIT(vkCreateDescriptorSetLayout, dev, &info);
771*b7893ccfSSadaf Ebrahimi }
772*b7893ccfSSadaf Ebrahimi 
NON_DISPATCHABLE_HANDLE_DTOR(DescriptorPool,vkDestroyDescriptorPool)773*b7893ccfSSadaf Ebrahimi NON_DISPATCHABLE_HANDLE_DTOR(DescriptorPool, vkDestroyDescriptorPool)
774*b7893ccfSSadaf Ebrahimi 
775*b7893ccfSSadaf Ebrahimi void DescriptorPool::init(const Device &dev, const VkDescriptorPoolCreateInfo &info) {
776*b7893ccfSSadaf Ebrahimi     setDynamicUsage(info.flags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT);
777*b7893ccfSSadaf Ebrahimi     NON_DISPATCHABLE_HANDLE_INIT(vkCreateDescriptorPool, dev, &info);
778*b7893ccfSSadaf Ebrahimi }
779*b7893ccfSSadaf Ebrahimi 
reset()780*b7893ccfSSadaf Ebrahimi void DescriptorPool::reset() { EXPECT(vkResetDescriptorPool(device(), handle(), 0) == VK_SUCCESS); }
781*b7893ccfSSadaf Ebrahimi 
alloc_sets(const Device & dev,const std::vector<const DescriptorSetLayout * > & layouts)782*b7893ccfSSadaf Ebrahimi std::vector<DescriptorSet *> DescriptorPool::alloc_sets(const Device &dev,
783*b7893ccfSSadaf Ebrahimi                                                         const std::vector<const DescriptorSetLayout *> &layouts) {
784*b7893ccfSSadaf Ebrahimi     const std::vector<VkDescriptorSetLayout> layout_handles = MakeVkHandles<VkDescriptorSetLayout>(layouts);
785*b7893ccfSSadaf Ebrahimi 
786*b7893ccfSSadaf Ebrahimi     std::vector<VkDescriptorSet> set_handles;
787*b7893ccfSSadaf Ebrahimi     set_handles.resize(layout_handles.size());
788*b7893ccfSSadaf Ebrahimi 
789*b7893ccfSSadaf Ebrahimi     VkDescriptorSetAllocateInfo alloc_info = {};
790*b7893ccfSSadaf Ebrahimi     alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
791*b7893ccfSSadaf Ebrahimi     alloc_info.descriptorSetCount = layout_handles.size();
792*b7893ccfSSadaf Ebrahimi     alloc_info.descriptorPool = handle();
793*b7893ccfSSadaf Ebrahimi     alloc_info.pSetLayouts = layout_handles.data();
794*b7893ccfSSadaf Ebrahimi     VkResult err = vkAllocateDescriptorSets(device(), &alloc_info, set_handles.data());
795*b7893ccfSSadaf Ebrahimi     EXPECT(err == VK_SUCCESS);
796*b7893ccfSSadaf Ebrahimi 
797*b7893ccfSSadaf Ebrahimi     std::vector<DescriptorSet *> sets;
798*b7893ccfSSadaf Ebrahimi     for (std::vector<VkDescriptorSet>::const_iterator it = set_handles.begin(); it != set_handles.end(); it++) {
799*b7893ccfSSadaf Ebrahimi         // do descriptor sets need memories bound?
800*b7893ccfSSadaf Ebrahimi         DescriptorSet *descriptorSet = new DescriptorSet(dev, this, *it);
801*b7893ccfSSadaf Ebrahimi         sets.push_back(descriptorSet);
802*b7893ccfSSadaf Ebrahimi     }
803*b7893ccfSSadaf Ebrahimi     return sets;
804*b7893ccfSSadaf Ebrahimi }
805*b7893ccfSSadaf Ebrahimi 
alloc_sets(const Device & dev,const DescriptorSetLayout & layout,uint32_t count)806*b7893ccfSSadaf Ebrahimi std::vector<DescriptorSet *> DescriptorPool::alloc_sets(const Device &dev, const DescriptorSetLayout &layout, uint32_t count) {
807*b7893ccfSSadaf Ebrahimi     return alloc_sets(dev, std::vector<const DescriptorSetLayout *>(count, &layout));
808*b7893ccfSSadaf Ebrahimi }
809*b7893ccfSSadaf Ebrahimi 
alloc_sets(const Device & dev,const DescriptorSetLayout & layout)810*b7893ccfSSadaf Ebrahimi DescriptorSet *DescriptorPool::alloc_sets(const Device &dev, const DescriptorSetLayout &layout) {
811*b7893ccfSSadaf Ebrahimi     std::vector<DescriptorSet *> set = alloc_sets(dev, layout, 1);
812*b7893ccfSSadaf Ebrahimi     return (set.empty()) ? NULL : set[0];
813*b7893ccfSSadaf Ebrahimi }
814*b7893ccfSSadaf Ebrahimi 
~DescriptorSet()815*b7893ccfSSadaf Ebrahimi DescriptorSet::~DescriptorSet() {
816*b7893ccfSSadaf Ebrahimi     if (initialized()) {
817*b7893ccfSSadaf Ebrahimi         // Only call vkFree* on sets allocated from pool with usage *_DYNAMIC
818*b7893ccfSSadaf Ebrahimi         if (containing_pool_->getDynamicUsage()) {
819*b7893ccfSSadaf Ebrahimi             VkDescriptorSet sets[1] = {handle()};
820*b7893ccfSSadaf Ebrahimi             EXPECT(vkFreeDescriptorSets(device(), containing_pool_->GetObj(), 1, sets) == VK_SUCCESS);
821*b7893ccfSSadaf Ebrahimi         }
822*b7893ccfSSadaf Ebrahimi     }
823*b7893ccfSSadaf Ebrahimi }
824*b7893ccfSSadaf Ebrahimi 
NON_DISPATCHABLE_HANDLE_DTOR(CommandPool,vkDestroyCommandPool)825*b7893ccfSSadaf Ebrahimi NON_DISPATCHABLE_HANDLE_DTOR(CommandPool, vkDestroyCommandPool)
826*b7893ccfSSadaf Ebrahimi 
827*b7893ccfSSadaf Ebrahimi void CommandPool::init(const Device &dev, const VkCommandPoolCreateInfo &info) {
828*b7893ccfSSadaf Ebrahimi     NON_DISPATCHABLE_HANDLE_INIT(vkCreateCommandPool, dev, &info);
829*b7893ccfSSadaf Ebrahimi }
830*b7893ccfSSadaf Ebrahimi 
~CommandBuffer()831*b7893ccfSSadaf Ebrahimi CommandBuffer::~CommandBuffer() {
832*b7893ccfSSadaf Ebrahimi     if (initialized()) {
833*b7893ccfSSadaf Ebrahimi         VkCommandBuffer cmds[] = {handle()};
834*b7893ccfSSadaf Ebrahimi         vkFreeCommandBuffers(dev_handle_, cmd_pool_, 1, cmds);
835*b7893ccfSSadaf Ebrahimi     }
836*b7893ccfSSadaf Ebrahimi }
837*b7893ccfSSadaf Ebrahimi 
init(const Device & dev,const VkCommandBufferAllocateInfo & info)838*b7893ccfSSadaf Ebrahimi void CommandBuffer::init(const Device &dev, const VkCommandBufferAllocateInfo &info) {
839*b7893ccfSSadaf Ebrahimi     VkCommandBuffer cmd;
840*b7893ccfSSadaf Ebrahimi 
841*b7893ccfSSadaf Ebrahimi     // Make sure commandPool is set
842*b7893ccfSSadaf Ebrahimi     assert(info.commandPool);
843*b7893ccfSSadaf Ebrahimi 
844*b7893ccfSSadaf Ebrahimi     if (EXPECT(vkAllocateCommandBuffers(dev.handle(), &info, &cmd) == VK_SUCCESS)) {
845*b7893ccfSSadaf Ebrahimi         Handle::init(cmd);
846*b7893ccfSSadaf Ebrahimi         dev_handle_ = dev.handle();
847*b7893ccfSSadaf Ebrahimi         cmd_pool_ = info.commandPool;
848*b7893ccfSSadaf Ebrahimi     }
849*b7893ccfSSadaf Ebrahimi }
850*b7893ccfSSadaf Ebrahimi 
begin(const VkCommandBufferBeginInfo * info)851*b7893ccfSSadaf Ebrahimi void CommandBuffer::begin(const VkCommandBufferBeginInfo *info) { EXPECT(vkBeginCommandBuffer(handle(), info) == VK_SUCCESS); }
852*b7893ccfSSadaf Ebrahimi 
begin()853*b7893ccfSSadaf Ebrahimi void CommandBuffer::begin() {
854*b7893ccfSSadaf Ebrahimi     VkCommandBufferBeginInfo info = {};
855*b7893ccfSSadaf Ebrahimi     VkCommandBufferInheritanceInfo hinfo = {};
856*b7893ccfSSadaf Ebrahimi     info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
857*b7893ccfSSadaf Ebrahimi     info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
858*b7893ccfSSadaf Ebrahimi     info.pInheritanceInfo = &hinfo;
859*b7893ccfSSadaf Ebrahimi     hinfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
860*b7893ccfSSadaf Ebrahimi     hinfo.pNext = NULL;
861*b7893ccfSSadaf Ebrahimi     hinfo.renderPass = VK_NULL_HANDLE;
862*b7893ccfSSadaf Ebrahimi     hinfo.subpass = 0;
863*b7893ccfSSadaf Ebrahimi     hinfo.framebuffer = VK_NULL_HANDLE;
864*b7893ccfSSadaf Ebrahimi     hinfo.occlusionQueryEnable = VK_FALSE;
865*b7893ccfSSadaf Ebrahimi     hinfo.queryFlags = 0;
866*b7893ccfSSadaf Ebrahimi     hinfo.pipelineStatistics = 0;
867*b7893ccfSSadaf Ebrahimi 
868*b7893ccfSSadaf Ebrahimi     begin(&info);
869*b7893ccfSSadaf Ebrahimi }
870*b7893ccfSSadaf Ebrahimi 
end()871*b7893ccfSSadaf Ebrahimi void CommandBuffer::end() { EXPECT(vkEndCommandBuffer(handle()) == VK_SUCCESS); }
872*b7893ccfSSadaf Ebrahimi 
reset(VkCommandBufferResetFlags flags)873*b7893ccfSSadaf Ebrahimi void CommandBuffer::reset(VkCommandBufferResetFlags flags) { EXPECT(vkResetCommandBuffer(handle(), flags) == VK_SUCCESS); }
874*b7893ccfSSadaf Ebrahimi 
875*b7893ccfSSadaf Ebrahimi }  // namespace vk_testing
876