Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright (c) 2015-2016 The Khronos Group Inc.
      3  * Copyright (c) 2015-2016 Valve Corporation
      4  * Copyright (c) 2015-2016 LunarG, Inc.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a copy
      7  * of this software and/or associated documentation files (the "Materials"), to
      8  * deal in the Materials without restriction, including without limitation the
      9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
     10  * sell copies of the Materials, and to permit persons to whom the Materials are
     11  * furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice(s) and this permission notice shall be included in
     14  * all copies or substantial portions of the Materials.
     15  *
     16  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     19  *
     20  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
     21  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     22  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
     23  * USE OR OTHER DEALINGS IN THE MATERIALS.
     24  *
     25  * Author: Courtney Goeltzenleuchter <courtney (at) LunarG.com>
     26  * Author: Tony Barbour <tony (at) LunarG.com>
     27  */
     28 
     29 #include <iostream>
     30 #include <string.h> // memset(), memcmp()
     31 #include <assert.h>
     32 #include <stdarg.h>
     33 #include "vktestbinding.h"
     34 
     35 namespace {
     36 
     37 #define NON_DISPATCHABLE_HANDLE_INIT(create_func, dev, ...)                    \
     38     do {                                                                       \
     39         handle_type handle;                                                    \
     40         if (EXPECT(create_func(dev.handle(), __VA_ARGS__, NULL, &handle) ==    \
     41                    VK_SUCCESS))                                                \
     42             NonDispHandle::init(dev.handle(), handle);                         \
     43     } while (0)
     44 
     45 #define NON_DISPATCHABLE_HANDLE_DTOR(cls, destroy_func)                        \
     46     cls::~cls() {                                                              \
     47         if (initialized())                                                     \
     48             destroy_func(device(), handle(), NULL);                            \
     49     }
     50 
     51 #define STRINGIFY(x) #x
     52 #define EXPECT(expr)                                                           \
     53     ((expr) ? true : expect_failure(STRINGIFY(expr), __FILE__, __LINE__,       \
     54                                     __FUNCTION__))
     55 
     56 vk_testing::ErrorCallback error_callback;
     57 
     58 bool expect_failure(const char *expr, const char *file, unsigned int line,
     59                     const char *function) {
     60     if (error_callback) {
     61         error_callback(expr, file, line, function);
     62     } else {
     63         std::cerr << file << ":" << line << ": " << function
     64                   << ": Expectation `" << expr << "' failed.\n";
     65     }
     66 
     67     return false;
     68 }
     69 
     70 template <class T, class S>
     71 std::vector<T> make_handles(const std::vector<S> &v) {
     72     std::vector<T> handles;
     73     handles.reserve(v.size());
     74     for (typename std::vector<S>::const_iterator it = v.begin(); it != v.end();
     75          it++)
     76         handles.push_back((*it)->handle());
     77     return handles;
     78 }
     79 
     80 VkMemoryAllocateInfo get_resource_alloc_info(const vk_testing::Device &dev,
     81                                              const VkMemoryRequirements &reqs,
     82                                              VkMemoryPropertyFlags mem_props) {
     83     VkMemoryAllocateInfo info =
     84         vk_testing::DeviceMemory::alloc_info(reqs.size, 0);
     85     dev.phy().set_memory_type(reqs.memoryTypeBits, &info, mem_props);
     86 
     87     return info;
     88 }
     89 
     90 } // namespace
     91 
     92 namespace vk_testing {
     93 
     94 void set_error_callback(ErrorCallback callback) { error_callback = callback; }
     95 
     96 VkPhysicalDeviceProperties PhysicalDevice::properties() const {
     97     VkPhysicalDeviceProperties info;
     98 
     99     vkGetPhysicalDeviceProperties(handle(), &info);
    100 
    101     return info;
    102 }
    103 
    104 std::vector<VkQueueFamilyProperties> PhysicalDevice::queue_properties() const {
    105     std::vector<VkQueueFamilyProperties> info;
    106     uint32_t count;
    107 
    108     // Call once with NULL data to receive count
    109     vkGetPhysicalDeviceQueueFamilyProperties(handle(), &count, NULL);
    110     info.resize(count);
    111     vkGetPhysicalDeviceQueueFamilyProperties(handle(), &count, info.data());
    112 
    113     return info;
    114 }
    115 
    116 VkPhysicalDeviceMemoryProperties PhysicalDevice::memory_properties() const {
    117     VkPhysicalDeviceMemoryProperties info;
    118 
    119     vkGetPhysicalDeviceMemoryProperties(handle(), &info);
    120 
    121     return info;
    122 }
    123 
    124 /*
    125  * Return list of Global layers available
    126  */
    127 std::vector<VkLayerProperties> GetGlobalLayers() {
    128     VkResult err;
    129     std::vector<VkLayerProperties> layers;
    130     uint32_t layer_count;
    131 
    132     do {
    133         layer_count = 0;
    134         err = vkEnumerateInstanceLayerProperties(&layer_count, NULL);
    135 
    136         if (err == VK_SUCCESS) {
    137             layers.reserve(layer_count);
    138             err =
    139                 vkEnumerateInstanceLayerProperties(&layer_count, layers.data());
    140         }
    141     } while (err == VK_INCOMPLETE);
    142 
    143     assert(err == VK_SUCCESS);
    144 
    145     return layers;
    146 }
    147 
    148 /*
    149  * Return list of Global extensions provided by the ICD / Loader
    150  */
    151 std::vector<VkExtensionProperties> GetGlobalExtensions() {
    152     return GetGlobalExtensions(NULL);
    153 }
    154 
    155 /*
    156  * Return list of Global extensions provided by the specified layer
    157  * If pLayerName is NULL, will return extensions implemented by the loader /
    158  * ICDs
    159  */
    160 std::vector<VkExtensionProperties> GetGlobalExtensions(const char *pLayerName) {
    161     std::vector<VkExtensionProperties> exts;
    162     uint32_t ext_count;
    163     VkResult err;
    164 
    165     do {
    166         ext_count = 0;
    167         err = vkEnumerateInstanceExtensionProperties(pLayerName, &ext_count,
    168                                                      NULL);
    169 
    170         if (err == VK_SUCCESS) {
    171             exts.resize(ext_count);
    172             err = vkEnumerateInstanceExtensionProperties(pLayerName, &ext_count,
    173                                                          exts.data());
    174         }
    175     } while (err == VK_INCOMPLETE);
    176 
    177     assert(err == VK_SUCCESS);
    178 
    179     return exts;
    180 }
    181 
    182 /*
    183  * Return list of PhysicalDevice extensions provided by the ICD / Loader
    184  */
    185 std::vector<VkExtensionProperties> PhysicalDevice::extensions() const {
    186     return extensions(NULL);
    187 }
    188 
    189 /*
    190  * Return list of PhysicalDevice extensions provided by the specified layer
    191  * If pLayerName is NULL, will return extensions for ICD / loader.
    192  */
    193 std::vector<VkExtensionProperties>
    194 PhysicalDevice::extensions(const char *pLayerName) const {
    195     std::vector<VkExtensionProperties> exts;
    196     VkResult err;
    197 
    198     do {
    199         uint32_t extCount = 0;
    200         err = vkEnumerateDeviceExtensionProperties(handle(), pLayerName,
    201                                                    &extCount, NULL);
    202 
    203         if (err == VK_SUCCESS) {
    204             exts.resize(extCount);
    205             err = vkEnumerateDeviceExtensionProperties(handle(), pLayerName,
    206                                                        &extCount, exts.data());
    207         }
    208     } while (err == VK_INCOMPLETE);
    209 
    210     assert(err == VK_SUCCESS);
    211 
    212     return exts;
    213 }
    214 
    215 bool PhysicalDevice::set_memory_type(const uint32_t type_bits,
    216                                      VkMemoryAllocateInfo *info,
    217                                      const VkFlags properties,
    218                                      const VkFlags forbid) const {
    219     uint32_t type_mask = type_bits;
    220     // Search memtypes to find first index with those properties
    221     for (uint32_t i = 0; i < memory_properties_.memoryTypeCount; i++) {
    222         if ((type_mask & 1) == 1) {
    223             // Type is available, does it match user properties?
    224             if ((memory_properties_.memoryTypes[i].propertyFlags &
    225                  properties) == properties &&
    226                 (memory_properties_.memoryTypes[i].propertyFlags & forbid) ==
    227                     0) {
    228                 info->memoryTypeIndex = i;
    229                 return true;
    230             }
    231         }
    232         type_mask >>= 1;
    233     }
    234     // No memory types matched, return failure
    235     return false;
    236 }
    237 
    238 /*
    239  * Return list of PhysicalDevice layers
    240  */
    241 std::vector<VkLayerProperties> PhysicalDevice::layers() const {
    242     std::vector<VkLayerProperties> layer_props;
    243     VkResult err;
    244 
    245     do {
    246         uint32_t layer_count = 0;
    247         err = vkEnumerateDeviceLayerProperties(handle(), &layer_count, NULL);
    248 
    249         if (err == VK_SUCCESS) {
    250             layer_props.reserve(layer_count);
    251             err = vkEnumerateDeviceLayerProperties(handle(), &layer_count,
    252                                                    layer_props.data());
    253         }
    254     } while (err == VK_INCOMPLETE);
    255 
    256     assert(err == VK_SUCCESS);
    257 
    258     return layer_props;
    259 }
    260 
    261 Device::~Device() {
    262     if (!initialized())
    263         return;
    264 
    265     for (int i = 0; i < QUEUE_COUNT; i++) {
    266         for (std::vector<Queue *>::iterator it = queues_[i].begin();
    267              it != queues_[i].end(); it++)
    268             delete *it;
    269         queues_[i].clear();
    270     }
    271 
    272     vkDestroyDevice(handle(), NULL);
    273 }
    274 
    275 void Device::init(std::vector<const char *> &layers,
    276                   std::vector<const char *> &extensions) {
    277     // request all queues
    278     const std::vector<VkQueueFamilyProperties> queue_props =
    279         phy_.queue_properties();
    280     std::vector<VkDeviceQueueCreateInfo> queue_info;
    281     queue_info.reserve(queue_props.size());
    282 
    283     std::vector<std::vector<float>> queue_priorities;
    284 
    285     for (uint32_t i = 0; i < (uint32_t)queue_props.size(); i++) {
    286         VkDeviceQueueCreateInfo qi = {};
    287         qi.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
    288         qi.pNext = NULL;
    289         qi.queueFamilyIndex = i;
    290         qi.queueCount = queue_props[i].queueCount;
    291 
    292         queue_priorities.emplace_back(qi.queueCount, 0.0);
    293 
    294         qi.pQueuePriorities = queue_priorities[i].data();
    295         if (queue_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
    296             graphics_queue_node_index_ = i;
    297         }
    298         queue_info.push_back(qi);
    299     }
    300 
    301     VkDeviceCreateInfo dev_info = {};
    302     dev_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
    303     dev_info.pNext = NULL;
    304     dev_info.queueCreateInfoCount = queue_info.size();
    305     dev_info.pQueueCreateInfos = queue_info.data();
    306     dev_info.enabledLayerCount = layers.size();
    307     dev_info.ppEnabledLayerNames = layers.data();
    308     dev_info.enabledExtensionCount = extensions.size();
    309     dev_info.ppEnabledExtensionNames = extensions.data();
    310 
    311     init(dev_info);
    312 }
    313 
    314 void Device::init(const VkDeviceCreateInfo &info) {
    315     VkDevice dev;
    316 
    317     if (EXPECT(vkCreateDevice(phy_.handle(), &info, NULL, &dev) == VK_SUCCESS))
    318         Handle::init(dev);
    319 
    320     init_queues();
    321     init_formats();
    322 }
    323 
    324 void Device::init_queues() {
    325     uint32_t queue_node_count;
    326 
    327     // Call with NULL data to get count
    328     vkGetPhysicalDeviceQueueFamilyProperties(phy_.handle(), &queue_node_count,
    329                                              NULL);
    330     EXPECT(queue_node_count >= 1);
    331 
    332     VkQueueFamilyProperties *queue_props =
    333         new VkQueueFamilyProperties[queue_node_count];
    334 
    335     vkGetPhysicalDeviceQueueFamilyProperties(phy_.handle(), &queue_node_count,
    336                                              queue_props);
    337 
    338     for (uint32_t i = 0; i < queue_node_count; i++) {
    339         VkQueue queue;
    340 
    341         for (uint32_t j = 0; j < queue_props[i].queueCount; j++) {
    342             // TODO: Need to add support for separate MEMMGR and work queues,
    343             // including synchronization
    344             vkGetDeviceQueue(handle(), i, j, &queue);
    345 
    346             if (queue_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
    347                 queues_[GRAPHICS].push_back(new Queue(queue, i));
    348             }
    349 
    350             if (queue_props[i].queueFlags & VK_QUEUE_COMPUTE_BIT) {
    351                 queues_[COMPUTE].push_back(new Queue(queue, i));
    352             }
    353 
    354             if (queue_props[i].queueFlags & VK_QUEUE_TRANSFER_BIT) {
    355                 queues_[DMA].push_back(new Queue(queue, i));
    356             }
    357         }
    358     }
    359 
    360     delete[] queue_props;
    361 
    362     EXPECT(!queues_[GRAPHICS].empty() || !queues_[COMPUTE].empty());
    363 }
    364 
    365 void Device::init_formats() {
    366     for (int f = VK_FORMAT_BEGIN_RANGE; f <= VK_FORMAT_END_RANGE; f++) {
    367         const VkFormat fmt = static_cast<VkFormat>(f);
    368         const VkFormatProperties props = format_properties(fmt);
    369 
    370         if (props.linearTilingFeatures) {
    371             const Format tmp = {fmt, VK_IMAGE_TILING_LINEAR,
    372                                 props.linearTilingFeatures};
    373             formats_.push_back(tmp);
    374         }
    375 
    376         if (props.optimalTilingFeatures) {
    377             const Format tmp = {fmt, VK_IMAGE_TILING_OPTIMAL,
    378                                 props.optimalTilingFeatures};
    379             formats_.push_back(tmp);
    380         }
    381     }
    382 
    383     EXPECT(!formats_.empty());
    384 }
    385 
    386 VkFormatProperties Device::format_properties(VkFormat format) {
    387     VkFormatProperties data;
    388     vkGetPhysicalDeviceFormatProperties(phy().handle(), format, &data);
    389 
    390     return data;
    391 }
    392 
    393 void Device::wait() { EXPECT(vkDeviceWaitIdle(handle()) == VK_SUCCESS); }
    394 
    395 VkResult Device::wait(const std::vector<const Fence *> &fences, bool wait_all,
    396                       uint64_t timeout) {
    397     const std::vector<VkFence> fence_handles = make_handles<VkFence>(fences);
    398     VkResult err = vkWaitForFences(handle(), fence_handles.size(),
    399                                    fence_handles.data(), wait_all, timeout);
    400     EXPECT(err == VK_SUCCESS || err == VK_TIMEOUT);
    401 
    402     return err;
    403 }
    404 
    405 void Device::update_descriptor_sets(
    406     const std::vector<VkWriteDescriptorSet> &writes,
    407     const std::vector<VkCopyDescriptorSet> &copies) {
    408     vkUpdateDescriptorSets(handle(), writes.size(), writes.data(),
    409                            copies.size(), copies.data());
    410 }
    411 
    412 void Queue::submit(const std::vector<const CommandBuffer *> &cmds,
    413                    Fence &fence) {
    414     const std::vector<VkCommandBuffer> cmd_handles =
    415         make_handles<VkCommandBuffer>(cmds);
    416     VkSubmitInfo submit_info;
    417     submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
    418     submit_info.pNext = NULL;
    419     submit_info.waitSemaphoreCount = 0;
    420     submit_info.pWaitSemaphores = NULL;
    421     submit_info.pWaitDstStageMask = NULL;
    422     submit_info.commandBufferCount = (uint32_t)cmd_handles.size();
    423     submit_info.pCommandBuffers = cmd_handles.data();
    424     submit_info.signalSemaphoreCount = 0;
    425     submit_info.pSignalSemaphores = NULL;
    426 
    427     EXPECT(vkQueueSubmit(handle(), 1, &submit_info, fence.handle()) ==
    428            VK_SUCCESS);
    429 }
    430 
    431 void Queue::submit(const CommandBuffer &cmd, Fence &fence) {
    432     submit(std::vector<const CommandBuffer *>(1, &cmd), fence);
    433 }
    434 
    435 void Queue::submit(const CommandBuffer &cmd) {
    436     Fence fence;
    437     submit(cmd, fence);
    438 }
    439 
    440 void Queue::wait() { EXPECT(vkQueueWaitIdle(handle()) == VK_SUCCESS); }
    441 
    442 DeviceMemory::~DeviceMemory() {
    443     if (initialized())
    444         vkFreeMemory(device(), handle(), NULL);
    445 }
    446 
    447 void DeviceMemory::init(const Device &dev, const VkMemoryAllocateInfo &info) {
    448     NON_DISPATCHABLE_HANDLE_INIT(vkAllocateMemory, dev, &info);
    449 }
    450 
    451 const void *DeviceMemory::map(VkFlags flags) const {
    452     void *data;
    453     if (!EXPECT(vkMapMemory(device(), handle(), 0, VK_WHOLE_SIZE, flags,
    454                             &data) == VK_SUCCESS))
    455         data = NULL;
    456 
    457     return data;
    458 }
    459 
    460 void *DeviceMemory::map(VkFlags flags) {
    461     void *data;
    462     if (!EXPECT(vkMapMemory(device(), handle(), 0, VK_WHOLE_SIZE, flags,
    463                             &data) == VK_SUCCESS))
    464         data = NULL;
    465 
    466     return data;
    467 }
    468 
    469 void DeviceMemory::unmap() const { vkUnmapMemory(device(), handle()); }
    470 
    471 NON_DISPATCHABLE_HANDLE_DTOR(Fence, vkDestroyFence)
    472 
    473 void Fence::init(const Device &dev, const VkFenceCreateInfo &info) {
    474     NON_DISPATCHABLE_HANDLE_INIT(vkCreateFence, dev, &info);
    475 }
    476 
    477 NON_DISPATCHABLE_HANDLE_DTOR(Semaphore, vkDestroySemaphore)
    478 
    479 void Semaphore::init(const Device &dev, const VkSemaphoreCreateInfo &info) {
    480     NON_DISPATCHABLE_HANDLE_INIT(vkCreateSemaphore, dev, &info);
    481 }
    482 
    483 NON_DISPATCHABLE_HANDLE_DTOR(Event, vkDestroyEvent)
    484 
    485 void Event::init(const Device &dev, const VkEventCreateInfo &info) {
    486     NON_DISPATCHABLE_HANDLE_INIT(vkCreateEvent, dev, &info);
    487 }
    488 
    489 void Event::set() { EXPECT(vkSetEvent(device(), handle()) == VK_SUCCESS); }
    490 
    491 void Event::reset() { EXPECT(vkResetEvent(device(), handle()) == VK_SUCCESS); }
    492 
    493 NON_DISPATCHABLE_HANDLE_DTOR(QueryPool, vkDestroyQueryPool)
    494 
    495 void QueryPool::init(const Device &dev, const VkQueryPoolCreateInfo &info) {
    496     NON_DISPATCHABLE_HANDLE_INIT(vkCreateQueryPool, dev, &info);
    497 }
    498 
    499 VkResult QueryPool::results(uint32_t first, uint32_t count, size_t size,
    500                             void *data, size_t stride) {
    501     VkResult err = vkGetQueryPoolResults(device(), handle(), first, count, size,
    502                                          data, stride, 0);
    503     EXPECT(err == VK_SUCCESS || err == VK_NOT_READY);
    504 
    505     return err;
    506 }
    507 
    508 NON_DISPATCHABLE_HANDLE_DTOR(Buffer, vkDestroyBuffer)
    509 
    510 void Buffer::init(const Device &dev, const VkBufferCreateInfo &info,
    511                   VkMemoryPropertyFlags mem_props) {
    512     init_no_mem(dev, info);
    513 
    514     internal_mem_.init(
    515         dev, get_resource_alloc_info(dev, memory_requirements(), mem_props));
    516     bind_memory(internal_mem_, 0);
    517 }
    518 
    519 void Buffer::init_no_mem(const Device &dev, const VkBufferCreateInfo &info) {
    520     NON_DISPATCHABLE_HANDLE_INIT(vkCreateBuffer, dev, &info);
    521     create_info_ = info;
    522 }
    523 
    524 VkMemoryRequirements Buffer::memory_requirements() const {
    525     VkMemoryRequirements reqs;
    526 
    527     vkGetBufferMemoryRequirements(device(), handle(), &reqs);
    528 
    529     return reqs;
    530 }
    531 
    532 void Buffer::bind_memory(const DeviceMemory &mem, VkDeviceSize mem_offset) {
    533     EXPECT(vkBindBufferMemory(device(), handle(), mem.handle(), mem_offset) ==
    534            VK_SUCCESS);
    535 }
    536 
    537 NON_DISPATCHABLE_HANDLE_DTOR(BufferView, vkDestroyBufferView)
    538 
    539 void BufferView::init(const Device &dev, const VkBufferViewCreateInfo &info) {
    540     NON_DISPATCHABLE_HANDLE_INIT(vkCreateBufferView, dev, &info);
    541 }
    542 
    543 NON_DISPATCHABLE_HANDLE_DTOR(Image, vkDestroyImage)
    544 
    545 void Image::init(const Device &dev, const VkImageCreateInfo &info,
    546                  VkMemoryPropertyFlags mem_props) {
    547     init_no_mem(dev, info);
    548 
    549     internal_mem_.init(
    550         dev, get_resource_alloc_info(dev, memory_requirements(), mem_props));
    551     bind_memory(internal_mem_, 0);
    552 }
    553 
    554 void Image::init_no_mem(const Device &dev, const VkImageCreateInfo &info) {
    555     NON_DISPATCHABLE_HANDLE_INIT(vkCreateImage, dev, &info);
    556     init_info(dev, info);
    557 }
    558 
    559 void Image::init_info(const Device &dev, const VkImageCreateInfo &info) {
    560     create_info_ = info;
    561 
    562     for (std::vector<Device::Format>::const_iterator it = dev.formats().begin();
    563          it != dev.formats().end(); it++) {
    564         if (memcmp(&it->format, &create_info_.format, sizeof(it->format)) ==
    565                 0 &&
    566             it->tiling == create_info_.tiling) {
    567             format_features_ = it->features;
    568             break;
    569         }
    570     }
    571 }
    572 
    573 VkMemoryRequirements Image::memory_requirements() const {
    574     VkMemoryRequirements reqs;
    575 
    576     vkGetImageMemoryRequirements(device(), handle(), &reqs);
    577 
    578     return reqs;
    579 }
    580 
    581 void Image::bind_memory(const DeviceMemory &mem, VkDeviceSize mem_offset) {
    582     EXPECT(vkBindImageMemory(device(), handle(), mem.handle(), mem_offset) ==
    583            VK_SUCCESS);
    584 }
    585 
    586 VkSubresourceLayout
    587 Image::subresource_layout(const VkImageSubresource &subres) const {
    588     VkSubresourceLayout data;
    589     size_t size = sizeof(data);
    590     vkGetImageSubresourceLayout(device(), handle(), &subres, &data);
    591     if (size != sizeof(data))
    592         memset(&data, 0, sizeof(data));
    593 
    594     return data;
    595 }
    596 
    597 VkSubresourceLayout
    598 Image::subresource_layout(const VkImageSubresourceLayers &subrescopy) const {
    599     VkSubresourceLayout data;
    600     VkImageSubresource subres =
    601         subresource(image_aspect(subrescopy.aspectMask), subrescopy.mipLevel,
    602                     subrescopy.baseArrayLayer);
    603     size_t size = sizeof(data);
    604     vkGetImageSubresourceLayout(device(), handle(), &subres, &data);
    605     if (size != sizeof(data))
    606         memset(&data, 0, sizeof(data));
    607 
    608     return data;
    609 }
    610 
    611 bool Image::transparent() const {
    612     return (
    613         create_info_.tiling == VK_IMAGE_TILING_LINEAR &&
    614         create_info_.samples == VK_SAMPLE_COUNT_1_BIT &&
    615         !(create_info_.usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
    616                                 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)));
    617 }
    618 
    619 NON_DISPATCHABLE_HANDLE_DTOR(ImageView, vkDestroyImageView)
    620 
    621 void ImageView::init(const Device &dev, const VkImageViewCreateInfo &info) {
    622     NON_DISPATCHABLE_HANDLE_INIT(vkCreateImageView, dev, &info);
    623 }
    624 
    625 NON_DISPATCHABLE_HANDLE_DTOR(ShaderModule, vkDestroyShaderModule)
    626 
    627 void ShaderModule::init(const Device &dev,
    628                         const VkShaderModuleCreateInfo &info) {
    629     NON_DISPATCHABLE_HANDLE_INIT(vkCreateShaderModule, dev, &info);
    630 }
    631 
    632 VkResult ShaderModule::init_try(const Device &dev,
    633                                 const VkShaderModuleCreateInfo &info) {
    634     VkShaderModule mod;
    635 
    636     VkResult err = vkCreateShaderModule(dev.handle(), &info, NULL, &mod);
    637     if (err == VK_SUCCESS)
    638         NonDispHandle::init(dev.handle(), mod);
    639 
    640     return err;
    641 }
    642 
    643 NON_DISPATCHABLE_HANDLE_DTOR(Pipeline, vkDestroyPipeline)
    644 
    645 void Pipeline::init(const Device &dev,
    646                     const VkGraphicsPipelineCreateInfo &info) {
    647     VkPipelineCache cache;
    648     VkPipelineCacheCreateInfo ci;
    649     memset((void *)&ci, 0, sizeof(VkPipelineCacheCreateInfo));
    650     ci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
    651     VkResult err = vkCreatePipelineCache(dev.handle(), &ci, NULL, &cache);
    652     if (err == VK_SUCCESS) {
    653         NON_DISPATCHABLE_HANDLE_INIT(vkCreateGraphicsPipelines, dev, cache, 1,
    654                                      &info);
    655         vkDestroyPipelineCache(dev.handle(), cache, NULL);
    656     }
    657 }
    658 
    659 VkResult Pipeline::init_try(const Device &dev,
    660                             const VkGraphicsPipelineCreateInfo &info) {
    661     VkPipeline pipe;
    662     VkPipelineCache cache;
    663     VkPipelineCacheCreateInfo ci;
    664     memset((void *)&ci, 0, sizeof(VkPipelineCacheCreateInfo));
    665     ci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
    666     VkResult err = vkCreatePipelineCache(dev.handle(), &ci, NULL, &cache);
    667     EXPECT(err == VK_SUCCESS);
    668     if (err == VK_SUCCESS) {
    669         err = vkCreateGraphicsPipelines(dev.handle(), cache, 1, &info, NULL,
    670                                         &pipe);
    671         if (err == VK_SUCCESS) {
    672             NonDispHandle::init(dev.handle(), pipe);
    673         }
    674         vkDestroyPipelineCache(dev.handle(), cache, NULL);
    675     }
    676 
    677     return err;
    678 }
    679 
    680 void Pipeline::init(const Device &dev,
    681                     const VkComputePipelineCreateInfo &info) {
    682     VkPipelineCache cache;
    683     VkPipelineCacheCreateInfo ci;
    684     memset((void *)&ci, 0, sizeof(VkPipelineCacheCreateInfo));
    685     ci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
    686     VkResult err = vkCreatePipelineCache(dev.handle(), &ci, NULL, &cache);
    687     if (err == VK_SUCCESS) {
    688         NON_DISPATCHABLE_HANDLE_INIT(vkCreateComputePipelines, dev, cache, 1,
    689                                      &info);
    690         vkDestroyPipelineCache(dev.handle(), cache, NULL);
    691     }
    692 }
    693 
    694 NON_DISPATCHABLE_HANDLE_DTOR(PipelineLayout, vkDestroyPipelineLayout)
    695 
    696 void PipelineLayout::init(
    697     const Device &dev, VkPipelineLayoutCreateInfo &info,
    698     const std::vector<const DescriptorSetLayout *> &layouts) {
    699     const std::vector<VkDescriptorSetLayout> layout_handles =
    700         make_handles<VkDescriptorSetLayout>(layouts);
    701     info.pSetLayouts = layout_handles.data();
    702 
    703     NON_DISPATCHABLE_HANDLE_INIT(vkCreatePipelineLayout, dev, &info);
    704 }
    705 
    706 NON_DISPATCHABLE_HANDLE_DTOR(Sampler, vkDestroySampler)
    707 
    708 void Sampler::init(const Device &dev, const VkSamplerCreateInfo &info) {
    709     NON_DISPATCHABLE_HANDLE_INIT(vkCreateSampler, dev, &info);
    710 }
    711 
    712 NON_DISPATCHABLE_HANDLE_DTOR(DescriptorSetLayout, vkDestroyDescriptorSetLayout)
    713 
    714 void DescriptorSetLayout::init(const Device &dev,
    715                                const VkDescriptorSetLayoutCreateInfo &info) {
    716     NON_DISPATCHABLE_HANDLE_INIT(vkCreateDescriptorSetLayout, dev, &info);
    717 }
    718 
    719 NON_DISPATCHABLE_HANDLE_DTOR(DescriptorPool, vkDestroyDescriptorPool)
    720 
    721 void DescriptorPool::init(const Device &dev,
    722                           const VkDescriptorPoolCreateInfo &info) {
    723     setDynamicUsage(info.flags &
    724                     VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT);
    725     NON_DISPATCHABLE_HANDLE_INIT(vkCreateDescriptorPool, dev, &info);
    726 }
    727 
    728 void DescriptorPool::reset() {
    729     EXPECT(vkResetDescriptorPool(device(), handle(), 0) == VK_SUCCESS);
    730 }
    731 
    732 std::vector<DescriptorSet *> DescriptorPool::alloc_sets(
    733     const Device &dev,
    734     const std::vector<const DescriptorSetLayout *> &layouts) {
    735     const std::vector<VkDescriptorSetLayout> layout_handles =
    736         make_handles<VkDescriptorSetLayout>(layouts);
    737 
    738     std::vector<VkDescriptorSet> set_handles;
    739     set_handles.resize(layout_handles.size());
    740 
    741     VkDescriptorSetAllocateInfo alloc_info = {};
    742     alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
    743     alloc_info.descriptorSetCount = layout_handles.size();
    744     alloc_info.descriptorPool = handle();
    745     alloc_info.pSetLayouts = layout_handles.data();
    746     VkResult err =
    747         vkAllocateDescriptorSets(device(), &alloc_info, set_handles.data());
    748     EXPECT(err == VK_SUCCESS);
    749 
    750     std::vector<DescriptorSet *> sets;
    751     for (std::vector<VkDescriptorSet>::const_iterator it = set_handles.begin();
    752          it != set_handles.end(); it++) {
    753         // do descriptor sets need memories bound?
    754         DescriptorSet *descriptorSet = new DescriptorSet(dev, this, *it);
    755         sets.push_back(descriptorSet);
    756     }
    757     return sets;
    758 }
    759 
    760 std::vector<DescriptorSet *>
    761 DescriptorPool::alloc_sets(const Device &dev, const DescriptorSetLayout &layout,
    762                            uint32_t count) {
    763     return alloc_sets(dev,
    764                       std::vector<const DescriptorSetLayout *>(count, &layout));
    765 }
    766 
    767 DescriptorSet *DescriptorPool::alloc_sets(const Device &dev,
    768                                           const DescriptorSetLayout &layout) {
    769     std::vector<DescriptorSet *> set = alloc_sets(dev, layout, 1);
    770     return (set.empty()) ? NULL : set[0];
    771 }
    772 
    773 DescriptorSet::~DescriptorSet() {
    774     if (initialized()) {
    775         // Only call vkFree* on sets allocated from pool with usage *_DYNAMIC
    776         if (containing_pool_->getDynamicUsage()) {
    777             VkDescriptorSet sets[1] = {handle()};
    778             EXPECT(vkFreeDescriptorSets(device(), containing_pool_->GetObj(), 1,
    779                                         sets) == VK_SUCCESS);
    780         }
    781     }
    782 }
    783 
    784 NON_DISPATCHABLE_HANDLE_DTOR(CommandPool, vkDestroyCommandPool)
    785 
    786 void CommandPool::init(const Device &dev, const VkCommandPoolCreateInfo &info) {
    787     NON_DISPATCHABLE_HANDLE_INIT(vkCreateCommandPool, dev, &info);
    788 }
    789 
    790 CommandBuffer::~CommandBuffer() {
    791     if (initialized()) {
    792         VkCommandBuffer cmds[] = {handle()};
    793         vkFreeCommandBuffers(dev_handle_, cmd_pool_, 1, cmds);
    794     }
    795 }
    796 
    797 void CommandBuffer::init(const Device &dev,
    798                          const VkCommandBufferAllocateInfo &info) {
    799     VkCommandBuffer cmd;
    800 
    801     // Make sure commandPool is set
    802     assert(info.commandPool);
    803 
    804     if (EXPECT(vkAllocateCommandBuffers(dev.handle(), &info, &cmd) ==
    805                VK_SUCCESS)) {
    806         Handle::init(cmd);
    807         dev_handle_ = dev.handle();
    808         cmd_pool_ = info.commandPool;
    809     }
    810 }
    811 
    812 void CommandBuffer::begin(const VkCommandBufferBeginInfo *info) {
    813     EXPECT(vkBeginCommandBuffer(handle(), info) == VK_SUCCESS);
    814 }
    815 
    816 void CommandBuffer::begin() {
    817     VkCommandBufferBeginInfo info = {};
    818     VkCommandBufferInheritanceInfo hinfo = {};
    819     info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
    820     info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
    821     info.pInheritanceInfo = &hinfo;
    822     hinfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
    823     hinfo.pNext = NULL;
    824     hinfo.renderPass = VK_NULL_HANDLE;
    825     hinfo.subpass = 0;
    826     hinfo.framebuffer = VK_NULL_HANDLE;
    827     hinfo.occlusionQueryEnable = VK_FALSE;
    828     hinfo.queryFlags = 0;
    829     hinfo.pipelineStatistics = 0;
    830 
    831     begin(&info);
    832 }
    833 
    834 void CommandBuffer::end() {
    835     EXPECT(vkEndCommandBuffer(handle()) == VK_SUCCESS);
    836 }
    837 
    838 void CommandBuffer::reset(VkCommandBufferResetFlags flags) {
    839     EXPECT(vkResetCommandBuffer(handle(), flags) == VK_SUCCESS);
    840 }
    841 
    842 }; // namespace vk_testing
    843