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  * Copyright (c) 2015-2016 Google, Inc.
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *     http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  * Author: Courtney Goeltzenleuchter <courtney (at) LunarG.com>
     20  * Author: Tony Barbour <tony (at) LunarG.com>
     21  */
     22 
     23 #include "vkrenderframework.h"
     24 
     25 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
     26 #define GET_DEVICE_PROC_ADDR(dev, entrypoint)                                                                                      \
     27     {                                                                                                                              \
     28         fp##entrypoint = (PFN_vk##entrypoint)vkGetDeviceProcAddr(dev, "vk" #entrypoint);                                           \
     29         assert(fp##entrypoint != NULL);                                                                                            \
     30     }
     31 
     32 // TODO : These functions are duplicated is vk_layer_utils.cpp, share code
     33 // Return true if format contains depth and stencil information
     34 bool vk_format_is_depth_and_stencil(VkFormat format) {
     35     bool is_ds = false;
     36 
     37     switch (format) {
     38     case VK_FORMAT_D16_UNORM_S8_UINT:
     39     case VK_FORMAT_D24_UNORM_S8_UINT:
     40     case VK_FORMAT_D32_SFLOAT_S8_UINT:
     41         is_ds = true;
     42         break;
     43     default:
     44         break;
     45     }
     46     return is_ds;
     47 }
     48 
     49 // Return true if format is a stencil-only format
     50 bool vk_format_is_stencil_only(VkFormat format) { return (format == VK_FORMAT_S8_UINT); }
     51 
     52 // Return true if format is a depth-only format
     53 bool vk_format_is_depth_only(VkFormat format) {
     54     bool is_depth = false;
     55 
     56     switch (format) {
     57     case VK_FORMAT_D16_UNORM:
     58     case VK_FORMAT_X8_D24_UNORM_PACK32:
     59     case VK_FORMAT_D32_SFLOAT:
     60         is_depth = true;
     61         break;
     62     default:
     63         break;
     64     }
     65 
     66     return is_depth;
     67 }
     68 
     69 VkRenderFramework::VkRenderFramework()
     70     : inst(VK_NULL_HANDLE), m_device(NULL), m_commandPool(VK_NULL_HANDLE), m_commandBuffer(NULL), m_renderPass(VK_NULL_HANDLE),
     71       m_framebuffer(VK_NULL_HANDLE), m_width(256.0), // default window width
     72       m_height(256.0),                               // default window height
     73       m_render_target_fmt(VK_FORMAT_R8G8B8A8_UNORM), m_depth_stencil_fmt(VK_FORMAT_UNDEFINED), m_clear_via_load_op(true),
     74       m_depth_clear_color(1.0), m_stencil_clear_color(0), m_depthStencil(NULL), m_CreateDebugReportCallback(VK_NULL_HANDLE),
     75       m_DestroyDebugReportCallback(VK_NULL_HANDLE), m_globalMsgCallback(VK_NULL_HANDLE), m_devMsgCallback(VK_NULL_HANDLE) {
     76 
     77     memset(&m_renderPassBeginInfo, 0, sizeof(m_renderPassBeginInfo));
     78     m_renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
     79 
     80     // clear the back buffer to dark grey
     81     m_clear_color.float32[0] = 0.25f;
     82     m_clear_color.float32[1] = 0.25f;
     83     m_clear_color.float32[2] = 0.25f;
     84     m_clear_color.float32[3] = 0.0f;
     85 }
     86 
     87 VkRenderFramework::~VkRenderFramework() {}
     88 
     89 void VkRenderFramework::InitFramework() {
     90     std::vector<const char *> instance_layer_names;
     91     std::vector<const char *> instance_extension_names;
     92     std::vector<const char *> device_extension_names;
     93     instance_extension_names.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
     94     device_extension_names.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
     95 #ifdef _WIN32
     96     instance_extension_names.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
     97 #endif
     98 #ifdef VK_USE_PLATFORM_XCB_KHR
     99     instance_extension_names.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
    100 #endif
    101     InitFramework(instance_layer_names, instance_extension_names, device_extension_names);
    102 }
    103 
    104 void VkRenderFramework::InitFramework(std::vector<const char *> instance_layer_names,
    105                                       std::vector<const char *> instance_extension_names,
    106                                       std::vector<const char *> device_extension_names, PFN_vkDebugReportCallbackEXT dbgFunction,
    107                                       void *userData) {
    108     VkInstanceCreateInfo instInfo = {};
    109     std::vector<VkExtensionProperties> instance_extensions;
    110     std::vector<VkExtensionProperties> device_extensions;
    111     VkResult U_ASSERT_ONLY err;
    112 
    113     /* TODO: Verify requested extensions are available */
    114 
    115     instInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
    116     instInfo.pNext = NULL;
    117     instInfo.pApplicationInfo = &app_info;
    118     instInfo.enabledLayerCount = instance_layer_names.size();
    119     instInfo.ppEnabledLayerNames = instance_layer_names.data();
    120     instInfo.enabledExtensionCount = instance_extension_names.size();
    121     instInfo.ppEnabledExtensionNames = instance_extension_names.data();
    122     err = vkCreateInstance(&instInfo, NULL, &this->inst);
    123     ASSERT_VK_SUCCESS(err);
    124 
    125     err = vkEnumeratePhysicalDevices(inst, &this->gpu_count, NULL);
    126     ASSERT_LE(this->gpu_count, ARRAY_SIZE(objs)) << "Too many gpus";
    127     ASSERT_VK_SUCCESS(err);
    128     err = vkEnumeratePhysicalDevices(inst, &this->gpu_count, objs);
    129     ASSERT_VK_SUCCESS(err);
    130     ASSERT_GE(this->gpu_count, (uint32_t)1) << "No GPU available";
    131     if (dbgFunction) {
    132         m_CreateDebugReportCallback =
    133             (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(this->inst, "vkCreateDebugReportCallbackEXT");
    134         ASSERT_NE(m_CreateDebugReportCallback, (PFN_vkCreateDebugReportCallbackEXT)NULL)
    135             << "Did not get function pointer for CreateDebugReportCallback";
    136         if (m_CreateDebugReportCallback) {
    137             VkDebugReportCallbackCreateInfoEXT dbgCreateInfo;
    138             memset(&dbgCreateInfo, 0, sizeof(dbgCreateInfo));
    139             dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
    140             dbgCreateInfo.flags =
    141                 VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
    142             dbgCreateInfo.pfnCallback = dbgFunction;
    143             dbgCreateInfo.pUserData = userData;
    144 
    145             err = m_CreateDebugReportCallback(this->inst, &dbgCreateInfo, NULL, &m_globalMsgCallback);
    146             ASSERT_VK_SUCCESS(err);
    147 
    148             m_DestroyDebugReportCallback =
    149                 (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(this->inst, "vkDestroyDebugReportCallbackEXT");
    150             ASSERT_NE(m_DestroyDebugReportCallback, (PFN_vkDestroyDebugReportCallbackEXT)NULL)
    151                 << "Did not get function pointer for "
    152                    "DestroyDebugReportCallback";
    153             m_DebugReportMessage = (PFN_vkDebugReportMessageEXT)vkGetInstanceProcAddr(this->inst, "vkDebugReportMessageEXT");
    154             ASSERT_NE(m_DebugReportMessage, (PFN_vkDebugReportMessageEXT)NULL)
    155                 << "Did not get function pointer for DebugReportMessage";
    156         }
    157     }
    158 
    159     /* TODO: Verify requested physical device extensions are available */
    160     this->device_extension_names = device_extension_names;
    161 }
    162 
    163 void VkRenderFramework::ShutdownFramework() {
    164     delete m_commandBuffer;
    165     if (m_commandPool)
    166         vkDestroyCommandPool(device(), m_commandPool, NULL);
    167     if (m_framebuffer)
    168         vkDestroyFramebuffer(device(), m_framebuffer, NULL);
    169     if (m_renderPass)
    170         vkDestroyRenderPass(device(), m_renderPass, NULL);
    171 
    172     if (m_globalMsgCallback)
    173         m_DestroyDebugReportCallback(this->inst, m_globalMsgCallback, NULL);
    174     if (m_devMsgCallback)
    175         m_DestroyDebugReportCallback(this->inst, m_devMsgCallback, NULL);
    176 
    177     while (!m_renderTargets.empty()) {
    178         vkDestroyImageView(device(), m_renderTargets.back()->targetView(m_render_target_fmt), NULL);
    179         vkDestroyImage(device(), m_renderTargets.back()->image(), NULL);
    180         vkFreeMemory(device(), m_renderTargets.back()->memory(), NULL);
    181         m_renderTargets.pop_back();
    182     }
    183 
    184     delete m_depthStencil;
    185 
    186     // reset the driver
    187     delete m_device;
    188     if (this->inst)
    189         vkDestroyInstance(this->inst, NULL);
    190 }
    191 
    192 void VkRenderFramework::InitState(VkPhysicalDeviceFeatures *features) {
    193     VkResult U_ASSERT_ONLY err;
    194 
    195     m_device = new VkDeviceObj(0, objs[0], device_extension_names, features);
    196     m_device->get_device_queue();
    197 
    198     m_depthStencil = new VkDepthStencilObj(m_device);
    199 
    200     m_render_target_fmt = VkTestFramework::GetFormat(inst, m_device);
    201 
    202     m_lineWidth = 1.0f;
    203 
    204     m_depthBiasConstantFactor = 0.0f;
    205     m_depthBiasClamp = 0.0f;
    206     m_depthBiasSlopeFactor = 0.0f;
    207 
    208     m_blendConstants[0] = 1.0f;
    209     m_blendConstants[1] = 1.0f;
    210     m_blendConstants[2] = 1.0f;
    211     m_blendConstants[3] = 1.0f;
    212 
    213     m_minDepthBounds = 0.f;
    214     m_maxDepthBounds = 1.f;
    215 
    216     m_compareMask = 0xff;
    217     m_writeMask = 0xff;
    218     m_reference = 0;
    219 
    220     VkCommandPoolCreateInfo cmd_pool_info;
    221     cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, cmd_pool_info.pNext = NULL,
    222     cmd_pool_info.queueFamilyIndex = m_device->graphics_queue_node_index_;
    223     cmd_pool_info.flags = 0, err = vkCreateCommandPool(device(), &cmd_pool_info, NULL, &m_commandPool);
    224     assert(!err);
    225 
    226     m_commandBuffer = new VkCommandBufferObj(m_device, m_commandPool);
    227 }
    228 
    229 void VkRenderFramework::InitViewport(float width, float height) {
    230     VkViewport viewport;
    231     VkRect2D scissor;
    232     viewport.x = 0;
    233     viewport.y = 0;
    234     viewport.width = 1.f * width;
    235     viewport.height = 1.f * height;
    236     viewport.minDepth = 0.f;
    237     viewport.maxDepth = 1.f;
    238     m_viewports.push_back(viewport);
    239 
    240     scissor.extent.width = (int32_t)width;
    241     scissor.extent.height = (int32_t)height;
    242     scissor.offset.x = 0;
    243     scissor.offset.y = 0;
    244     m_scissors.push_back(scissor);
    245 
    246     m_width = width;
    247     m_height = height;
    248 }
    249 
    250 void VkRenderFramework::InitViewport() { InitViewport(m_width, m_height); }
    251 void VkRenderFramework::InitRenderTarget() { InitRenderTarget(1); }
    252 
    253 void VkRenderFramework::InitRenderTarget(uint32_t targets) { InitRenderTarget(targets, NULL); }
    254 
    255 void VkRenderFramework::InitRenderTarget(VkImageView *dsBinding) { InitRenderTarget(1, dsBinding); }
    256 
    257 void VkRenderFramework::InitRenderTarget(uint32_t targets, VkImageView *dsBinding) {
    258     std::vector<VkAttachmentDescription> attachments;
    259     std::vector<VkAttachmentReference> color_references;
    260     std::vector<VkImageView> bindings;
    261     attachments.reserve(targets + 1); // +1 for dsBinding
    262     color_references.reserve(targets);
    263     bindings.reserve(targets + 1); // +1 for dsBinding
    264 
    265     VkAttachmentDescription att = {};
    266     att.format = m_render_target_fmt;
    267     att.samples = VK_SAMPLE_COUNT_1_BIT;
    268     att.loadOp = (m_clear_via_load_op) ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
    269     att.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
    270     att.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
    271     att.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
    272     att.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
    273     att.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
    274 
    275     VkAttachmentReference ref = {};
    276     ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
    277 
    278     m_renderPassClearValues.clear();
    279     VkClearValue clear = {};
    280     clear.color = m_clear_color;
    281 
    282     VkImageView bind = {};
    283 
    284     for (uint32_t i = 0; i < targets; i++) {
    285         attachments.push_back(att);
    286 
    287         ref.attachment = i;
    288         color_references.push_back(ref);
    289 
    290         m_renderPassClearValues.push_back(clear);
    291 
    292         VkImageObj *img = new VkImageObj(m_device);
    293 
    294         VkFormatProperties props;
    295 
    296         vkGetPhysicalDeviceFormatProperties(m_device->phy().handle(), m_render_target_fmt, &props);
    297 
    298         if (props.linearTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) {
    299             img->init((uint32_t)m_width, (uint32_t)m_height, m_render_target_fmt,
    300                       VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_TILING_LINEAR);
    301         } else if (props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) {
    302             img->init((uint32_t)m_width, (uint32_t)m_height, m_render_target_fmt,
    303                       VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_TILING_OPTIMAL);
    304         } else {
    305             FAIL() << "Neither Linear nor Optimal allowed for render target";
    306         }
    307 
    308         m_renderTargets.push_back(img);
    309         bind = img->targetView(m_render_target_fmt);
    310         bindings.push_back(bind);
    311     }
    312 
    313     VkSubpassDescription subpass = {};
    314     subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
    315     subpass.flags = 0;
    316     subpass.inputAttachmentCount = 0;
    317     subpass.pInputAttachments = NULL;
    318     subpass.colorAttachmentCount = targets;
    319     subpass.pColorAttachments = color_references.data();
    320     subpass.pResolveAttachments = NULL;
    321 
    322     VkAttachmentReference ds_reference;
    323     if (dsBinding) {
    324         att.format = m_depth_stencil_fmt;
    325         att.loadOp = (m_clear_via_load_op) ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
    326         ;
    327         att.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
    328         att.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
    329         att.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
    330         att.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
    331         att.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
    332         attachments.push_back(att);
    333 
    334         clear.depthStencil.depth = m_depth_clear_color;
    335         clear.depthStencil.stencil = m_stencil_clear_color;
    336         m_renderPassClearValues.push_back(clear);
    337 
    338         bindings.push_back(*dsBinding);
    339 
    340         ds_reference.attachment = targets;
    341         ds_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
    342         subpass.pDepthStencilAttachment = &ds_reference;
    343     } else {
    344         subpass.pDepthStencilAttachment = NULL;
    345     }
    346 
    347     subpass.preserveAttachmentCount = 0;
    348     subpass.pPreserveAttachments = NULL;
    349 
    350     VkRenderPassCreateInfo rp_info = {};
    351     rp_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
    352     rp_info.attachmentCount = attachments.size();
    353     rp_info.pAttachments = attachments.data();
    354     rp_info.subpassCount = 1;
    355     rp_info.pSubpasses = &subpass;
    356 
    357     vkCreateRenderPass(device(), &rp_info, NULL, &m_renderPass);
    358 
    359     // Create Framebuffer and RenderPass with color attachments and any
    360     // depth/stencil attachment
    361     VkFramebufferCreateInfo fb_info = {};
    362     fb_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
    363     fb_info.pNext = NULL;
    364     fb_info.renderPass = m_renderPass;
    365     fb_info.attachmentCount = bindings.size();
    366     fb_info.pAttachments = bindings.data();
    367     fb_info.width = (uint32_t)m_width;
    368     fb_info.height = (uint32_t)m_height;
    369     fb_info.layers = 1;
    370 
    371     vkCreateFramebuffer(device(), &fb_info, NULL, &m_framebuffer);
    372 
    373     m_renderPassBeginInfo.renderPass = m_renderPass;
    374     m_renderPassBeginInfo.framebuffer = m_framebuffer;
    375     m_renderPassBeginInfo.renderArea.extent.width = (int32_t)m_width;
    376     m_renderPassBeginInfo.renderArea.extent.height = (int32_t)m_height;
    377     m_renderPassBeginInfo.clearValueCount = m_renderPassClearValues.size();
    378     m_renderPassBeginInfo.pClearValues = m_renderPassClearValues.data();
    379 }
    380 
    381 VkDeviceObj::VkDeviceObj(uint32_t id, VkPhysicalDevice obj) : vk_testing::Device(obj), id(id) {
    382     init();
    383 
    384     props = phy().properties();
    385     queue_props = phy().queue_properties();
    386 }
    387 
    388 VkDeviceObj::VkDeviceObj(uint32_t id, VkPhysicalDevice obj, std::vector<const char *> &extension_names,
    389                          VkPhysicalDeviceFeatures *features)
    390     : vk_testing::Device(obj), id(id) {
    391     init(extension_names, features);
    392 
    393     props = phy().properties();
    394     queue_props = phy().queue_properties();
    395 }
    396 
    397 void VkDeviceObj::get_device_queue() {
    398     ASSERT_NE(true, graphics_queues().empty());
    399     m_queue = graphics_queues()[0]->handle();
    400 }
    401 
    402 VkDescriptorSetObj::VkDescriptorSetObj(VkDeviceObj *device) : m_device(device), m_nextSlot(0) {}
    403 
    404 VkDescriptorSetObj::~VkDescriptorSetObj() {
    405     if (m_set) {
    406         delete m_set;
    407     }
    408 }
    409 
    410 int VkDescriptorSetObj::AppendDummy() {
    411     /* request a descriptor but do not update it */
    412     VkDescriptorSetLayoutBinding binding = {};
    413     binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
    414     binding.descriptorCount = 1;
    415     binding.binding = m_layout_bindings.size();
    416     binding.stageFlags = VK_SHADER_STAGE_ALL;
    417     binding.pImmutableSamplers = NULL;
    418 
    419     m_layout_bindings.push_back(binding);
    420     m_type_counts[VK_DESCRIPTOR_TYPE_STORAGE_BUFFER] += binding.descriptorCount;
    421 
    422     return m_nextSlot++;
    423 }
    424 
    425 int VkDescriptorSetObj::AppendBuffer(VkDescriptorType type, VkConstantBufferObj &constantBuffer) {
    426     assert(type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
    427            type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER || type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC);
    428     VkDescriptorSetLayoutBinding binding = {};
    429     binding.descriptorType = type;
    430     binding.descriptorCount = 1;
    431     binding.binding = m_layout_bindings.size();
    432     binding.stageFlags = VK_SHADER_STAGE_ALL;
    433     binding.pImmutableSamplers = NULL;
    434 
    435     m_layout_bindings.push_back(binding);
    436     m_type_counts[type] += binding.descriptorCount;
    437 
    438     m_writes.push_back(vk_testing::Device::write_descriptor_set(vk_testing::DescriptorSet(), m_nextSlot, 0, type, 1,
    439                                                                 &constantBuffer.m_descriptorBufferInfo));
    440 
    441     return m_nextSlot++;
    442 }
    443 
    444 int VkDescriptorSetObj::AppendSamplerTexture(VkSamplerObj *sampler, VkTextureObj *texture) {
    445     VkDescriptorSetLayoutBinding binding = {};
    446     binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
    447     binding.descriptorCount = 1;
    448     binding.binding = m_layout_bindings.size();
    449     binding.stageFlags = VK_SHADER_STAGE_ALL;
    450     binding.pImmutableSamplers = NULL;
    451 
    452     m_layout_bindings.push_back(binding);
    453     m_type_counts[VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER] += binding.descriptorCount;
    454     VkDescriptorImageInfo tmp = texture->m_imageInfo;
    455     tmp.sampler = sampler->handle();
    456     m_imageSamplerDescriptors.push_back(tmp);
    457 
    458     m_writes.push_back(vk_testing::Device::write_descriptor_set(vk_testing::DescriptorSet(), m_nextSlot, 0,
    459                                                                 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &tmp));
    460 
    461     return m_nextSlot++;
    462 }
    463 
    464 VkPipelineLayout VkDescriptorSetObj::GetPipelineLayout() const { return m_pipeline_layout.handle(); }
    465 
    466 VkDescriptorSet VkDescriptorSetObj::GetDescriptorSetHandle() const { return m_set->handle(); }
    467 
    468 void VkDescriptorSetObj::CreateVKDescriptorSet(VkCommandBufferObj *commandBuffer) {
    469 
    470     if (m_type_counts.size()) {
    471         // create VkDescriptorPool
    472         VkDescriptorPoolSize poolSize;
    473         vector<VkDescriptorPoolSize> sizes;
    474         for (auto it = m_type_counts.begin(); it != m_type_counts.end(); ++it) {
    475             poolSize.descriptorCount = it->second;
    476             poolSize.type = it->first;
    477             sizes.push_back(poolSize);
    478         }
    479         VkDescriptorPoolCreateInfo pool = {};
    480         pool.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
    481         pool.poolSizeCount = sizes.size();
    482         pool.maxSets = 1;
    483         pool.pPoolSizes = sizes.data();
    484         init(*m_device, pool);
    485     }
    486 
    487     // create VkDescriptorSetLayout
    488     VkDescriptorSetLayoutCreateInfo layout = {};
    489     layout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
    490     layout.bindingCount = m_layout_bindings.size();
    491     layout.pBindings = m_layout_bindings.data();
    492 
    493     m_layout.init(*m_device, layout);
    494     vector<const vk_testing::DescriptorSetLayout *> layouts;
    495     layouts.push_back(&m_layout);
    496 
    497     // create VkPipelineLayout
    498     VkPipelineLayoutCreateInfo pipeline_layout = {};
    499     pipeline_layout.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
    500     pipeline_layout.setLayoutCount = layouts.size();
    501     pipeline_layout.pSetLayouts = NULL;
    502 
    503     m_pipeline_layout.init(*m_device, pipeline_layout, layouts);
    504 
    505     if (m_type_counts.size()) {
    506         // create VkDescriptorSet
    507         m_set = alloc_sets(*m_device, m_layout);
    508 
    509         // build the update array
    510         size_t imageSamplerCount = 0;
    511         for (std::vector<VkWriteDescriptorSet>::iterator it = m_writes.begin(); it != m_writes.end(); it++) {
    512             it->dstSet = m_set->handle();
    513             if (it->descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
    514                 it->pImageInfo = &m_imageSamplerDescriptors[imageSamplerCount++];
    515         }
    516 
    517         // do the updates
    518         m_device->update_descriptor_sets(m_writes);
    519     }
    520 }
    521 
    522 VkRenderpassObj::VkRenderpassObj(VkDeviceObj *dev) {
    523     // Create a renderPass with a single color attachment
    524     VkAttachmentReference attach = {};
    525     attach.layout = VK_IMAGE_LAYOUT_GENERAL;
    526 
    527     VkSubpassDescription subpass = {};
    528     subpass.pColorAttachments = &attach;
    529     subpass.colorAttachmentCount = 1;
    530 
    531     VkRenderPassCreateInfo rpci = {};
    532     rpci.subpassCount = 1;
    533     rpci.pSubpasses = &subpass;
    534     rpci.attachmentCount = 1;
    535 
    536     VkAttachmentDescription attach_desc = {};
    537     attach_desc.format = VK_FORMAT_B8G8R8A8_UNORM;
    538     attach_desc.samples = VK_SAMPLE_COUNT_1_BIT;
    539     attach_desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
    540     attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
    541 
    542     rpci.pAttachments = &attach_desc;
    543     rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
    544 
    545     device = dev->device();
    546     vkCreateRenderPass(device, &rpci, NULL, &m_renderpass);
    547 }
    548 
    549 VkRenderpassObj::~VkRenderpassObj() { vkDestroyRenderPass(device, m_renderpass, NULL); }
    550 
    551 VkImageObj::VkImageObj(VkDeviceObj *dev) {
    552     m_device = dev;
    553     m_descriptorImageInfo.imageView = VK_NULL_HANDLE;
    554     m_descriptorImageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
    555 }
    556 
    557 void VkImageObj::ImageMemoryBarrier(VkCommandBufferObj *cmd_buf, VkImageAspectFlags aspect, VkFlags output_mask /*=
    558             VK_ACCESS_HOST_WRITE_BIT |
    559             VK_ACCESS_SHADER_WRITE_BIT |
    560             VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
    561             VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
    562             VK_MEMORY_OUTPUT_COPY_BIT*/,
    563                                     VkFlags input_mask /*=
    564             VK_ACCESS_HOST_READ_BIT |
    565             VK_ACCESS_INDIRECT_COMMAND_READ_BIT |
    566             VK_ACCESS_INDEX_READ_BIT |
    567             VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT |
    568             VK_ACCESS_UNIFORM_READ_BIT |
    569             VK_ACCESS_SHADER_READ_BIT |
    570             VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
    571             VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
    572             VK_MEMORY_INPUT_COPY_BIT*/, VkImageLayout image_layout) {
    573     const VkImageSubresourceRange subresourceRange = subresource_range(aspect, 0, 1, 0, 1);
    574     VkImageMemoryBarrier barrier;
    575     barrier = image_memory_barrier(output_mask, input_mask, layout(), image_layout, subresourceRange);
    576 
    577     VkImageMemoryBarrier *pmemory_barrier = &barrier;
    578 
    579     VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
    580     VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
    581 
    582     // write barrier to the command buffer
    583     vkCmdPipelineBarrier(cmd_buf->handle(), src_stages, dest_stages, 0, 0, NULL, 0, NULL, 1, pmemory_barrier);
    584 }
    585 
    586 void VkImageObj::SetLayout(VkCommandBufferObj *cmd_buf, VkImageAspectFlags aspect, VkImageLayout image_layout) {
    587     VkFlags src_mask, dst_mask;
    588     const VkFlags all_cache_outputs = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
    589                                       VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
    590     const VkFlags all_cache_inputs = VK_ACCESS_HOST_READ_BIT | VK_ACCESS_INDIRECT_COMMAND_READ_BIT | VK_ACCESS_INDEX_READ_BIT |
    591                                      VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_UNIFORM_READ_BIT | VK_ACCESS_SHADER_READ_BIT |
    592                                      VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
    593                                      VK_ACCESS_MEMORY_READ_BIT;
    594 
    595     if (image_layout == m_descriptorImageInfo.imageLayout) {
    596         return;
    597     }
    598 
    599     switch (image_layout) {
    600     case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
    601         if (m_descriptorImageInfo.imageLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
    602             src_mask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
    603         else
    604             src_mask = VK_ACCESS_TRANSFER_WRITE_BIT;
    605         dst_mask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT;
    606         break;
    607 
    608     case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
    609         if (m_descriptorImageInfo.imageLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
    610             src_mask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
    611         else if (m_descriptorImageInfo.imageLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
    612             src_mask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
    613         else
    614             src_mask = VK_ACCESS_TRANSFER_WRITE_BIT;
    615         dst_mask = VK_ACCESS_TRANSFER_WRITE_BIT;
    616         break;
    617 
    618     case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
    619         if (m_descriptorImageInfo.imageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
    620             src_mask = VK_ACCESS_TRANSFER_WRITE_BIT;
    621         else
    622             src_mask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
    623         dst_mask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_MEMORY_READ_BIT;
    624         break;
    625 
    626     case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
    627         if (m_descriptorImageInfo.imageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
    628             src_mask = VK_ACCESS_TRANSFER_READ_BIT;
    629         else
    630             src_mask = 0;
    631         dst_mask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
    632         break;
    633 
    634     case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
    635         dst_mask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
    636         src_mask = all_cache_outputs;
    637         break;
    638 
    639     default:
    640         src_mask = all_cache_outputs;
    641         dst_mask = all_cache_inputs;
    642         break;
    643     }
    644 
    645     if (m_descriptorImageInfo.imageLayout == VK_IMAGE_LAYOUT_UNDEFINED)
    646         src_mask = 0;
    647 
    648     ImageMemoryBarrier(cmd_buf, aspect, src_mask, dst_mask, image_layout);
    649     m_descriptorImageInfo.imageLayout = image_layout;
    650 }
    651 
    652 void VkImageObj::SetLayout(VkImageAspectFlags aspect, VkImageLayout image_layout) {
    653     VkResult U_ASSERT_ONLY err;
    654 
    655     if (image_layout == m_descriptorImageInfo.imageLayout) {
    656         return;
    657     }
    658 
    659     VkCommandPoolCreateInfo cmd_pool_info = {};
    660     cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
    661     cmd_pool_info.pNext = NULL;
    662     cmd_pool_info.queueFamilyIndex = m_device->graphics_queue_node_index_;
    663     cmd_pool_info.flags = 0;
    664     vk_testing::CommandPool pool(*m_device, cmd_pool_info);
    665     VkCommandBufferObj cmd_buf(m_device, pool.handle());
    666 
    667     /* Build command buffer to set image layout in the driver */
    668     err = cmd_buf.BeginCommandBuffer();
    669     assert(!err);
    670 
    671     SetLayout(&cmd_buf, aspect, image_layout);
    672 
    673     err = cmd_buf.EndCommandBuffer();
    674     assert(!err);
    675 
    676     cmd_buf.QueueCommandBuffer();
    677 }
    678 
    679 bool VkImageObj::IsCompatible(VkFlags usage, VkFlags features) {
    680     if ((usage & VK_IMAGE_USAGE_SAMPLED_BIT) && !(features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT))
    681         return false;
    682 
    683     return true;
    684 }
    685 
    686 void VkImageObj::init_no_layout(uint32_t w, uint32_t h, VkFormat fmt, VkFlags usage, VkImageTiling requested_tiling,
    687                                 VkMemoryPropertyFlags reqs) {
    688 
    689     VkFormatProperties image_fmt;
    690     VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL;
    691 
    692     vkGetPhysicalDeviceFormatProperties(m_device->phy().handle(), fmt, &image_fmt);
    693 
    694     if (requested_tiling == VK_IMAGE_TILING_LINEAR) {
    695         if (IsCompatible(usage, image_fmt.linearTilingFeatures)) {
    696             tiling = VK_IMAGE_TILING_LINEAR;
    697         } else if (IsCompatible(usage, image_fmt.optimalTilingFeatures)) {
    698             tiling = VK_IMAGE_TILING_OPTIMAL;
    699         } else {
    700             ASSERT_TRUE(false) << "Error: Cannot find requested tiling configuration";
    701         }
    702     } else if (IsCompatible(usage, image_fmt.optimalTilingFeatures)) {
    703         tiling = VK_IMAGE_TILING_OPTIMAL;
    704     } else if (IsCompatible(usage, image_fmt.linearTilingFeatures)) {
    705         tiling = VK_IMAGE_TILING_LINEAR;
    706     } else {
    707         ASSERT_TRUE(false) << "Error: Cannot find requested tiling configuration";
    708     }
    709 
    710     VkImageCreateInfo imageCreateInfo = vk_testing::Image::create_info();
    711     imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
    712     imageCreateInfo.format = fmt;
    713     imageCreateInfo.extent.width = w;
    714     imageCreateInfo.extent.height = h;
    715     imageCreateInfo.mipLevels = 1;
    716     imageCreateInfo.tiling = tiling;
    717     imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
    718 
    719     layout(imageCreateInfo.initialLayout);
    720     imageCreateInfo.usage = usage;
    721 
    722     vk_testing::Image::init(*m_device, imageCreateInfo, reqs);
    723 }
    724 
    725 void VkImageObj::init(uint32_t w, uint32_t h, VkFormat fmt, VkFlags usage, VkImageTiling requested_tiling,
    726                       VkMemoryPropertyFlags reqs) {
    727 
    728     init_no_layout(w, h, fmt, usage, requested_tiling, reqs);
    729 
    730     VkImageLayout newLayout;
    731     if (usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
    732         newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
    733     else if (usage & VK_IMAGE_USAGE_SAMPLED_BIT)
    734         newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
    735     else
    736         newLayout = m_descriptorImageInfo.imageLayout;
    737 
    738     VkImageAspectFlags image_aspect = 0;
    739     if (vk_format_is_depth_and_stencil(fmt)) {
    740         image_aspect = VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT;
    741     } else if (vk_format_is_depth_only(fmt)) {
    742         image_aspect = VK_IMAGE_ASPECT_DEPTH_BIT;
    743     } else if (vk_format_is_stencil_only(fmt)) {
    744         image_aspect = VK_IMAGE_ASPECT_STENCIL_BIT;
    745     } else { // color
    746         image_aspect = VK_IMAGE_ASPECT_COLOR_BIT;
    747     }
    748     SetLayout(image_aspect, newLayout);
    749 }
    750 
    751 VkResult VkImageObj::CopyImage(VkImageObj &src_image) {
    752     VkResult U_ASSERT_ONLY err;
    753     VkImageLayout src_image_layout, dest_image_layout;
    754 
    755     VkCommandPoolCreateInfo cmd_pool_info = {};
    756     cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
    757     cmd_pool_info.pNext = NULL;
    758     cmd_pool_info.queueFamilyIndex = m_device->graphics_queue_node_index_;
    759     cmd_pool_info.flags = 0;
    760     vk_testing::CommandPool pool(*m_device, cmd_pool_info);
    761     VkCommandBufferObj cmd_buf(m_device, pool.handle());
    762 
    763     /* Build command buffer to copy staging texture to usable texture */
    764     err = cmd_buf.BeginCommandBuffer();
    765     assert(!err);
    766 
    767     /* TODO: Can we determine image aspect from image object? */
    768     src_image_layout = src_image.layout();
    769     src_image.SetLayout(&cmd_buf, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
    770 
    771     dest_image_layout = (this->layout() == VK_IMAGE_LAYOUT_UNDEFINED) ? VK_IMAGE_LAYOUT_GENERAL : this->layout();
    772     this->SetLayout(&cmd_buf, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
    773 
    774     VkImageCopy copy_region = {};
    775     copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    776     copy_region.srcSubresource.baseArrayLayer = 0;
    777     copy_region.srcSubresource.mipLevel = 0;
    778     copy_region.srcSubresource.layerCount = 1;
    779     copy_region.srcOffset.x = 0;
    780     copy_region.srcOffset.y = 0;
    781     copy_region.srcOffset.z = 0;
    782     copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    783     copy_region.dstSubresource.baseArrayLayer = 0;
    784     copy_region.dstSubresource.mipLevel = 0;
    785     copy_region.dstSubresource.layerCount = 1;
    786     copy_region.dstOffset.x = 0;
    787     copy_region.dstOffset.y = 0;
    788     copy_region.dstOffset.z = 0;
    789     copy_region.extent = src_image.extent();
    790 
    791     vkCmdCopyImage(cmd_buf.handle(), src_image.handle(), src_image.layout(), handle(), layout(), 1, &copy_region);
    792 
    793     src_image.SetLayout(&cmd_buf, VK_IMAGE_ASPECT_COLOR_BIT, src_image_layout);
    794 
    795     this->SetLayout(&cmd_buf, VK_IMAGE_ASPECT_COLOR_BIT, dest_image_layout);
    796 
    797     err = cmd_buf.EndCommandBuffer();
    798     assert(!err);
    799 
    800     cmd_buf.QueueCommandBuffer();
    801 
    802     return VK_SUCCESS;
    803 }
    804 
    805 VkTextureObj::VkTextureObj(VkDeviceObj *device, uint32_t *colors) : VkImageObj(device) {
    806     m_device = device;
    807     const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM;
    808     uint32_t tex_colors[2] = {0xffff0000, 0xff00ff00};
    809     void *data;
    810     uint32_t x, y;
    811     VkImageObj stagingImage(device);
    812     VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
    813 
    814     stagingImage.init(16, 16, tex_format, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_TILING_LINEAR,
    815                       reqs);
    816     VkSubresourceLayout layout = stagingImage.subresource_layout(subresource(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0));
    817 
    818     if (colors == NULL)
    819         colors = tex_colors;
    820 
    821     memset(&m_imageInfo, 0, sizeof(m_imageInfo));
    822 
    823     VkImageViewCreateInfo view = {};
    824     view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
    825     view.pNext = NULL;
    826     view.image = VK_NULL_HANDLE;
    827     view.viewType = VK_IMAGE_VIEW_TYPE_2D;
    828     view.format = tex_format;
    829     view.components.r = VK_COMPONENT_SWIZZLE_R;
    830     view.components.g = VK_COMPONENT_SWIZZLE_G;
    831     view.components.b = VK_COMPONENT_SWIZZLE_B;
    832     view.components.a = VK_COMPONENT_SWIZZLE_A;
    833     view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    834     view.subresourceRange.baseMipLevel = 0;
    835     view.subresourceRange.levelCount = 1;
    836     view.subresourceRange.baseArrayLayer = 0;
    837     view.subresourceRange.layerCount = 1;
    838 
    839     /* create image */
    840     init(16, 16, tex_format, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_OPTIMAL);
    841     stagingImage.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_GENERAL);
    842 
    843     /* create image view */
    844     view.image = handle();
    845     m_textureView.init(*m_device, view);
    846     m_imageInfo.imageView = m_textureView.handle();
    847 
    848     data = stagingImage.MapMemory();
    849 
    850     for (y = 0; y < extent().height; y++) {
    851         uint32_t *row = (uint32_t *)((char *)data + layout.rowPitch * y);
    852         for (x = 0; x < extent().width; x++)
    853             row[x] = colors[(x & 1) ^ (y & 1)];
    854     }
    855     stagingImage.UnmapMemory();
    856     stagingImage.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
    857     VkImageObj::CopyImage(stagingImage);
    858 }
    859 
    860 VkSamplerObj::VkSamplerObj(VkDeviceObj *device) {
    861     m_device = device;
    862 
    863     VkSamplerCreateInfo samplerCreateInfo;
    864     memset(&samplerCreateInfo, 0, sizeof(samplerCreateInfo));
    865     samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
    866     samplerCreateInfo.magFilter = VK_FILTER_NEAREST;
    867     samplerCreateInfo.minFilter = VK_FILTER_NEAREST;
    868     samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
    869     samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
    870     samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
    871     samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
    872     samplerCreateInfo.mipLodBias = 0.0;
    873     samplerCreateInfo.anisotropyEnable = VK_FALSE;
    874     samplerCreateInfo.maxAnisotropy = 1;
    875     samplerCreateInfo.compareOp = VK_COMPARE_OP_NEVER;
    876     samplerCreateInfo.minLod = 0.0;
    877     samplerCreateInfo.maxLod = 0.0;
    878     samplerCreateInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
    879     samplerCreateInfo.unnormalizedCoordinates = VK_FALSE;
    880 
    881     init(*m_device, samplerCreateInfo);
    882 }
    883 
    884 /*
    885  * Basic ConstantBuffer constructor. Then use create methods to fill in the
    886  * details.
    887  */
    888 VkConstantBufferObj::VkConstantBufferObj(VkDeviceObj *device, VkBufferUsageFlags usage) {
    889     m_device = device;
    890     m_commandBuffer = 0;
    891 
    892     memset(&m_descriptorBufferInfo, 0, sizeof(m_descriptorBufferInfo));
    893 
    894     // Special case for usages outside of original limits of framework
    895     if ((VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT) != usage) {
    896         init_no_mem(*m_device, create_info(0, usage));
    897     }
    898 }
    899 
    900 VkConstantBufferObj::~VkConstantBufferObj() {
    901     // TODO: Should we call QueueRemoveMemReference for the constant buffer
    902     // memory here?
    903     if (m_commandBuffer) {
    904         delete m_commandBuffer;
    905         delete m_commandPool;
    906     }
    907 }
    908 
    909 VkConstantBufferObj::VkConstantBufferObj(VkDeviceObj *device, int constantCount, int constantSize, const void *data,
    910                                          VkBufferUsageFlags usage) {
    911     m_device = device;
    912     m_commandBuffer = 0;
    913 
    914     memset(&m_descriptorBufferInfo, 0, sizeof(m_descriptorBufferInfo));
    915     m_numVertices = constantCount;
    916     m_stride = constantSize;
    917 
    918     VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
    919     const VkDeviceSize allocationSize = static_cast<VkDeviceSize>(constantCount * constantSize);
    920 
    921     if ((VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT) == usage) {
    922         init_as_src_and_dst(*m_device, allocationSize, reqs);
    923     } else {
    924         init(*m_device, create_info(allocationSize, usage), reqs);
    925     }
    926 
    927     void *pData = memory().map();
    928     memcpy(pData, data, static_cast<size_t>(allocationSize));
    929     memory().unmap();
    930 
    931     /*
    932      * Constant buffers are going to be used as vertex input buffers
    933      * or as shader uniform buffers. So, we'll create the shaderbuffer
    934      * descriptor here so it's ready if needed.
    935      */
    936     this->m_descriptorBufferInfo.buffer = handle();
    937     this->m_descriptorBufferInfo.offset = 0;
    938     this->m_descriptorBufferInfo.range = allocationSize;
    939 }
    940 
    941 void VkConstantBufferObj::Bind(VkCommandBuffer commandBuffer, VkDeviceSize offset, uint32_t binding) {
    942     vkCmdBindVertexBuffers(commandBuffer, binding, 1, &handle(), &offset);
    943 }
    944 
    945 void VkConstantBufferObj::BufferMemoryBarrier(VkFlags srcAccessMask /*=
    946             VK_ACCESS_HOST_WRITE_BIT |
    947             VK_ACCESS_SHADER_WRITE_BIT |
    948             VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
    949             VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
    950             VK_MEMORY_OUTPUT_COPY_BIT*/, VkFlags dstAccessMask /*=
    951             VK_ACCESS_HOST_READ_BIT |
    952             VK_ACCESS_INDIRECT_COMMAND_READ_BIT |
    953             VK_ACCESS_INDEX_READ_BIT |
    954             VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT |
    955             VK_ACCESS_UNIFORM_READ_BIT |
    956             VK_ACCESS_SHADER_READ_BIT |
    957             VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
    958             VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
    959             VK_MEMORY_INPUT_COPY_BIT*/) {
    960     VkResult err = VK_SUCCESS;
    961 
    962     if (!m_commandBuffer) {
    963         m_fence.init(*m_device, vk_testing::Fence::create_info());
    964         VkCommandPoolCreateInfo cmd_pool_info = {};
    965         cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
    966         cmd_pool_info.pNext = NULL;
    967         cmd_pool_info.queueFamilyIndex = m_device->graphics_queue_node_index_;
    968         cmd_pool_info.flags = 0;
    969         m_commandPool = new vk_testing::CommandPool(*m_device, cmd_pool_info);
    970         m_commandBuffer = new VkCommandBufferObj(m_device, m_commandPool->handle());
    971     } else {
    972         m_device->wait(m_fence);
    973     }
    974 
    975     // open the command buffer
    976     VkCommandBufferBeginInfo cmd_buf_info = {};
    977     VkCommandBufferInheritanceInfo cmd_buf_hinfo = {};
    978     cmd_buf_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
    979     cmd_buf_info.pNext = NULL;
    980     cmd_buf_info.flags = 0;
    981     cmd_buf_info.pInheritanceInfo = &cmd_buf_hinfo;
    982 
    983     cmd_buf_hinfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
    984     cmd_buf_hinfo.pNext = NULL;
    985     cmd_buf_hinfo.renderPass = VK_NULL_HANDLE;
    986     cmd_buf_hinfo.subpass = 0;
    987     cmd_buf_hinfo.framebuffer = VK_NULL_HANDLE;
    988     cmd_buf_hinfo.occlusionQueryEnable = VK_FALSE;
    989     cmd_buf_hinfo.queryFlags = 0;
    990     cmd_buf_hinfo.pipelineStatistics = 0;
    991 
    992     err = m_commandBuffer->BeginCommandBuffer(&cmd_buf_info);
    993     ASSERT_VK_SUCCESS(err);
    994 
    995     VkBufferMemoryBarrier memory_barrier = buffer_memory_barrier(srcAccessMask, dstAccessMask, 0, m_numVertices * m_stride);
    996     VkBufferMemoryBarrier *pmemory_barrier = &memory_barrier;
    997 
    998     VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
    999     VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
   1000 
   1001     // write barrier to the command buffer
   1002     m_commandBuffer->PipelineBarrier(src_stages, dest_stages, 0, 0, NULL, 1, pmemory_barrier, 0, NULL);
   1003 
   1004     // finish recording the command buffer
   1005     err = m_commandBuffer->EndCommandBuffer();
   1006     ASSERT_VK_SUCCESS(err);
   1007 
   1008     // submit the command buffer to the universal queue
   1009     VkCommandBuffer bufferArray[1];
   1010     bufferArray[0] = m_commandBuffer->GetBufferHandle();
   1011     VkSubmitInfo submit_info;
   1012     submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
   1013     submit_info.pNext = NULL;
   1014     submit_info.waitSemaphoreCount = 0;
   1015     submit_info.pWaitSemaphores = NULL;
   1016     submit_info.pWaitDstStageMask = NULL;
   1017     submit_info.commandBufferCount = 1;
   1018     submit_info.pCommandBuffers = bufferArray;
   1019     submit_info.signalSemaphoreCount = 0;
   1020     submit_info.pSignalSemaphores = NULL;
   1021 
   1022     err = vkQueueSubmit(m_device->m_queue, 1, &submit_info, m_fence.handle());
   1023     ASSERT_VK_SUCCESS(err);
   1024 }
   1025 
   1026 VkIndexBufferObj::VkIndexBufferObj(VkDeviceObj *device) : VkConstantBufferObj(device) {}
   1027 
   1028 void VkIndexBufferObj::CreateAndInitBuffer(int numIndexes, VkIndexType indexType, const void *data) {
   1029     m_numVertices = numIndexes;
   1030     m_indexType = indexType;
   1031     switch (indexType) {
   1032     case VK_INDEX_TYPE_UINT16:
   1033         m_stride = 2;
   1034         break;
   1035     case VK_INDEX_TYPE_UINT32:
   1036         m_stride = 4;
   1037         break;
   1038     default:
   1039         assert(!"unknown index type");
   1040         m_stride = 2;
   1041         break;
   1042     }
   1043 
   1044     const size_t allocationSize = numIndexes * m_stride;
   1045     VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
   1046     init_as_src_and_dst(*m_device, allocationSize, reqs);
   1047 
   1048     void *pData = memory().map();
   1049     memcpy(pData, data, allocationSize);
   1050     memory().unmap();
   1051 
   1052     // set up the descriptor for the constant buffer
   1053     this->m_descriptorBufferInfo.buffer = handle();
   1054     this->m_descriptorBufferInfo.offset = 0;
   1055     this->m_descriptorBufferInfo.range = allocationSize;
   1056 }
   1057 
   1058 void VkIndexBufferObj::Bind(VkCommandBuffer commandBuffer, VkDeviceSize offset) {
   1059     vkCmdBindIndexBuffer(commandBuffer, handle(), offset, m_indexType);
   1060 }
   1061 
   1062 VkIndexType VkIndexBufferObj::GetIndexType() { return m_indexType; }
   1063 
   1064 VkPipelineShaderStageCreateInfo VkShaderObj::GetStageCreateInfo() const {
   1065     VkPipelineShaderStageCreateInfo stageInfo = {};
   1066 
   1067     stageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
   1068     stageInfo.stage = m_stage;
   1069     stageInfo.module = handle();
   1070     stageInfo.pName = m_name;
   1071 
   1072     return stageInfo;
   1073 }
   1074 
   1075 VkShaderObj::VkShaderObj(VkDeviceObj *device, const char *shader_code, VkShaderStageFlagBits stage, VkRenderFramework *framework,
   1076                          char const *name) {
   1077     VkResult U_ASSERT_ONLY err = VK_SUCCESS;
   1078     std::vector<unsigned int> spv;
   1079     VkShaderModuleCreateInfo moduleCreateInfo;
   1080     size_t shader_len;
   1081 
   1082     m_stage = stage;
   1083     m_device = device;
   1084     m_name = name;
   1085 
   1086     moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
   1087     moduleCreateInfo.pNext = NULL;
   1088 
   1089     if (framework->m_use_glsl) {
   1090 
   1091         shader_len = strlen(shader_code);
   1092         moduleCreateInfo.codeSize = 3 * sizeof(uint32_t) + shader_len + 1;
   1093         moduleCreateInfo.pCode = (uint32_t *)malloc(moduleCreateInfo.codeSize);
   1094         moduleCreateInfo.flags = 0;
   1095 
   1096         /* try version 0 first: VkShaderStage followed by GLSL */
   1097         ((uint32_t *)moduleCreateInfo.pCode)[0] = ICD_SPV_MAGIC;
   1098         ((uint32_t *)moduleCreateInfo.pCode)[1] = 0;
   1099         ((uint32_t *)moduleCreateInfo.pCode)[2] = stage;
   1100         memcpy(((uint32_t *)moduleCreateInfo.pCode + 3), shader_code, shader_len + 1);
   1101 
   1102     } else {
   1103 
   1104         // Use Reference GLSL to SPV compiler
   1105         framework->GLSLtoSPV(stage, shader_code, spv);
   1106         moduleCreateInfo.pCode = spv.data();
   1107         moduleCreateInfo.codeSize = spv.size() * sizeof(unsigned int);
   1108         moduleCreateInfo.flags = 0;
   1109     }
   1110 
   1111     err = init_try(*m_device, moduleCreateInfo);
   1112     assert(VK_SUCCESS == err);
   1113 }
   1114 
   1115 VkPipelineObj::VkPipelineObj(VkDeviceObj *device) {
   1116     m_device = device;
   1117 
   1118     m_vi_state.pNext = VK_NULL_HANDLE;
   1119     m_vi_state.flags = 0;
   1120     m_vi_state.vertexBindingDescriptionCount = 0;
   1121     m_vi_state.pVertexBindingDescriptions = VK_NULL_HANDLE;
   1122     m_vi_state.vertexAttributeDescriptionCount = 0;
   1123     m_vi_state.pVertexAttributeDescriptions = VK_NULL_HANDLE;
   1124 
   1125     m_vertexBufferCount = 0;
   1126 
   1127     m_ia_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
   1128     m_ia_state.pNext = VK_NULL_HANDLE;
   1129     m_ia_state.flags = 0;
   1130     m_ia_state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
   1131     m_ia_state.primitiveRestartEnable = VK_FALSE;
   1132 
   1133     m_rs_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
   1134     m_rs_state.pNext = VK_NULL_HANDLE;
   1135     m_rs_state.flags = 0;
   1136     m_rs_state.depthClampEnable = VK_TRUE;
   1137     m_rs_state.rasterizerDiscardEnable = VK_FALSE;
   1138     m_rs_state.polygonMode = VK_POLYGON_MODE_FILL;
   1139     m_rs_state.cullMode = VK_CULL_MODE_BACK_BIT;
   1140     m_rs_state.frontFace = VK_FRONT_FACE_CLOCKWISE;
   1141     m_rs_state.depthBiasEnable = VK_FALSE;
   1142     m_rs_state.lineWidth = 1.0f;
   1143     m_rs_state.depthBiasConstantFactor = 0.0f;
   1144     m_rs_state.depthBiasClamp = 0.0f;
   1145     m_rs_state.depthBiasSlopeFactor = 0.0f;
   1146 
   1147     memset(&m_cb_state, 0, sizeof(m_cb_state));
   1148     m_cb_state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
   1149     m_cb_state.pNext = VK_NULL_HANDLE;
   1150     m_cb_state.logicOp = VK_LOGIC_OP_COPY;
   1151     m_cb_state.blendConstants[0] = 1.0f;
   1152     m_cb_state.blendConstants[1] = 1.0f;
   1153     m_cb_state.blendConstants[2] = 1.0f;
   1154     m_cb_state.blendConstants[3] = 1.0f;
   1155 
   1156     m_ms_state.pNext = VK_NULL_HANDLE;
   1157     m_ms_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
   1158     m_ms_state.flags = 0;
   1159     m_ms_state.pSampleMask = NULL;
   1160     m_ms_state.alphaToCoverageEnable = VK_FALSE;
   1161     m_ms_state.alphaToOneEnable = VK_FALSE;
   1162     m_ms_state.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
   1163     m_ms_state.minSampleShading = 0;
   1164     m_ms_state.sampleShadingEnable = 0;
   1165 
   1166     m_vp_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
   1167     m_vp_state.pNext = VK_NULL_HANDLE;
   1168     m_vp_state.flags = 0;
   1169     m_vp_state.viewportCount = 1;
   1170     m_vp_state.scissorCount = 1;
   1171     m_vp_state.pViewports = NULL;
   1172     m_vp_state.pScissors = NULL;
   1173 
   1174     m_ds_state = nullptr;
   1175 };
   1176 
   1177 void VkPipelineObj::AddShader(VkShaderObj *shader) { m_shaderObjs.push_back(shader); }
   1178 
   1179 void VkPipelineObj::AddVertexInputAttribs(VkVertexInputAttributeDescription *vi_attrib, uint32_t count) {
   1180     m_vi_state.pVertexAttributeDescriptions = vi_attrib;
   1181     m_vi_state.vertexAttributeDescriptionCount = count;
   1182 }
   1183 
   1184 void VkPipelineObj::AddVertexInputBindings(VkVertexInputBindingDescription *vi_binding, uint32_t count) {
   1185     m_vi_state.pVertexBindingDescriptions = vi_binding;
   1186     m_vi_state.vertexBindingDescriptionCount = count;
   1187 }
   1188 
   1189 void VkPipelineObj::AddColorAttachment(uint32_t binding, const VkPipelineColorBlendAttachmentState *att) {
   1190     if (binding + 1 > m_colorAttachments.size()) {
   1191         m_colorAttachments.resize(binding + 1);
   1192     }
   1193     m_colorAttachments[binding] = *att;
   1194 }
   1195 
   1196 void VkPipelineObj::SetDepthStencil(const VkPipelineDepthStencilStateCreateInfo *ds_state) {
   1197     m_ds_state = ds_state;
   1198 }
   1199 
   1200 void VkPipelineObj::SetViewport(const vector<VkViewport> viewports) {
   1201     m_viewports = viewports;
   1202     // If we explicitly set a null viewport, pass it through to create info
   1203     // but preserve viewportCount because it musn't change
   1204     if (m_viewports.size() == 0) {
   1205         m_vp_state.pViewports = nullptr;
   1206     }
   1207 }
   1208 
   1209 void VkPipelineObj::SetScissor(const vector<VkRect2D> scissors) {
   1210     m_scissors = scissors;
   1211     // If we explicitly set a null scissors, pass it through to create info
   1212     // but preserve viewportCount because it musn't change
   1213     if (m_scissors.size() == 0) {
   1214         m_vp_state.pScissors = nullptr;
   1215     }
   1216 }
   1217 
   1218 void VkPipelineObj::MakeDynamic(VkDynamicState state) {
   1219     /* Only add a state once */
   1220     for (auto it = m_dynamic_state_enables.begin(); it != m_dynamic_state_enables.end(); it++) {
   1221         if ((*it) == state)
   1222             return;
   1223     }
   1224     m_dynamic_state_enables.push_back(state);
   1225 }
   1226 
   1227 void VkPipelineObj::SetMSAA(const VkPipelineMultisampleStateCreateInfo *ms_state) { m_ms_state = *ms_state; }
   1228 
   1229 void VkPipelineObj::SetInputAssembly(const VkPipelineInputAssemblyStateCreateInfo *ia_state) { m_ia_state = *ia_state; }
   1230 
   1231 void VkPipelineObj::SetRasterization(const VkPipelineRasterizationStateCreateInfo *rs_state) { m_rs_state = *rs_state; }
   1232 
   1233 void VkPipelineObj::SetTessellation(const VkPipelineTessellationStateCreateInfo *te_state) { m_te_state = *te_state; }
   1234 
   1235 VkResult VkPipelineObj::CreateVKPipeline(VkPipelineLayout layout, VkRenderPass render_pass) {
   1236     VkGraphicsPipelineCreateInfo info = {};
   1237     VkPipelineDynamicStateCreateInfo dsci = {};
   1238 
   1239     info.stageCount = m_shaderObjs.size();
   1240     info.pStages = new VkPipelineShaderStageCreateInfo[info.stageCount];
   1241 
   1242     for (size_t i = 0; i < m_shaderObjs.size(); i++) {
   1243         ((VkPipelineShaderStageCreateInfo *)info.pStages)[i] = m_shaderObjs[i]->GetStageCreateInfo();
   1244     }
   1245 
   1246     m_vi_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
   1247     info.pVertexInputState = &m_vi_state;
   1248 
   1249     m_ia_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
   1250     info.pInputAssemblyState = &m_ia_state;
   1251 
   1252     info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
   1253     info.pNext = NULL;
   1254     info.flags = 0;
   1255     info.layout = layout;
   1256 
   1257     m_cb_state.attachmentCount = m_colorAttachments.size();
   1258     m_cb_state.pAttachments = m_colorAttachments.data();
   1259 
   1260     if (m_viewports.size() > 0) {
   1261         m_vp_state.viewportCount = m_viewports.size();
   1262         m_vp_state.pViewports = m_viewports.data();
   1263     } else {
   1264         MakeDynamic(VK_DYNAMIC_STATE_VIEWPORT);
   1265     }
   1266 
   1267     if (m_scissors.size() > 0) {
   1268         m_vp_state.scissorCount = m_scissors.size();
   1269         m_vp_state.pScissors = m_scissors.data();
   1270     } else {
   1271         MakeDynamic(VK_DYNAMIC_STATE_SCISSOR);
   1272     }
   1273 
   1274     if (m_dynamic_state_enables.size() > 0) {
   1275         dsci.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
   1276         dsci.dynamicStateCount = m_dynamic_state_enables.size();
   1277         dsci.pDynamicStates = m_dynamic_state_enables.data();
   1278         info.pDynamicState = &dsci;
   1279     }
   1280 
   1281     info.renderPass = render_pass;
   1282     info.subpass = 0;
   1283     info.pViewportState = &m_vp_state;
   1284     info.pRasterizationState = &m_rs_state;
   1285     info.pMultisampleState = &m_ms_state;
   1286     info.pDepthStencilState = m_ds_state;
   1287     info.pColorBlendState = &m_cb_state;
   1288 
   1289     if (m_ia_state.topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST) {
   1290         m_te_state.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
   1291         info.pTessellationState = &m_te_state;
   1292     } else {
   1293         info.pTessellationState = nullptr;
   1294     }
   1295 
   1296     return init_try(*m_device, info);
   1297 }
   1298 
   1299 VkCommandBufferObj::VkCommandBufferObj(VkDeviceObj *device, VkCommandPool pool) {
   1300     m_device = device;
   1301 
   1302     init(*device, vk_testing::CommandBuffer::create_info(pool));
   1303 }
   1304 
   1305 VkCommandBuffer VkCommandBufferObj::GetBufferHandle() { return handle(); }
   1306 
   1307 VkResult VkCommandBufferObj::BeginCommandBuffer(VkCommandBufferBeginInfo *pInfo) {
   1308     begin(pInfo);
   1309     return VK_SUCCESS;
   1310 }
   1311 
   1312 VkResult VkCommandBufferObj::BeginCommandBuffer() {
   1313     begin();
   1314     return VK_SUCCESS;
   1315 }
   1316 
   1317 VkResult VkCommandBufferObj::EndCommandBuffer() {
   1318     end();
   1319     return VK_SUCCESS;
   1320 }
   1321 
   1322 void VkCommandBufferObj::PipelineBarrier(VkPipelineStageFlags src_stages, VkPipelineStageFlags dest_stages,
   1323                                          VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount,
   1324                                          const VkMemoryBarrier *pMemoryBarriers, uint32_t bufferMemoryBarrierCount,
   1325                                          const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount,
   1326                                          const VkImageMemoryBarrier *pImageMemoryBarriers) {
   1327     vkCmdPipelineBarrier(handle(), src_stages, dest_stages, dependencyFlags, memoryBarrierCount, pMemoryBarriers,
   1328                          bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
   1329 }
   1330 
   1331 void VkCommandBufferObj::ClearAllBuffers(VkClearColorValue clear_color, float depth_clear_color, uint32_t stencil_clear_color,
   1332                                          VkDepthStencilObj *depthStencilObj) {
   1333     uint32_t i;
   1334     const VkFlags output_mask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
   1335                                 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
   1336     const VkFlags input_mask = 0;
   1337 
   1338     // whatever we want to do, we do it to the whole buffer
   1339     VkImageSubresourceRange srRange = {};
   1340     srRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
   1341     srRange.baseMipLevel = 0;
   1342     srRange.levelCount = VK_REMAINING_MIP_LEVELS;
   1343     srRange.baseArrayLayer = 0;
   1344     srRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
   1345 
   1346     VkImageMemoryBarrier memory_barrier = {};
   1347     memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
   1348     memory_barrier.srcAccessMask = output_mask;
   1349     memory_barrier.dstAccessMask = input_mask;
   1350     memory_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
   1351     memory_barrier.subresourceRange = srRange;
   1352     VkImageMemoryBarrier *pmemory_barrier = &memory_barrier;
   1353 
   1354     VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
   1355     VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
   1356 
   1357     for (i = 0; i < m_renderTargets.size(); i++) {
   1358         memory_barrier.image = m_renderTargets[i]->image();
   1359         memory_barrier.oldLayout = m_renderTargets[i]->layout();
   1360         vkCmdPipelineBarrier(handle(), src_stages, dest_stages, 0, 0, NULL, 0, NULL, 1, pmemory_barrier);
   1361         m_renderTargets[i]->layout(memory_barrier.newLayout);
   1362 
   1363         vkCmdClearColorImage(handle(), m_renderTargets[i]->image(), VK_IMAGE_LAYOUT_GENERAL, &clear_color, 1, &srRange);
   1364     }
   1365 
   1366     if (depthStencilObj) {
   1367         VkImageSubresourceRange dsRange = {};
   1368         dsRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
   1369         dsRange.baseMipLevel = 0;
   1370         dsRange.levelCount = VK_REMAINING_MIP_LEVELS;
   1371         dsRange.baseArrayLayer = 0;
   1372         dsRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
   1373 
   1374         // prepare the depth buffer for clear
   1375 
   1376         memory_barrier.oldLayout = memory_barrier.newLayout;
   1377         memory_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
   1378         memory_barrier.image = depthStencilObj->handle();
   1379         memory_barrier.subresourceRange = dsRange;
   1380 
   1381         vkCmdPipelineBarrier(handle(), src_stages, dest_stages, 0, 0, NULL, 0, NULL, 1, pmemory_barrier);
   1382 
   1383         VkClearDepthStencilValue clear_value = {depth_clear_color, stencil_clear_color};
   1384         vkCmdClearDepthStencilImage(handle(), depthStencilObj->handle(), VK_IMAGE_LAYOUT_GENERAL, &clear_value, 1, &dsRange);
   1385 
   1386         // prepare depth buffer for rendering
   1387         memory_barrier.image = depthStencilObj->handle();
   1388         memory_barrier.newLayout = memory_barrier.oldLayout;
   1389         memory_barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
   1390         memory_barrier.subresourceRange = dsRange;
   1391         vkCmdPipelineBarrier(handle(), src_stages, dest_stages, 0, 0, NULL, 0, NULL, 1, pmemory_barrier);
   1392     }
   1393 }
   1394 
   1395 void VkCommandBufferObj::FillBuffer(VkBuffer buffer, VkDeviceSize offset, VkDeviceSize fill_size, uint32_t data) {
   1396     vkCmdFillBuffer(handle(), buffer, offset, fill_size, data);
   1397 }
   1398 
   1399 void VkCommandBufferObj::UpdateBuffer(VkBuffer buffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void *pData) {
   1400     vkCmdUpdateBuffer(handle(), buffer, dstOffset, dataSize, pData);
   1401 }
   1402 
   1403 void VkCommandBufferObj::CopyImage(VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout,
   1404                                    uint32_t regionCount, const VkImageCopy *pRegions) {
   1405     vkCmdCopyImage(handle(), srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
   1406 }
   1407 
   1408 void VkCommandBufferObj::ResolveImage(VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
   1409                                       VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve *pRegions) {
   1410     vkCmdResolveImage(handle(), srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
   1411 }
   1412 
   1413 void VkCommandBufferObj::PrepareAttachments() {
   1414     uint32_t i;
   1415     const VkFlags output_mask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
   1416                                 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
   1417     const VkFlags input_mask = VK_ACCESS_HOST_READ_BIT | VK_ACCESS_INDIRECT_COMMAND_READ_BIT | VK_ACCESS_INDEX_READ_BIT |
   1418                                VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_UNIFORM_READ_BIT | VK_ACCESS_SHADER_READ_BIT |
   1419                                VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
   1420                                VK_ACCESS_MEMORY_READ_BIT;
   1421 
   1422     VkImageSubresourceRange srRange = {};
   1423     srRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
   1424     srRange.baseMipLevel = 0;
   1425     srRange.levelCount = VK_REMAINING_MIP_LEVELS;
   1426     srRange.baseArrayLayer = 0;
   1427     srRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
   1428 
   1429     VkImageMemoryBarrier memory_barrier = {};
   1430     memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
   1431     memory_barrier.srcAccessMask = output_mask;
   1432     memory_barrier.dstAccessMask = input_mask;
   1433     memory_barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
   1434     memory_barrier.subresourceRange = srRange;
   1435     VkImageMemoryBarrier *pmemory_barrier = &memory_barrier;
   1436 
   1437     VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
   1438     VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
   1439 
   1440     for (i = 0; i < m_renderTargets.size(); i++) {
   1441         memory_barrier.image = m_renderTargets[i]->image();
   1442         memory_barrier.oldLayout = m_renderTargets[i]->layout();
   1443         vkCmdPipelineBarrier(handle(), src_stages, dest_stages, 0, 0, NULL, 0, NULL, 1, pmemory_barrier);
   1444         m_renderTargets[i]->layout(memory_barrier.newLayout);
   1445     }
   1446 }
   1447 
   1448 void VkCommandBufferObj::BeginRenderPass(const VkRenderPassBeginInfo &info) {
   1449     vkCmdBeginRenderPass(handle(), &info, VK_SUBPASS_CONTENTS_INLINE);
   1450 }
   1451 
   1452 void VkCommandBufferObj::EndRenderPass() { vkCmdEndRenderPass(handle()); }
   1453 
   1454 void VkCommandBufferObj::SetViewport(uint32_t firstViewport, uint32_t viewportCount, const VkViewport *pViewports) {
   1455     vkCmdSetViewport(handle(), firstViewport, viewportCount, pViewports);
   1456 }
   1457 
   1458 void VkCommandBufferObj::SetScissor(uint32_t firstScissor, uint32_t scissorCount, const VkRect2D *pScissors) {
   1459     vkCmdSetScissor(handle(), firstScissor, scissorCount, pScissors);
   1460 }
   1461 
   1462 void VkCommandBufferObj::SetLineWidth(float lineWidth) { vkCmdSetLineWidth(handle(), lineWidth); }
   1463 
   1464 void VkCommandBufferObj::SetDepthBias(float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor) {
   1465     vkCmdSetDepthBias(handle(), depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor);
   1466 }
   1467 
   1468 void VkCommandBufferObj::SetBlendConstants(const float blendConstants[4]) { vkCmdSetBlendConstants(handle(), blendConstants); }
   1469 
   1470 void VkCommandBufferObj::SetDepthBounds(float minDepthBounds, float maxDepthBounds) {
   1471     vkCmdSetDepthBounds(handle(), minDepthBounds, maxDepthBounds);
   1472 }
   1473 
   1474 void VkCommandBufferObj::SetStencilReadMask(VkStencilFaceFlags faceMask, uint32_t compareMask) {
   1475     vkCmdSetStencilCompareMask(handle(), faceMask, compareMask);
   1476 }
   1477 
   1478 void VkCommandBufferObj::SetStencilWriteMask(VkStencilFaceFlags faceMask, uint32_t writeMask) {
   1479     vkCmdSetStencilWriteMask(handle(), faceMask, writeMask);
   1480 }
   1481 
   1482 void VkCommandBufferObj::SetStencilReference(VkStencilFaceFlags faceMask, uint32_t reference) {
   1483     vkCmdSetStencilReference(handle(), faceMask, reference);
   1484 }
   1485 
   1486 void VkCommandBufferObj::AddRenderTarget(VkImageObj *renderTarget) { m_renderTargets.push_back(renderTarget); }
   1487 
   1488 void VkCommandBufferObj::DrawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset,
   1489                                      uint32_t firstInstance) {
   1490     vkCmdDrawIndexed(handle(), indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
   1491 }
   1492 
   1493 void VkCommandBufferObj::Draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) {
   1494     vkCmdDraw(handle(), vertexCount, instanceCount, firstVertex, firstInstance);
   1495 }
   1496 
   1497 void VkCommandBufferObj::QueueCommandBuffer(bool checkSuccess) {
   1498     VkFence nullFence = {VK_NULL_HANDLE};
   1499     QueueCommandBuffer(nullFence, checkSuccess);
   1500 }
   1501 
   1502 void VkCommandBufferObj::QueueCommandBuffer(VkFence fence, bool checkSuccess) {
   1503     VkResult err = VK_SUCCESS;
   1504 
   1505     // submit the command buffer to the universal queue
   1506     VkSubmitInfo submit_info;
   1507     submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
   1508     submit_info.pNext = NULL;
   1509     submit_info.waitSemaphoreCount = 0;
   1510     submit_info.pWaitSemaphores = NULL;
   1511     submit_info.pWaitDstStageMask = NULL;
   1512     submit_info.commandBufferCount = 1;
   1513     submit_info.pCommandBuffers = &handle();
   1514     submit_info.signalSemaphoreCount = 0;
   1515     submit_info.pSignalSemaphores = NULL;
   1516 
   1517     err = vkQueueSubmit(m_device->m_queue, 1, &submit_info, fence);
   1518     if (checkSuccess) {
   1519         ASSERT_VK_SUCCESS(err);
   1520     }
   1521 
   1522     err = vkQueueWaitIdle(m_device->m_queue);
   1523     if (checkSuccess) {
   1524         ASSERT_VK_SUCCESS(err);
   1525     }
   1526 
   1527     // Wait for work to finish before cleaning up.
   1528     vkDeviceWaitIdle(m_device->device());
   1529 }
   1530 
   1531 void VkCommandBufferObj::BindPipeline(VkPipelineObj &pipeline) {
   1532     vkCmdBindPipeline(handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.handle());
   1533 }
   1534 
   1535 void VkCommandBufferObj::BindDescriptorSet(VkDescriptorSetObj &descriptorSet) {
   1536     VkDescriptorSet set_obj = descriptorSet.GetDescriptorSetHandle();
   1537 
   1538     // bind pipeline, vertex buffer (descriptor set) and WVP (dynamic buffer
   1539     // view)
   1540     vkCmdBindDescriptorSets(handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, descriptorSet.GetPipelineLayout(), 0, 1, &set_obj, 0, NULL);
   1541 }
   1542 
   1543 void VkCommandBufferObj::BindIndexBuffer(VkIndexBufferObj *indexBuffer, VkDeviceSize offset) {
   1544     vkCmdBindIndexBuffer(handle(), indexBuffer->handle(), offset, indexBuffer->GetIndexType());
   1545 }
   1546 
   1547 void VkCommandBufferObj::BindVertexBuffer(VkConstantBufferObj *vertexBuffer, VkDeviceSize offset, uint32_t binding) {
   1548     vkCmdBindVertexBuffers(handle(), binding, 1, &vertexBuffer->handle(), &offset);
   1549 }
   1550 
   1551 bool VkDepthStencilObj::Initialized() { return m_initialized; }
   1552 VkDepthStencilObj::VkDepthStencilObj(VkDeviceObj *device) : VkImageObj(device) { m_initialized = false; }
   1553 
   1554 VkImageView *VkDepthStencilObj::BindInfo() { return &m_attachmentBindInfo; }
   1555 
   1556 void VkDepthStencilObj::Init(VkDeviceObj *device, int32_t width, int32_t height, VkFormat format, VkImageUsageFlags usage) {
   1557 
   1558     VkImageViewCreateInfo view_info = {};
   1559 
   1560     m_device = device;
   1561     m_initialized = true;
   1562     m_depth_stencil_fmt = format;
   1563 
   1564     /* create image */
   1565     init(width, height, m_depth_stencil_fmt, usage, VK_IMAGE_TILING_OPTIMAL);
   1566 
   1567     VkImageAspectFlags aspect = VK_IMAGE_ASPECT_DEPTH_BIT;
   1568     if (vk_format_is_depth_and_stencil(format))
   1569         aspect |= VK_IMAGE_ASPECT_STENCIL_BIT;
   1570 
   1571     SetLayout(aspect, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
   1572 
   1573     view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
   1574     view_info.pNext = NULL;
   1575     view_info.image = VK_NULL_HANDLE;
   1576     view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
   1577     view_info.subresourceRange.baseMipLevel = 0;
   1578     view_info.subresourceRange.levelCount = 1;
   1579     view_info.subresourceRange.baseArrayLayer = 0;
   1580     view_info.subresourceRange.layerCount = 1;
   1581     view_info.flags = 0;
   1582     view_info.format = m_depth_stencil_fmt;
   1583     view_info.image = handle();
   1584     view_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
   1585     m_imageView.init(*m_device, view_info);
   1586 
   1587     m_attachmentBindInfo = m_imageView.handle();
   1588 }
   1589