tests: Add VkCommandPoolObj wrapper class

Add object to wrap VkCommandPool handle in testing framework.  Tests can
now create a custom command pool that works with the VkCommandBufferObj
wrapper.  Add utility function to VkDeviceObj that finds a queue family which
doesn't support a given capability.

Change-Id: I2f005249cc8650acf632f83ae5171de1b4509c8c
diff --git a/tests/layer_validation_tests.cpp b/tests/layer_validation_tests.cpp
index 40f3507..db824dd 100644
--- a/tests/layer_validation_tests.cpp
+++ b/tests/layer_validation_tests.cpp
@@ -7338,7 +7338,7 @@
     VkCommandBufferAllocateInfo cmd = {};
     cmd.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
     cmd.pNext = NULL;
-    cmd.commandPool = m_commandPool;
+    cmd.commandPool = m_commandPool->handle();
     cmd.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;
     cmd.commandBufferCount = 1;
 
@@ -7359,7 +7359,7 @@
     vkBeginCommandBuffer(draw_cmd, &cmd_buf_info);
 
     m_errorMonitor->VerifyFound();
-    vkFreeCommandBuffers(m_device->device(), m_commandPool, 1, &draw_cmd);
+    vkFreeCommandBuffers(m_device->device(), m_commandPool->handle(), 1, &draw_cmd);
 }
 
 TEST_F(VkLayerTest, CommandBufferResetErrors) {
@@ -9216,13 +9216,7 @@
 
     // Create command pool with incompatible queueflags
     const std::vector<VkQueueFamilyProperties> queue_props = m_device->queue_props;
-    uint32_t queue_family_index = UINT32_MAX;
-    for (uint32_t i = 0; i < queue_props.size(); i++) {
-        if ((queue_props[i].queueFlags & VK_QUEUE_COMPUTE_BIT) == 0) {
-            queue_family_index = i;
-            break;
-        }
-    }
+    uint32_t queue_family_index = m_device->QueueFamilyWithoutCapabilities(VK_QUEUE_COMPUTE_BIT);
     if (queue_family_index == UINT32_MAX) {
         printf("             No non-compute queue found; skipped.\n");
         return;  // NOTE: this exits the test function!
@@ -12136,7 +12130,7 @@
 
     VkCommandBufferAllocateInfo command_buffer_allocate_info = {};
     command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
-    command_buffer_allocate_info.commandPool = m_commandPool;
+    command_buffer_allocate_info.commandPool = m_commandPool->handle();
     command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;
     command_buffer_allocate_info.commandBufferCount = 1;
 
@@ -12206,7 +12200,7 @@
     alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
     alloc_info.pNext = NULL;
     alloc_info.commandBufferCount = 2;
-    alloc_info.commandPool = m_commandPool;
+    alloc_info.commandPool = m_commandPool->handle();
     alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
     vkAllocateCommandBuffers(m_device->device(), &alloc_info, cmd_bufs);
 
@@ -13161,7 +13155,7 @@
 
     VkCommandBufferAllocateInfo cbai = {};
     cbai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
-    cbai.commandPool = m_commandPool;
+    cbai.commandPool = m_commandPool->handle();
     cbai.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;
     cbai.commandBufferCount = 1;
 
@@ -18303,7 +18297,7 @@
 
     VkCommandBufferAllocateInfo command_buffer_allocate_info = {};
     command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
-    command_buffer_allocate_info.commandPool = m_commandPool;
+    command_buffer_allocate_info.commandPool = m_commandPool->handle();
     command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;
     command_buffer_allocate_info.commandBufferCount = 1;
 
@@ -18347,7 +18341,7 @@
     // Allocate a secondary and primary cmd buffer
     VkCommandBufferAllocateInfo command_buffer_allocate_info = {};
     command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
-    command_buffer_allocate_info.commandPool = m_commandPool;
+    command_buffer_allocate_info.commandPool = m_commandPool->handle();
     command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;
     command_buffer_allocate_info.commandBufferCount = 1;
 
@@ -18419,8 +18413,8 @@
     m_errorMonitor->VerifyNotFound();
     err = vkDeviceWaitIdle(m_device->device());
     ASSERT_VK_SUCCESS(err);
-    vkFreeCommandBuffers(m_device->device(), m_commandPool, 1, &secondary_command_buffer);
-    vkFreeCommandBuffers(m_device->device(), m_commandPool, 1, &primary_command_buffer);
+    vkFreeCommandBuffers(m_device->device(), m_commandPool->handle(), 1, &secondary_command_buffer);
+    vkFreeCommandBuffers(m_device->device(), m_commandPool->handle(), 1, &primary_command_buffer);
 }
 
 // This is a positive test. No failures are expected.
@@ -19250,7 +19244,7 @@
     alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
     alloc_info.pNext = NULL;
     alloc_info.commandBufferCount = 4;
-    alloc_info.commandPool = m_commandPool;
+    alloc_info.commandPool = m_commandPool->handle();
     alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
     vkAllocateCommandBuffers(m_device->device(), &alloc_info, cmd_bufs);
     VkImageObj image(m_device);
@@ -22777,7 +22771,7 @@
     alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
     alloc_info.pNext = NULL;
     alloc_info.commandBufferCount = 1;
-    alloc_info.commandPool = m_commandPool;
+    alloc_info.commandPool = m_commandPool->handle();
     alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
     vkAllocateCommandBuffers(m_device->device(), &alloc_info, &cmd_buf);
 
diff --git a/tests/vkrenderframework.cpp b/tests/vkrenderframework.cpp
index a4f3c3c..161216b 100644
--- a/tests/vkrenderframework.cpp
+++ b/tests/vkrenderframework.cpp
@@ -184,7 +184,7 @@
 
 void VkRenderFramework::ShutdownFramework() {
     delete m_commandBuffer;
-    if (m_commandPool) vkDestroyCommandPool(device(), m_commandPool, NULL);
+    delete m_commandPool;
     if (m_framebuffer) vkDestroyFramebuffer(device(), m_framebuffer, NULL);
     if (m_renderPass) vkDestroyRenderPass(device(), m_renderPass, NULL);
 
@@ -216,8 +216,6 @@
 }
 
 void VkRenderFramework::InitState(VkPhysicalDeviceFeatures *features, const VkCommandPoolCreateFlags flags) {
-    VkResult U_ASSERT_ONLY err;
-
     m_device = new VkDeviceObj(0, objs[0], device_extension_names, features);
     m_device->get_device_queue();
 
@@ -243,12 +241,7 @@
     m_writeMask = 0xff;
     m_reference = 0;
 
-    VkCommandPoolCreateInfo cmd_pool_info;
-    cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, cmd_pool_info.pNext = NULL,
-    cmd_pool_info.queueFamilyIndex = m_device->graphics_queue_node_index_;
-    cmd_pool_info.flags = flags;
-    err = vkCreateCommandPool(device(), &cmd_pool_info, NULL, &m_commandPool);
-    assert(!err);
+    m_commandPool = new VkCommandPoolObj(m_device, m_device->graphics_queue_node_index_, flags);
 
     m_commandBuffer = new VkCommandBufferObj(m_device, m_commandPool);
 }
@@ -421,11 +414,24 @@
     queue_props = phy().queue_properties();
 }
 
