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@google.com> 26 * Author: Tobin Ehlis <tobine@google.com> 27 * Author: Chris Forbes <chrisf@ijw.co.nz> 28 * Author: Mark Lobodzinski <mark@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 _PIPELINE_NODE_PIPELINE_NODE429 _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 _SAMPLER_NODE_SAMPLER_NODE446 _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 RENDER_PASS_NODERENDER_PASS_NODE490 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 FENCE_NODE()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 _LAYOUT_NODE_LAYOUT_NODE597 _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 SET_NODE()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 _DESCRIPTOR_POOL_NODE_DESCRIPTOR_POOL_NODE632 _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 } ~_DESCRIPTOR_POOL_NODE_DESCRIPTOR_POOL_NODE650 ~_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