Home | History | Annotate | Download | only in layers
      1 /* Copyright (c) 2015-2016 The Khronos Group Inc.
      2  * Copyright (c) 2015-2016 Valve Corporation
      3  * Copyright (c) 2015-2016 LunarG, Inc.
      4  * Copyright (C) 2015-2016 Google 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
     11  * are furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice(s) and this permission notice shall be included
     14  * in 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 <courtneygo (at) google.com>
     26  * Author: Tobin Ehlis <tobine (at) google.com>
     27  * Author: Chris Forbes <chrisf (at) ijw.co.nz>
     28  * Author: Mark Lobodzinski <mark (at) lunarg.com>
     29  */
     30 
     31 // Enable mem_tracker merged code
     32 #define MTMERGE 1
     33 
     34 #pragma once
     35 #include "vulkan/vk_layer.h"
     36 #include <atomic>
     37 #include <vector>
     38 #include <unordered_map>
     39 #include <memory>
     40 #include <functional>
     41 
     42 using std::vector;
     43 
     44 //#ifdef __cplusplus
     45 //extern "C" {
     46 //#endif
     47 
     48 #if MTMERGE
     49 // Mem Tracker ERROR codes
     50 typedef enum _MEM_TRACK_ERROR {
     51     MEMTRACK_NONE,                         // Used for INFO & other non-error messages
     52     MEMTRACK_INVALID_CB,                   // Cmd Buffer invalid
     53     MEMTRACK_INVALID_MEM_OBJ,              // Invalid Memory Object
     54     MEMTRACK_INVALID_ALIASING,             // Invalid Memory Aliasing
     55     MEMTRACK_INVALID_LAYOUT,               // Invalid Layout
     56     MEMTRACK_INTERNAL_ERROR,               // Bug in Mem Track Layer internal data structures
     57     MEMTRACK_FREED_MEM_REF,                // MEM Obj freed while it still has obj and/or CB refs
     58     MEMTRACK_MEM_OBJ_CLEAR_EMPTY_BINDINGS, // Clearing bindings on mem obj that doesn't have any bindings
     59     MEMTRACK_MISSING_MEM_BINDINGS,         // Trying to retrieve mem bindings, but none found (may be internal error)
     60     MEMTRACK_INVALID_OBJECT,               // Attempting to reference generic VK Object that is invalid
     61     MEMTRACK_MEMORY_BINDING_ERROR,         // Error during one of many calls that bind memory to object or CB
     62     MEMTRACK_MEMORY_LEAK,                  // Failure to call vkFreeMemory on Mem Obj prior to DestroyDevice
     63     MEMTRACK_INVALID_STATE,                // Memory not in the correct state
     64     MEMTRACK_RESET_CB_WHILE_IN_FLIGHT,     // vkResetCommandBuffer() called on a CB that hasn't completed
     65     MEMTRACK_INVALID_FENCE_STATE,          // Invalid Fence State signaled or used
     66     MEMTRACK_REBIND_OBJECT,                // Non-sparse object bindings are immutable
     67     MEMTRACK_INVALID_USAGE_FLAG,           // Usage flags specified at image/buffer create conflict w/ use of object
     68     MEMTRACK_INVALID_MAP,                  // Size flag specified at alloc is too small for mapping range
     69 } MEM_TRACK_ERROR;
     70 
     71 // MemTracker Semaphore states
     72 typedef enum SemaphoreState {
     73     MEMTRACK_SEMAPHORE_STATE_UNSET,     // Semaphore is in an undefined state
     74     MEMTRACK_SEMAPHORE_STATE_SIGNALLED, // Semaphore has is in signalled state
     75     MEMTRACK_SEMAPHORE_STATE_WAIT,      // Semaphore is in wait state
     76 } SemaphoreState;
     77 
     78 struct MemRange {
     79     VkDeviceSize offset;
     80     VkDeviceSize size;
     81 };
     82 
     83 /*
     84  * MTMTODO : Update this comment
     85  * Data Structure overview
     86  *  There are 4 global STL(' maps
     87  *  cbMap -- map of command Buffer (CB) objects to MT_CB_INFO structures
     88  *    Each MT_CB_INFO struct has an stl list container with
     89  *    memory objects that are referenced by this CB
     90  *  memObjMap -- map of Memory Objects to MT_MEM_OBJ_INFO structures
     91  *    Each MT_MEM_OBJ_INFO has two stl list containers with:
     92  *      -- all CBs referencing this mem obj
     93  *      -- all VK Objects that are bound to this memory
     94  *  objectMap -- map of objects to MT_OBJ_INFO structures
     95  *
     96  * Algorithm overview
     97  * These are the primary events that should happen related to different objects
     98  * 1. Command buffers
     99  *   CREATION - Add object,structure to map
    100  *   CMD BIND - If mem associated, add mem reference to list container
    101  *   DESTROY  - Remove from map, decrement (and report) mem references
    102  * 2. Mem Objects
    103  *   CREATION - Add object,structure to map
    104  *   OBJ BIND - Add obj structure to list container for that mem node
    105  *   CMB BIND - If mem-related add CB structure to list container for that mem node
    106  *   DESTROY  - Flag as errors any remaining refs and remove from map
    107  * 3. Generic Objects
    108  *   MEM BIND - DESTROY any previous binding, Add obj node w/ ref to map, add obj ref to list container for that mem node
    109  *   DESTROY - If mem bound, remove reference list container for that memInfo, remove object ref from map
    110  */
    111 // TODO : Is there a way to track when Cmd Buffer finishes & remove mem references at that point?
    112 // TODO : Could potentially store a list of freed mem allocs to flag when they're incorrectly used
    113 
    114 // Simple struct to hold handle and type of object so they can be uniquely identified and looked up in appropriate map
    115 struct MT_OBJ_HANDLE_TYPE {
    116     uint64_t handle;
    117     VkDebugReportObjectTypeEXT type;
    118 };
    119 
    120 struct MEMORY_RANGE {
    121     uint64_t handle;
    122     VkDeviceMemory memory;
    123     VkDeviceSize start;
    124     VkDeviceSize end;
    125 };
    126 
    127 // Data struct for tracking memory object
    128 struct DEVICE_MEM_INFO {
    129     void *object;      // Dispatchable object used to create this memory (device of swapchain)
    130     uint32_t refCount; // Count of references (obj bindings or CB use)
    131     bool valid;        // Stores if the memory has valid data or not
    132     VkDeviceMemory mem;
    133     VkMemoryAllocateInfo allocInfo;
    134     list<MT_OBJ_HANDLE_TYPE> pObjBindings;        // list container of objects bound to this memory
    135     list<VkCommandBuffer> pCommandBufferBindings; // list container of cmd buffers that reference this mem object
    136     vector<MEMORY_RANGE> bufferRanges;
    137     vector<MEMORY_RANGE> imageRanges;
    138     VkImage image; // If memory is bound to image, this will have VkImage handle, else VK_NULL_HANDLE
    139     MemRange memRange;
    140     void *pData, *pDriverData;
    141 };
    142 
    143 // This only applies to Buffers and Images, which can have memory bound to them
    144 struct MT_OBJ_BINDING_INFO {
    145     VkDeviceMemory mem;
    146     bool valid; // If this is a swapchain image backing memory is not a MT_MEM_OBJ_INFO so store it here.
    147     union create_info {
    148         VkImageCreateInfo image;
    149         VkBufferCreateInfo buffer;
    150     } create_info;
    151 };
    152 
    153 struct MT_FB_ATTACHMENT_INFO {
    154     VkImage image;
    155     VkDeviceMemory mem;
    156 };
    157 
    158 struct MT_PASS_ATTACHMENT_INFO {
    159     uint32_t attachment;
    160     VkAttachmentLoadOp load_op;
    161     VkAttachmentStoreOp store_op;
    162 };
    163 
    164 // Associate fenceId with a fence object
    165 struct MT_FENCE_INFO {
    166     uint64_t fenceId;         // Sequence number for fence at last submit
    167     VkQueue queue;            // Queue that this fence is submitted against or NULL
    168     VkSwapchainKHR swapchain; // Swapchain that this fence is submitted against or NULL
    169     VkBool32 firstTimeFlag;   // Fence was created in signaled state, avoid warnings for first use
    170     VkFenceCreateInfo createInfo;
    171 };
    172 
    173 // Track Queue information
    174 struct MT_QUEUE_INFO {
    175     uint64_t lastRetiredId;
    176     uint64_t lastSubmittedId;
    177     list<VkCommandBuffer> pQueueCommandBuffers;
    178     list<VkDeviceMemory> pMemRefList;
    179 };
    180 
    181 struct MT_DESCRIPTOR_SET_INFO {
    182     std::vector<VkImageView> images;
    183     std::vector<VkBuffer> buffers;
    184 };
    185 
    186 // Track Swapchain Information
    187 struct MT_SWAP_CHAIN_INFO {
    188     VkSwapchainCreateInfoKHR createInfo;
    189     std::vector<VkImage> images;
    190 };
    191 
    192 #endif
    193 // Draw State ERROR codes
    194 typedef enum _DRAW_STATE_ERROR {
    195     DRAWSTATE_NONE,                          // Used for INFO & other non-error messages
    196     DRAWSTATE_INTERNAL_ERROR,                // Error with DrawState internal data structures
    197     DRAWSTATE_NO_PIPELINE_BOUND,             // Unable to identify a bound pipeline
    198     DRAWSTATE_INVALID_POOL,                  // Invalid DS pool
    199     DRAWSTATE_INVALID_SET,                   // Invalid DS
    200     DRAWSTATE_INVALID_LAYOUT,                // Invalid DS layout
    201     DRAWSTATE_INVALID_IMAGE_LAYOUT,          // Invalid Image layout
    202     DRAWSTATE_INVALID_PIPELINE,              // Invalid Pipeline handle referenced
    203     DRAWSTATE_INVALID_PIPELINE_LAYOUT,       // Invalid PipelineLayout
    204     DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, // Attempt to create a pipeline
    205                                              // with invalid state
    206     DRAWSTATE_INVALID_COMMAND_BUFFER,        // Invalid CommandBuffer referenced
    207     DRAWSTATE_INVALID_BARRIER,               // Invalid Barrier
    208     DRAWSTATE_INVALID_BUFFER,                // Invalid Buffer
    209     DRAWSTATE_INVALID_QUERY,                 // Invalid Query
    210     DRAWSTATE_INVALID_FENCE,                 // Invalid Fence
    211     DRAWSTATE_INVALID_SEMAPHORE,             // Invalid Semaphore
    212     DRAWSTATE_INVALID_EVENT,                 // Invalid Event
    213     DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS,       // binding in vkCmdBindVertexData() too
    214                                              // large for PSO's
    215                                              // pVertexBindingDescriptions array
    216     DRAWSTATE_VTX_INDEX_ALIGNMENT_ERROR,     // binding offset in
    217                                              // vkCmdBindIndexBuffer() out of
    218                                              // alignment based on indexType
    219     // DRAWSTATE_MISSING_DOT_PROGRAM,              // No "dot" program in order
    220     // to generate png image
    221     DRAWSTATE_OUT_OF_MEMORY,                          // malloc failed
    222     DRAWSTATE_INVALID_DESCRIPTOR_SET,                 // Descriptor Set handle is unknown
    223     DRAWSTATE_DESCRIPTOR_TYPE_MISMATCH,               // Type in layout vs. update are not the
    224                                                       // same
    225     DRAWSTATE_DESCRIPTOR_STAGEFLAGS_MISMATCH,         // StageFlags in layout are not
    226                                                       // the same throughout a single
    227                                                       // VkWriteDescriptorSet update
    228     DRAWSTATE_DESCRIPTOR_UPDATE_OUT_OF_BOUNDS,        // Descriptors set for update out
    229                                                       // of bounds for corresponding
    230                                                       // layout section
    231     DRAWSTATE_DESCRIPTOR_POOL_EMPTY,                  // Attempt to allocate descriptor from a
    232                                                       // pool with no more descriptors of that
    233                                                       // type available
    234     DRAWSTATE_CANT_FREE_FROM_NON_FREE_POOL,           // Invalid to call
    235                                                       // vkFreeDescriptorSets on Sets
    236                                                       // allocated from a NON_FREE Pool
    237     DRAWSTATE_INVALID_UPDATE_INDEX,                   // Index of requested update is invalid for
    238                                                       // specified descriptors set
    239     DRAWSTATE_INVALID_UPDATE_STRUCT,                  // Struct in DS Update tree is of invalid
    240                                                       // type
    241     DRAWSTATE_NUM_SAMPLES_MISMATCH,                   // Number of samples in bound PSO does not
    242                                                       // match number in FB of current RenderPass
    243     DRAWSTATE_NO_END_COMMAND_BUFFER,                  // Must call vkEndCommandBuffer() before
    244                                                       // QueueSubmit on that commandBuffer
    245     DRAWSTATE_NO_BEGIN_COMMAND_BUFFER,                // Binding cmds or calling End on CB that
    246                                                       // never had vkBeginCommandBuffer()
    247                                                       // called on it
    248     DRAWSTATE_COMMAND_BUFFER_SINGLE_SUBMIT_VIOLATION, // Cmd Buffer created with
    249     // VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
    250     // flag is submitted
    251     // multiple times
    252     DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, // vkCmdExecuteCommands() called
    253                                                 // with a primary commandBuffer
    254                                                 // in pCommandBuffers array
    255     DRAWSTATE_VIEWPORT_NOT_BOUND,               // Draw submitted with no viewport state bound
    256     DRAWSTATE_SCISSOR_NOT_BOUND,                // Draw submitted with no scissor state bound
    257     DRAWSTATE_LINE_WIDTH_NOT_BOUND,             // Draw submitted with no line width state
    258                                                 // bound
    259     DRAWSTATE_DEPTH_BIAS_NOT_BOUND,             // Draw submitted with no depth bias state
    260                                                 // bound
    261     DRAWSTATE_BLEND_NOT_BOUND,                  // Draw submitted with no blend state bound when
    262                                                 // color write enabled
    263     DRAWSTATE_DEPTH_BOUNDS_NOT_BOUND,           // Draw submitted with no depth bounds
    264                                                 // state bound when depth enabled
    265     DRAWSTATE_STENCIL_NOT_BOUND,                // Draw submitted with no stencil state bound
    266                                                 // when stencil enabled
    267     DRAWSTATE_INDEX_BUFFER_NOT_BOUND,           // Draw submitted with no depth-stencil
    268                                                 // state bound when depth write enabled
    269     DRAWSTATE_PIPELINE_LAYOUTS_INCOMPATIBLE,    // Draw submitted PSO Pipeline
    270                                                 // layout that's not compatible
    271                                                 // with layout from
    272                                                 // BindDescriptorSets
    273     DRAWSTATE_RENDERPASS_INCOMPATIBLE,          // Incompatible renderpasses between
    274                                                 // secondary cmdBuffer and primary
    275                                                 // cmdBuffer or framebuffer
    276     DRAWSTATE_FRAMEBUFFER_INCOMPATIBLE,         // Incompatible framebuffer between
    277                                                 // secondary cmdBuffer and active
    278                                                 // renderPass
    279     DRAWSTATE_INVALID_RENDERPASS,               // Use of a NULL or otherwise invalid
    280                                                 // RenderPass object
    281     DRAWSTATE_INVALID_RENDERPASS_CMD,           // Invalid cmd submitted while a
    282                                                 // RenderPass is active
    283     DRAWSTATE_NO_ACTIVE_RENDERPASS,             // Rendering cmd submitted without an active
    284                                                 // RenderPass
    285     DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED,       // DescriptorSet bound but it was
    286                                                 // never updated. This is a warning
    287                                                 // code.
    288     DRAWSTATE_DESCRIPTOR_SET_NOT_BOUND,         // DescriptorSet used by pipeline at
    289                                                 // draw time is not bound, or has been
    290                                                 // disturbed (which would have flagged
    291                                                 // previous warning)
    292     DRAWSTATE_INVALID_DYNAMIC_OFFSET_COUNT,     // DescriptorSets bound with
    293                                                 // different number of dynamic
    294                                                 // descriptors that were included in
    295                                                 // dynamicOffsetCount
    296     DRAWSTATE_CLEAR_CMD_BEFORE_DRAW,            // Clear cmd issued before any Draw in
    297                                                 // CommandBuffer, should use RenderPass Ops
    298                                                 // instead
    299     DRAWSTATE_BEGIN_CB_INVALID_STATE,           // CB state at Begin call is bad. Can be
    300                                                 // Primary/Secondary CB created with
    301                                                 // mismatched FB/RP information or CB in
    302                                                 // RECORDING state
    303     DRAWSTATE_INVALID_CB_SIMULTANEOUS_USE,      // CmdBuffer is being used in
    304                                                 // violation of
    305     // VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT
    306     // rules (i.e. simultaneous use w/o
    307     // that bit set)
    308     DRAWSTATE_INVALID_COMMAND_BUFFER_RESET, // Attempting to call Reset (or
    309                                             // Begin on recorded cmdBuffer) that
    310                                             // was allocated from Pool w/o
    311     // VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT
    312     // bit set
    313     DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH,             // Count for viewports and scissors
    314                                                      // mismatch and/or state doesn't match
    315                                                      // count
    316     DRAWSTATE_INVALID_IMAGE_ASPECT,                  // Image aspect is invalid for the current
    317                                                      // operation
    318     DRAWSTATE_MISSING_ATTACHMENT_REFERENCE,          // Attachment reference must be
    319                                                      // present in active subpass
    320     DRAWSTATE_SAMPLER_DESCRIPTOR_ERROR,              // A Descriptor of *_SAMPLER type is
    321                                                      // being updated with an invalid or bad
    322                                                      // Sampler
    323     DRAWSTATE_INCONSISTENT_IMMUTABLE_SAMPLER_UPDATE, // Descriptors of
    324                                                      // *COMBINED_IMAGE_SAMPLER
    325                                                      // type are being updated
    326                                                      // where some, but not all,
    327                                                      // of the updates use
    328                                                      // immutable samplers
    329     DRAWSTATE_IMAGEVIEW_DESCRIPTOR_ERROR,            // A Descriptor of *_IMAGE or
    330                                                      // *_ATTACHMENT type is being updated
    331                                                      // with an invalid or bad ImageView
    332     DRAWSTATE_BUFFERVIEW_DESCRIPTOR_ERROR,           // A Descriptor of *_TEXEL_BUFFER
    333                                                      // type is being updated with an
    334                                                      // invalid or bad BufferView
    335     DRAWSTATE_BUFFERINFO_DESCRIPTOR_ERROR,           // A Descriptor of
    336     // *_[UNIFORM|STORAGE]_BUFFER_[DYNAMIC]
    337     // type is being updated with an
    338     // invalid or bad BufferView
    339     DRAWSTATE_DYNAMIC_OFFSET_OVERFLOW,       // At draw time the dynamic offset
    340                                              // combined with buffer offset and range
    341                                              // oversteps size of buffer
    342     DRAWSTATE_DOUBLE_DESTROY,                // Destroying an object twice
    343     DRAWSTATE_OBJECT_INUSE,                  // Destroying or modifying an object in use by a
    344                                              // command buffer
    345     DRAWSTATE_QUEUE_FORWARD_PROGRESS,        // Queue cannot guarantee forward progress
    346     DRAWSTATE_INVALID_UNIFORM_BUFFER_OFFSET, // Dynamic Uniform Buffer Offsets
    347                                              // violate device limit
    348     DRAWSTATE_INVALID_STORAGE_BUFFER_OFFSET, // Dynamic Storage Buffer Offsets
    349                                              // violate device limit
    350     DRAWSTATE_INDEPENDENT_BLEND,             // If independent blending is not enabled, all
    351                                              // elements of pAttachmentsMustBeIdentical
    352     DRAWSTATE_DISABLED_LOGIC_OP,             // If logic operations is not enabled, logicOpEnable
    353                                              // must be VK_FALSE
    354     DRAWSTATE_INVALID_LOGIC_OP,              // If logicOpEnable is VK_TRUE, logicOp must
    355                                              // must be a valid VkLogicOp value
    356     DRAWSTATE_INVALID_QUEUE_INDEX,           // Specified queue index exceeds number
    357                                              // of queried queue families
    358     DRAWSTATE_PUSH_CONSTANTS_ERROR,          // Push constants exceed maxPushConstantSize
    359 } DRAW_STATE_ERROR;
    360 
    361 typedef enum _SHADER_CHECKER_ERROR {
    362     SHADER_CHECKER_NONE,
    363     SHADER_CHECKER_INTERFACE_TYPE_MISMATCH,    // Type mismatch between shader stages or shader and pipeline
    364     SHADER_CHECKER_OUTPUT_NOT_CONSUMED,        // Entry appears in output interface, but missing in input
    365     SHADER_CHECKER_INPUT_NOT_PRODUCED,         // Entry appears in input interface, but missing in output
    366     SHADER_CHECKER_NON_SPIRV_SHADER,           // Shader image is not SPIR-V
    367     SHADER_CHECKER_INCONSISTENT_SPIRV,         // General inconsistency within a SPIR-V module
    368     SHADER_CHECKER_UNKNOWN_STAGE,              // Stage is not supported by analysis
    369     SHADER_CHECKER_INCONSISTENT_VI,            // VI state contains conflicting binding or attrib descriptions
    370     SHADER_CHECKER_MISSING_DESCRIPTOR,         // Shader attempts to use a descriptor binding not declared in the layout
    371     SHADER_CHECKER_BAD_SPECIALIZATION,         // Specialization map entry points outside specialization data block
    372     SHADER_CHECKER_MISSING_ENTRYPOINT,         // Shader module does not contain the requested entrypoint
    373     SHADER_CHECKER_PUSH_CONSTANT_OUT_OF_RANGE, // Push constant variable is not in a push constant range
    374     SHADER_CHECKER_PUSH_CONSTANT_NOT_ACCESSIBLE_FROM_STAGE, // Push constant range exists, but not accessible from stage
    375     SHADER_CHECKER_DESCRIPTOR_TYPE_MISMATCH,                // Descriptor type does not match shader resource type
    376     SHADER_CHECKER_DESCRIPTOR_NOT_ACCESSIBLE_FROM_STAGE,    // Descriptor used by shader, but not accessible from stage
    377     SHADER_CHECKER_FEATURE_NOT_ENABLED,        // Shader uses capability requiring a feature not enabled on device
    378     SHADER_CHECKER_BAD_CAPABILITY,             // Shader uses capability not supported by Vulkan (OpenCL features)
    379 } SHADER_CHECKER_ERROR;
    380 
    381 typedef enum _DRAW_TYPE {
    382     DRAW = 0,
    383     DRAW_INDEXED = 1,
    384     DRAW_INDIRECT = 2,
    385     DRAW_INDEXED_INDIRECT = 3,
    386     DRAW_BEGIN_RANGE = DRAW,
    387     DRAW_END_RANGE = DRAW_INDEXED_INDIRECT,
    388     NUM_DRAW_TYPES = (DRAW_END_RANGE - DRAW_BEGIN_RANGE + 1),
    389 } DRAW_TYPE;
    390 
    391 typedef struct _SHADER_DS_MAPPING {
    392     uint32_t slotCount;
    393     VkDescriptorSetLayoutCreateInfo *pShaderMappingSlot;
    394 } SHADER_DS_MAPPING;
    395 
    396 typedef struct _GENERIC_HEADER {
    397     VkStructureType sType;
    398     const void *pNext;
    399 } GENERIC_HEADER;
    400 
    401 typedef struct _PIPELINE_NODE {
    402     VkPipeline pipeline;
    403     VkGraphicsPipelineCreateInfo graphicsPipelineCI;
    404     VkPipelineVertexInputStateCreateInfo vertexInputCI;
    405     VkPipelineInputAssemblyStateCreateInfo iaStateCI;
    406     VkPipelineTessellationStateCreateInfo tessStateCI;
    407     VkPipelineViewportStateCreateInfo vpStateCI;
    408     VkPipelineRasterizationStateCreateInfo rsStateCI;
    409     VkPipelineMultisampleStateCreateInfo msStateCI;
    410     VkPipelineColorBlendStateCreateInfo cbStateCI;
    411     VkPipelineDepthStencilStateCreateInfo dsStateCI;
    412     VkPipelineDynamicStateCreateInfo dynStateCI;
    413     VkPipelineShaderStageCreateInfo vsCI;
    414     VkPipelineShaderStageCreateInfo tcsCI;
    415     VkPipelineShaderStageCreateInfo tesCI;
    416     VkPipelineShaderStageCreateInfo gsCI;
    417     VkPipelineShaderStageCreateInfo fsCI;
    418     // Compute shader is include in VkComputePipelineCreateInfo
    419     VkComputePipelineCreateInfo computePipelineCI;
    420     // Flag of which shader stages are active for this pipeline
    421     uint32_t active_shaders;
    422     // Capture which sets are actually used by the shaders of this pipeline
    423     std::set<unsigned> active_sets;
    424     // Vtx input info (if any)
    425     std::vector<VkVertexInputBindingDescription> vertexBindingDescriptions;
    426     std::vector<VkVertexInputAttributeDescription> vertexAttributeDescriptions;
    427     std::vector<VkPipelineColorBlendAttachmentState> attachments;
    428     // Default constructor
    429     _PIPELINE_NODE()
    430         : pipeline{}, graphicsPipelineCI{}, vertexInputCI{}, iaStateCI{}, tessStateCI{}, vpStateCI{}, rsStateCI{}, msStateCI{},
    431           cbStateCI{}, dsStateCI{}, dynStateCI{}, vsCI{}, tcsCI{}, tesCI{}, gsCI{}, fsCI{}, computePipelineCI{}, active_shaders(0),
    432           active_sets(),
    433           vertexBindingDescriptions(), vertexAttributeDescriptions(), attachments()
    434           {}
    435 } PIPELINE_NODE;
    436 
    437 class BASE_NODE {
    438   public:
    439     std::atomic_int in_use;
    440 };
    441 
    442 typedef struct _SAMPLER_NODE {
    443     VkSampler sampler;
    444     VkSamplerCreateInfo createInfo;
    445 
    446     _SAMPLER_NODE(const VkSampler *ps, const VkSamplerCreateInfo *pci) : sampler(*ps), createInfo(*pci){};
    447 } SAMPLER_NODE;
    448 
    449 class IMAGE_NODE : public BASE_NODE {
    450   public:
    451     VkImageCreateInfo createInfo;
    452     VkDeviceMemory mem;
    453     VkDeviceSize memOffset;
    454     VkDeviceSize memSize;
    455 };
    456 
    457 typedef struct _IMAGE_LAYOUT_NODE {
    458     VkImageLayout layout;
    459     VkFormat format;
    460 } IMAGE_LAYOUT_NODE;
    461 
    462 typedef struct _IMAGE_CMD_BUF_LAYOUT_NODE {
    463     VkImageLayout initialLayout;
    464     VkImageLayout layout;
    465 } IMAGE_CMD_BUF_LAYOUT_NODE;
    466 
    467 class BUFFER_NODE : public BASE_NODE {
    468   public:
    469     using BASE_NODE::in_use;
    470     unique_ptr<VkBufferCreateInfo> create_info;
    471 };
    472 
    473 // Store the DAG.
    474 struct DAGNode {
    475     uint32_t pass;
    476     std::vector<uint32_t> prev;
    477     std::vector<uint32_t> next;
    478 };
    479 
    480 struct RENDER_PASS_NODE {
    481     VkRenderPassCreateInfo const *pCreateInfo;
    482     VkFramebuffer fb;
    483     vector<bool> hasSelfDependency;
    484     vector<DAGNode> subpassToNode;
    485     vector<vector<VkFormat>> subpassColorFormats;
    486     vector<MT_PASS_ATTACHMENT_INFO> attachments;
    487     unordered_map<uint32_t, bool> attachment_first_read;
    488     unordered_map<uint32_t, VkImageLayout> attachment_first_layout;
    489 
    490     RENDER_PASS_NODE(VkRenderPassCreateInfo const *pCreateInfo) : pCreateInfo(pCreateInfo), fb(VK_NULL_HANDLE) {
    491         uint32_t i;
    492 
    493         subpassColorFormats.reserve(pCreateInfo->subpassCount);
    494         for (i = 0; i < pCreateInfo->subpassCount; i++) {
    495             const VkSubpassDescription *subpass = &pCreateInfo->pSubpasses[i];
    496             vector<VkFormat> color_formats;
    497             uint32_t j;
    498 
    499             color_formats.reserve(subpass->colorAttachmentCount);
    500             for (j = 0; j < subpass->colorAttachmentCount; j++) {
    501                 const uint32_t att = subpass->pColorAttachments[j].attachment;
    502                 const VkFormat format = pCreateInfo->pAttachments[att].format;
    503 
    504                 color_formats.push_back(format);
    505             }
    506 
    507             subpassColorFormats.push_back(color_formats);
    508         }
    509     }
    510 };
    511 
    512 class PHYS_DEV_PROPERTIES_NODE {
    513   public:
    514     VkPhysicalDeviceProperties properties;
    515     VkPhysicalDeviceFeatures features;
    516     vector<VkQueueFamilyProperties> queue_family_properties;
    517 };
    518 
    519 class FENCE_NODE : public BASE_NODE {
    520   public:
    521     using BASE_NODE::in_use;
    522 #if MTMERGE
    523     uint64_t fenceId;         // Sequence number for fence at last submit
    524     VkSwapchainKHR swapchain; // Swapchain that this fence is submitted against or NULL
    525     VkBool32 firstTimeFlag;   // Fence was created in signaled state, avoid warnings for first use
    526     VkFenceCreateInfo createInfo;
    527 #endif
    528     VkQueue queue;
    529     vector<VkCommandBuffer> cmdBuffers;
    530     bool needsSignaled;
    531     vector<VkFence> priorFences;
    532 
    533     // Default constructor
    534     FENCE_NODE() : queue(NULL), needsSignaled(VK_FALSE){};
    535 };
    536 
    537 class SEMAPHORE_NODE : public BASE_NODE {
    538   public:
    539     using BASE_NODE::in_use;
    540     uint32_t signaled;
    541     SemaphoreState state;
    542     VkQueue queue;
    543 };
    544 
    545 class EVENT_NODE : public BASE_NODE {
    546   public:
    547     using BASE_NODE::in_use;
    548     bool needsSignaled;
    549     VkPipelineStageFlags stageMask;
    550 };
    551 
    552 class QUEUE_NODE {
    553   public:
    554     VkDevice device;
    555     vector<VkFence> lastFences;
    556 #if MTMERGE
    557     uint64_t lastRetiredId;
    558     uint64_t lastSubmittedId;
    559     // MTMTODO : merge cmd_buffer data structs here
    560     list<VkCommandBuffer> pQueueCommandBuffers;
    561     list<VkDeviceMemory> pMemRefList;
    562 #endif
    563     vector<VkCommandBuffer> untrackedCmdBuffers;
    564     unordered_set<VkCommandBuffer> inFlightCmdBuffers;
    565     unordered_map<VkEvent, VkPipelineStageFlags> eventToStageMap;
    566 };
    567 
    568 class QUERY_POOL_NODE : public BASE_NODE {
    569   public:
    570     VkQueryPoolCreateInfo createInfo;
    571 };
    572 
    573 class FRAMEBUFFER_NODE {
    574   public:
    575     VkFramebufferCreateInfo createInfo;
    576     unordered_set<VkCommandBuffer> referencingCmdBuffers;
    577     vector<MT_FB_ATTACHMENT_INFO> attachments;
    578 };
    579 
    580 // Descriptor Data structures
    581 // Layout Node has the core layout data
    582 typedef struct _LAYOUT_NODE {
    583     VkDescriptorSetLayout layout;
    584     VkDescriptorSetLayoutCreateInfo createInfo;
    585     uint32_t startIndex;                                 // 1st index of this layout
    586     uint32_t endIndex;                                   // last index of this layout
    587     uint32_t dynamicDescriptorCount;                     // Total count of dynamic descriptors used
    588                                                          // by this layout
    589     vector<VkDescriptorType> descriptorTypes;            // Type per descriptor in this
    590                                                          // layout to verify correct
    591                                                          // updates
    592     vector<VkShaderStageFlags> stageFlags;               // stageFlags per descriptor in this
    593                                                          // layout to verify correct updates
    594     unordered_map<uint32_t, uint32_t> bindingToIndexMap; // map set binding # to
    595                                                          // pBindings index
    596     // Default constructor
    597     _LAYOUT_NODE() : layout{}, createInfo{}, startIndex(0), endIndex(0), dynamicDescriptorCount(0){};
    598 } LAYOUT_NODE;
    599 
    600 // Store layouts and pushconstants for PipelineLayout
    601 struct PIPELINE_LAYOUT_NODE {
    602     vector<VkDescriptorSetLayout> descriptorSetLayouts;
    603     vector<VkPushConstantRange> pushConstantRanges;
    604 };
    605 
    606 class SET_NODE : public BASE_NODE {
    607   public:
    608     using BASE_NODE::in_use;
    609     VkDescriptorSet set;
    610     VkDescriptorPool pool;
    611     // Head of LL of all Update structs for this set
    612     GENERIC_HEADER *pUpdateStructs;
    613     // Total num of descriptors in this set (count of its layout plus all prior layouts)
    614     uint32_t descriptorCount;
    615     GENERIC_HEADER **ppDescriptors; // Array where each index points to update node for its slot
    616     LAYOUT_NODE *pLayout;           // Layout for this set
    617     SET_NODE *pNext;
    618     unordered_set<VkCommandBuffer> boundCmdBuffers; // Cmd buffers that this set has been bound to
    619     SET_NODE() : pUpdateStructs(NULL), ppDescriptors(NULL), pLayout(NULL), pNext(NULL){};
    620 };
    621 
    622 typedef struct _DESCRIPTOR_POOL_NODE {
    623     VkDescriptorPool pool;
    624     uint32_t maxSets;                              // Max descriptor sets allowed in this pool
    625     uint32_t availableSets;                        // Available descriptr sets in this pool
    626 
    627     VkDescriptorPoolCreateInfo createInfo;
    628     SET_NODE *pSets;                               // Head of LL of sets for this Pool
    629     vector<uint32_t> maxDescriptorTypeCount;       // Max # of descriptors of each type in this pool
    630     vector<uint32_t> availableDescriptorTypeCount; // Available # of descriptors of each type in this pool
    631 
    632     _DESCRIPTOR_POOL_NODE(const VkDescriptorPool pool, const VkDescriptorPoolCreateInfo *pCreateInfo)
    633         : pool(pool), maxSets(pCreateInfo->maxSets), availableSets(pCreateInfo->maxSets), createInfo(*pCreateInfo), pSets(NULL),
    634           maxDescriptorTypeCount(VK_DESCRIPTOR_TYPE_RANGE_SIZE), availableDescriptorTypeCount(VK_DESCRIPTOR_TYPE_RANGE_SIZE) {
    635         if (createInfo.poolSizeCount) { // Shadow type struct from ptr into local struct
    636             size_t poolSizeCountSize = createInfo.poolSizeCount * sizeof(VkDescriptorPoolSize);
    637             createInfo.pPoolSizes = new VkDescriptorPoolSize[poolSizeCountSize];
    638             memcpy((void *)createInfo.pPoolSizes, pCreateInfo->pPoolSizes, poolSizeCountSize);
    639             // Now set max counts for each descriptor type based on count of that type times maxSets
    640             uint32_t i = 0;
    641             for (i = 0; i < createInfo.poolSizeCount; ++i) {
    642                 uint32_t typeIndex = static_cast<uint32_t>(createInfo.pPoolSizes[i].type);
    643                 maxDescriptorTypeCount[typeIndex] = createInfo.pPoolSizes[i].descriptorCount;
    644                 availableDescriptorTypeCount[typeIndex] = maxDescriptorTypeCount[typeIndex];
    645             }
    646         } else {
    647             createInfo.pPoolSizes = NULL; // Make sure this is NULL so we don't try to clean it up
    648         }
    649     }
    650     ~_DESCRIPTOR_POOL_NODE() {
    651         delete[] createInfo.pPoolSizes;
    652         // TODO : pSets are currently freed in deletePools function which uses freeShadowUpdateTree function
    653         //  need to migrate that struct to smart ptrs for auto-cleanup
    654     }
    655 } DESCRIPTOR_POOL_NODE;
    656 
    657 // Cmd Buffer Tracking
    658 typedef enum _CMD_TYPE {
    659     CMD_BINDPIPELINE,
    660     CMD_BINDPIPELINEDELTA,
    661     CMD_SETVIEWPORTSTATE,
    662     CMD_SETSCISSORSTATE,
    663     CMD_SETLINEWIDTHSTATE,
    664     CMD_SETDEPTHBIASSTATE,
    665     CMD_SETBLENDSTATE,
    666     CMD_SETDEPTHBOUNDSSTATE,
    667     CMD_SETSTENCILREADMASKSTATE,
    668     CMD_SETSTENCILWRITEMASKSTATE,
    669     CMD_SETSTENCILREFERENCESTATE,
    670     CMD_BINDDESCRIPTORSETS,
    671     CMD_BINDINDEXBUFFER,
    672     CMD_BINDVERTEXBUFFER,
    673     CMD_DRAW,
    674     CMD_DRAWINDEXED,
    675     CMD_DRAWINDIRECT,
    676     CMD_DRAWINDEXEDINDIRECT,
    677     CMD_DISPATCH,
    678     CMD_DISPATCHINDIRECT,
    679     CMD_COPYBUFFER,
    680     CMD_COPYIMAGE,
    681     CMD_BLITIMAGE,
    682     CMD_COPYBUFFERTOIMAGE,
    683     CMD_COPYIMAGETOBUFFER,
    684     CMD_CLONEIMAGEDATA,
    685     CMD_UPDATEBUFFER,
    686     CMD_FILLBUFFER,
    687     CMD_CLEARCOLORIMAGE,
    688     CMD_CLEARATTACHMENTS,
    689     CMD_CLEARDEPTHSTENCILIMAGE,
    690     CMD_RESOLVEIMAGE,
    691     CMD_SETEVENT,
    692     CMD_RESETEVENT,
    693     CMD_WAITEVENTS,
    694     CMD_PIPELINEBARRIER,
    695     CMD_BEGINQUERY,
    696     CMD_ENDQUERY,
    697     CMD_RESETQUERYPOOL,
    698     CMD_COPYQUERYPOOLRESULTS,
    699     CMD_WRITETIMESTAMP,
    700     CMD_PUSHCONSTANTS,
    701     CMD_INITATOMICCOUNTERS,
    702     CMD_LOADATOMICCOUNTERS,
    703     CMD_SAVEATOMICCOUNTERS,
    704     CMD_BEGINRENDERPASS,
    705     CMD_NEXTSUBPASS,
    706     CMD_ENDRENDERPASS,
    707     CMD_EXECUTECOMMANDS,
    708 } CMD_TYPE;
    709 // Data structure for holding sequence of cmds in cmd buffer
    710 typedef struct _CMD_NODE {
    711     CMD_TYPE type;
    712     uint64_t cmdNumber;
    713 } CMD_NODE;
    714 
    715 typedef enum _CB_STATE {
    716     CB_NEW,       // Newly created CB w/o any cmds
    717     CB_RECORDING, // BeginCB has been called on this CB
    718     CB_RECORDED,  // EndCB has been called on this CB
    719     CB_INVALID    // CB had a bound descriptor set destroyed or updated
    720 } CB_STATE;
    721 // CB Status -- used to track status of various bindings on cmd buffer objects
    722 typedef VkFlags CBStatusFlags;
    723 typedef enum _CBStatusFlagBits {
    724     CBSTATUS_NONE = 0x00000000,                     // No status is set
    725     CBSTATUS_VIEWPORT_SET = 0x00000001,             // Viewport has been set
    726     CBSTATUS_LINE_WIDTH_SET = 0x00000002,           // Line width has been set
    727     CBSTATUS_DEPTH_BIAS_SET = 0x00000004,           // Depth bias has been set
    728     CBSTATUS_COLOR_BLEND_WRITE_ENABLE = 0x00000008, // PSO w/ CB Enable set has been set
    729     CBSTATUS_BLEND_SET = 0x00000010,                // Blend state object has been set
    730     CBSTATUS_DEPTH_WRITE_ENABLE = 0x00000020,       // PSO w/ Depth Enable set has been set
    731     CBSTATUS_STENCIL_TEST_ENABLE = 0x00000040,      // PSO w/ Stencil Enable set has been set
    732     CBSTATUS_DEPTH_BOUNDS_SET = 0x00000080,         // Depth bounds state object has been set
    733     CBSTATUS_STENCIL_READ_MASK_SET = 0x00000100,    // Stencil read mask has been set
    734     CBSTATUS_STENCIL_WRITE_MASK_SET = 0x00000200,   // Stencil write mask has been set
    735     CBSTATUS_STENCIL_REFERENCE_SET = 0x00000400,    // Stencil reference has been set
    736     CBSTATUS_INDEX_BUFFER_BOUND = 0x00000800,       // Index buffer has been set
    737     CBSTATUS_SCISSOR_SET = 0x00001000,              // Scissor has been set
    738     CBSTATUS_ALL = 0x00001FFF,                      // All dynamic state set
    739 } CBStatusFlagBits;
    740 
    741 typedef struct stencil_data {
    742     uint32_t compareMask;
    743     uint32_t writeMask;
    744     uint32_t reference;
    745 } CBStencilData;
    746 
    747 typedef struct _DRAW_DATA { vector<VkBuffer> buffers; } DRAW_DATA;
    748 
    749 struct ImageSubresourcePair {
    750     VkImage image;
    751     bool hasSubresource;
    752     VkImageSubresource subresource;
    753 };
    754 
    755 bool operator==(const ImageSubresourcePair &img1, const ImageSubresourcePair &img2) {
    756     if (img1.image != img2.image || img1.hasSubresource != img2.hasSubresource)
    757         return false;
    758     return !img1.hasSubresource ||
    759            (img1.subresource.aspectMask == img2.subresource.aspectMask && img1.subresource.mipLevel == img2.subresource.mipLevel &&
    760             img1.subresource.arrayLayer == img2.subresource.arrayLayer);
    761 }
    762 
    763 namespace std {
    764 template <> struct hash<ImageSubresourcePair> {
    765     size_t operator()(ImageSubresourcePair img) const throw() {
    766         size_t hashVal = hash<uint64_t>()(reinterpret_cast<uint64_t &>(img.image));
    767         hashVal ^= hash<bool>()(img.hasSubresource);
    768         if (img.hasSubresource) {
    769             hashVal ^= hash<uint32_t>()(reinterpret_cast<uint32_t &>(img.subresource.aspectMask));
    770             hashVal ^= hash<uint32_t>()(img.subresource.mipLevel);
    771             hashVal ^= hash<uint32_t>()(img.subresource.arrayLayer);
    772         }
    773         return hashVal;
    774     }
    775 };
    776 }
    777 
    778 struct QueryObject {
    779     VkQueryPool pool;
    780     uint32_t index;
    781 };
    782 
    783 bool operator==(const QueryObject &query1, const QueryObject &query2) {
    784     return (query1.pool == query2.pool && query1.index == query2.index);
    785 }
    786 
    787 namespace std {
    788 template <> struct hash<QueryObject> {
    789     size_t operator()(QueryObject query) const throw() {
    790         return hash<uint64_t>()((uint64_t)(query.pool)) ^ hash<uint32_t>()(query.index);
    791     }
    792 };
    793 }
    794 // Track last states that are bound per pipeline bind point (Gfx & Compute)
    795 struct LAST_BOUND_STATE {
    796     VkPipeline pipeline;
    797     VkPipelineLayout pipelineLayout;
    798     // Track each set that has been bound
    799     // TODO : can unique be global per CB? (do we care about Gfx vs. Compute?)
    800     unordered_set<VkDescriptorSet> uniqueBoundSets;
    801     // Ordered bound set tracking where index is set# that given set is bound to
    802     vector<VkDescriptorSet> boundDescriptorSets;
    803     // one dynamic offset per dynamic descriptor bound to this CB
    804     vector<uint32_t> dynamicOffsets;
    805     void reset() {
    806         pipeline = VK_NULL_HANDLE;
    807         pipelineLayout = VK_NULL_HANDLE;
    808         uniqueBoundSets.clear();
    809         boundDescriptorSets.clear();
    810         dynamicOffsets.clear();
    811     }
    812 };
    813 // Cmd Buffer Wrapper Struct
    814 struct GLOBAL_CB_NODE {
    815     VkCommandBuffer commandBuffer;
    816     VkCommandBufferAllocateInfo createInfo;
    817     VkCommandBufferBeginInfo beginInfo;
    818     VkCommandBufferInheritanceInfo inheritanceInfo;
    819     // VkFence fence;                      // fence tracking this cmd buffer
    820     VkDevice device;                    // device this CB belongs to
    821     uint64_t numCmds;                   // number of cmds in this CB
    822     uint64_t drawCount[NUM_DRAW_TYPES]; // Count of each type of draw in this CB
    823     CB_STATE state;                     // Track cmd buffer update state
    824     uint64_t submitCount;               // Number of times CB has been submitted
    825     CBStatusFlags status;               // Track status of various bindings on cmd buffer
    826     vector<CMD_NODE> cmds;              // vector of commands bound to this command buffer
    827     // Currently storing "lastBound" objects on per-CB basis
    828     //  long-term may want to create caches of "lastBound" states and could have
    829     //  each individual CMD_NODE referencing its own "lastBound" state
    830     //    VkPipeline lastBoundPipeline;
    831     //    VkPipelineLayout lastBoundPipelineLayout;
    832     //    // Capture unique std::set of descriptorSets that are bound to this CB.
    833     //    std::set<VkDescriptorSet> uniqueBoundSets;
    834     //    vector<VkDescriptorSet> boundDescriptorSets; // Index is set# that given set is bound to
    835     // Store last bound state for Gfx & Compute pipeline bind points
    836     LAST_BOUND_STATE lastBound[VK_PIPELINE_BIND_POINT_RANGE_SIZE];
    837 
    838     vector<uint32_t> dynamicOffsets;
    839     vector<VkViewport> viewports;
    840     vector<VkRect2D> scissors;
    841     VkRenderPassBeginInfo activeRenderPassBeginInfo;
    842     uint64_t fenceId;
    843     VkFence lastSubmittedFence;
    844     VkQueue lastSubmittedQueue;
    845     VkRenderPass activeRenderPass;
    846     VkSubpassContents activeSubpassContents;
    847     uint32_t activeSubpass;
    848     VkFramebuffer framebuffer;
    849     // Track descriptor sets that are destroyed or updated while bound to CB
    850     // TODO : These data structures relate to tracking resources that invalidate
    851     //  a cmd buffer that references them. Need to unify how we handle these
    852     //  cases so we don't have different tracking data for each type.
    853     std::set<VkDescriptorSet> destroyedSets;
    854     std::set<VkDescriptorSet> updatedSets;
    855     unordered_set<VkFramebuffer> destroyedFramebuffers;
    856     vector<VkEvent> waitedEvents;
    857     vector<VkSemaphore> semaphores;
    858     vector<VkEvent> events;
    859     unordered_map<QueryObject, vector<VkEvent>> waitedEventsBeforeQueryReset;
    860     unordered_map<QueryObject, bool> queryToStateMap; // 0 is unavailable, 1 is available
    861     unordered_set<QueryObject> activeQueries;
    862     unordered_set<QueryObject> startedQueries;
    863     unordered_map<ImageSubresourcePair, IMAGE_CMD_BUF_LAYOUT_NODE> imageLayoutMap;
    864     unordered_map<VkImage, vector<ImageSubresourcePair>> imageSubresourceMap;
    865     unordered_map<VkEvent, VkPipelineStageFlags> eventToStageMap;
    866     vector<DRAW_DATA> drawData;
    867     DRAW_DATA currentDrawData;
    868     VkCommandBuffer primaryCommandBuffer;
    869     // If cmd buffer is primary, track secondary command buffers pending
    870     // execution
    871     std::unordered_set<VkCommandBuffer> secondaryCommandBuffers;
    872     // MTMTODO : Scrub these data fields and merge active sets w/ lastBound as appropriate
    873     vector<VkDescriptorSet> activeDescriptorSets;
    874     vector<std::function<VkBool32()>> validate_functions;
    875     list<VkDeviceMemory> pMemObjList; // List container of Mem objs referenced by this CB
    876     vector<std::function<bool(VkQueue)>> eventUpdates;
    877 };
    878 
    879 class SWAPCHAIN_NODE {
    880   public:
    881     VkSwapchainCreateInfoKHR createInfo;
    882     uint32_t *pQueueFamilyIndices;
    883     std::vector<VkImage> images;
    884     SWAPCHAIN_NODE(const VkSwapchainCreateInfoKHR *pCreateInfo) : createInfo(*pCreateInfo), pQueueFamilyIndices(NULL) {
    885         if (pCreateInfo->queueFamilyIndexCount && pCreateInfo->imageSharingMode == VK_SHARING_MODE_CONCURRENT) {
    886             pQueueFamilyIndices = new uint32_t[pCreateInfo->queueFamilyIndexCount];
    887             memcpy(pQueueFamilyIndices, pCreateInfo->pQueueFamilyIndices, pCreateInfo->queueFamilyIndexCount * sizeof(uint32_t));
    888             createInfo.pQueueFamilyIndices = pQueueFamilyIndices;
    889         }
    890     }
    891     ~SWAPCHAIN_NODE() { delete[] pQueueFamilyIndices; }
    892 };
    893 
    894 //#ifdef __cplusplus
    895 //}
    896 //#endif
    897