+uint32_t VkDeviceObj::QueueFamilyWithoutCapabilities(VkQueueFlags capabilities)
+{
+    // Find a queue family without desired capabilities
+    for (uint32_t i = 0; i < queue_props.size(); i++) {
+        if ((queue_props[i].queueFlags & capabilities) == 0) {
+            return i;
+        }
+    }
+    return UINT32_MAX;
+}
+
+
 void VkDeviceObj::get_device_queue() {
     ASSERT_NE(true, graphics_queues().empty());
     m_queue = graphics_queues()[0]->handle();
 }
 
+
 VkDescriptorSetObj::VkDescriptorSetObj(VkDeviceObj *device) : m_device(device), m_nextSlot(0) {}
 
 VkDescriptorSetObj::~VkDescriptorSetObj() {
@@ -681,13 +687,8 @@
         return;
     }
 
-    VkCommandPoolCreateInfo cmd_pool_info = {};
-    cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
-    cmd_pool_info.pNext = NULL;
-    cmd_pool_info.queueFamilyIndex = m_device->graphics_queue_node_index_;
-    cmd_pool_info.flags = 0;
-    vk_testing::CommandPool pool(*m_device, cmd_pool_info);
-    VkCommandBufferObj cmd_buf(m_device, pool.handle());
+    VkCommandPoolObj pool(m_device, m_device->graphics_queue_node_index_);
+    VkCommandBufferObj cmd_buf(m_device, &pool);
 
     /* Build command buffer to set image layout in the driver */
     err = cmd_buf.BeginCommandBuffer();
@@ -809,13 +810,8 @@
     VkResult U_ASSERT_ONLY err;
     VkImageLayout src_image_layout, dest_image_layout;
 
-    VkCommandPoolCreateInfo cmd_pool_info = {};
-    cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
-    cmd_pool_info.pNext = NULL;
-    cmd_pool_info.queueFamilyIndex = m_device->graphics_queue_node_index_;
-    cmd_pool_info.flags = 0;
-    vk_testing::CommandPool pool(*m_device, cmd_pool_info);
-    VkCommandBufferObj cmd_buf(m_device, pool.handle());
+    VkCommandPoolObj pool(m_device, m_device->graphics_queue_node_index_);
+    VkCommandBufferObj cmd_buf(m_device, &pool);
 
     /* Build command buffer to copy staging texture to usable texture */
     err = cmd_buf.BeginCommandBuffer();
@@ -1016,13 +1012,8 @@
 
     if (!m_commandBuffer) {
         m_fence.init(*m_device, vk_testing::Fence::create_info());
-        VkCommandPoolCreateInfo cmd_pool_info = {};
-        cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
-        cmd_pool_info.pNext = NULL;
-        cmd_pool_info.queueFamilyIndex = m_device->graphics_queue_node_index_;
-        cmd_pool_info.flags = 0;
-        m_commandPool = new vk_testing::CommandPool(*m_device, cmd_pool_info);
-        m_commandBuffer = new VkCommandBufferObj(m_device, m_commandPool->handle());
+        m_commandPool = new VkCommandPoolObj(m_device, m_device->graphics_queue_node_index_);
+        m_commandBuffer = new VkCommandBufferObj(m_device, m_commandPool);
     } else {
         m_device->wait(m_fence);
     }
@@ -1358,10 +1349,10 @@
     return init_try(*m_device, *gp_ci);
 }
 
-VkCommandBufferObj::VkCommandBufferObj(VkDeviceObj *device, VkCommandPool pool) {
+VkCommandBufferObj::VkCommandBufferObj(VkDeviceObj *device, VkCommandPoolObj *pool) {
     m_device = device;
 
-    init(*device, vk_testing::CommandBuffer::create_info(pool));
+    init(*device, vk_testing::CommandBuffer::create_info(pool->handle()));
 }
 
 VkCommandBuffer VkCommandBufferObj::GetBufferHandle() { return handle(); }
@@ -1620,6 +1611,10 @@
     vkCmdBindVertexBuffers(handle(), binding, 1, &vertexBuffer->handle(), &offset);
 }
 
+VkCommandPoolObj::VkCommandPoolObj(VkDeviceObj *device, uint32_t queue_family_index, VkCommandPoolCreateFlags flags) {
+    init(*device, vk_testing::CommandPool::create_info(queue_family_index, flags));
+}
+
 bool VkDepthStencilObj::Initialized() { return m_initialized; }
 VkDepthStencilObj::VkDepthStencilObj(VkDeviceObj *device) : VkImageObj(device) { m_initialized = false; }
 
diff --git a/tests/vkrenderframework.h b/tests/vkrenderframework.h
index b36d254..a693038 100644
--- a/tests/vkrenderframework.h
+++ b/tests/vkrenderframework.h
@@ -40,6 +40,8 @@
     VkDeviceObj(uint32_t id, VkPhysicalDevice obj, std::vector<const char *> &extension_names,
                 VkPhysicalDeviceFeatures *features = nullptr);
 
+    uint32_t QueueFamilyWithoutCapabilities(VkQueueFlags capabilities);
+
     VkDevice device() { return handle(); }
     void get_device_queue();
 
@@ -50,6 +52,7 @@
     VkQueue m_queue;
 };
 
+class VkCommandPoolObj;
 class VkCommandBufferObj;
 class VkDepthStencilObj;
 
@@ -86,7 +89,7 @@
     VkPhysicalDevice objs[16];
     uint32_t gpu_count;
     VkDeviceObj *m_device;
-    VkCommandPool m_commandPool;
+    VkCommandPoolObj *m_commandPool;
     VkCommandBufferObj *m_commandBuffer;
     VkRenderPass m_renderPass;
     VkFramebuffer m_framebuffer;
@@ -145,9 +148,14 @@
 class VkPipelineObj;
 class VkDescriptorSetObj;
 
+class VkCommandPoolObj : public vk_testing::CommandPool {
+   public:
+    VkCommandPoolObj(VkDeviceObj *device, uint32_t queue_family_index, VkCommandPoolCreateFlags flags = 0);
+};
+
 class VkCommandBufferObj : public vk_testing::CommandBuffer {
    public:
-    VkCommandBufferObj(VkDeviceObj *device, VkCommandPool pool);
+    VkCommandBufferObj(VkDeviceObj *device, VkCommandPoolObj *pool);
     VkCommandBuffer GetBufferHandle();
     VkResult BeginCommandBuffer();
     VkResult BeginCommandBuffer(VkCommandBufferBeginInfo *pInfo);
@@ -222,7 +230,7 @@
     vk_testing::BufferView m_bufferView;
     int m_numVertices;
     int m_stride;
-    vk_testing::CommandPool *m_commandPool;
+    VkCommandPoolObj *m_commandPool;
     VkCommandBufferObj *m_commandBuffer;
     vk_testing::Fence m_fence;
 };
diff --git a/tests/vktestbinding.h b/tests/vktestbinding.h
index 1324620..29db1fa 100644
--- a/tests/vktestbinding.h
+++ b/tests/vktestbinding.h
@@ -161,6 +161,7 @@
     const std::vector<Queue *> &graphics_queues() const { return queues_[GRAPHICS]; }
     const std::vector<Queue *> &compute_queues() { return queues_[COMPUTE]; }
     const std::vector<Queue *> &dma_queues() { return queues_[DMA]; }
+    uint32_t queue_family_without_capabilities( VkQueueFlags capabilities );
     uint32_t graphics_queue_node_index_;
 
     struct Format {
@@ -568,14 +569,14 @@
 
     void init(const Device &dev, const VkCommandPoolCreateInfo &info);
 
-    static VkCommandPoolCreateInfo create_info(uint32_t queue_family_index);
+    static VkCommandPoolCreateInfo create_info(uint32_t queue_family_index, VkCommandPoolCreateFlags flags);
 };
 
-inline VkCommandPoolCreateInfo CommandPool::create_info(uint32_t queue_family_index) {
+inline VkCommandPoolCreateInfo CommandPool::create_info(uint32_t queue_family_index, VkCommandPoolCreateFlags flags) {
     VkCommandPoolCreateInfo info = {};
     info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
     info.queueFamilyIndex = queue_family_index;
-    info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
+    info.flags = flags;
     return info;
 }