core_validation.cpp revision 0dcd0f7b37456e2e552d37094ba503c0d089b906
15b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis/* Copyright (c) 2015-2016 The Khronos Group Inc.
25b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis * Copyright (c) 2015-2016 Valve Corporation
35b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis * Copyright (c) 2015-2016 LunarG, Inc.
45b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis * Copyright (C) 2015-2016 Google Inc.
55b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis *
643b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * Licensed under the Apache License, Version 2.0 (the "License");
743b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * you may not use this file except in compliance with the License.
843b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * You may obtain a copy of the License at
95b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis *
1043b53e83705f02245da6ae61e31273866a35b833Jon Ashburn *     http://www.apache.org/licenses/LICENSE-2.0
115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis *
1243b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * Unless required by applicable law or agreed to in writing, software
1343b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * distributed under the License is distributed on an "AS IS" BASIS,
1443b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1543b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * See the License for the specific language governing permissions and
1643b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * limitations under the License.
175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis *
185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis * Author: Cody Northrop <cnorthrop@google.com>
195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis * Author: Michael Lentine <mlentine@google.com>
205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis * Author: Tobin Ehlis <tobine@google.com>
215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis * Author: Chia-I Wu <olv@google.com>
225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis * Author: Chris Forbes <chrisf@ijw.co.nz>
235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis * Author: Mark Lobodzinski <mark@lunarg.com>
245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis * Author: Ian Elliott <ianelliott@google.com>
255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis */
265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Allow use of STL min and max functions in Windows
285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#define NOMINMAX
295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Turn on mem_tracker merged code
3103b71511c9e94f2e6101a3214858cee3742ec277Mark Lobodzinski#define MTMERGESOURCE 1
325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3394c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis#include <SPIRV/spirv.hpp>
3494c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis#include <algorithm>
3594c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis#include <assert.h>
3694c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis#include <iostream>
3794c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis#include <list>
3894c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis#include <map>
39b9e992386a44404152747d66817a733aa127e281Jeremy Hayes#include <mutex>
4094c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis#include <set>
41825ac70f99460ccb9494d34f93d8ee7ec303e5deMark Lobodzinski//#include <memory>
425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include <stdio.h>
435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include <stdlib.h>
445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include <string.h>
4594c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis#include <string>
46dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes#include <tuple>
475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include "vk_loader_platform.h"
495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include "vk_dispatch_table_helper.h"
505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include "vk_struct_string_helper_cpp.h"
515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#if defined(__GNUC__)
525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#pragma GCC diagnostic ignored "-Wwrite-strings"
535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#endif
545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#if defined(__GNUC__)
555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#pragma GCC diagnostic warning "-Wwrite-strings"
565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#endif
575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include "vk_struct_size_helper.h"
585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include "core_validation.h"
595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include "vk_layer_table.h"
605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include "vk_layer_data.h"
615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include "vk_layer_extension_utils.h"
625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include "vk_layer_utils.h"
63b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes#include "spirv-tools/libspirv.h"
645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#if defined __ANDROID__
665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include <android/log.h>
675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#define LOGCONSOLE(...) ((void)__android_log_print(ANDROID_LOG_INFO, "DS", __VA_ARGS__))
685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#else
69c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine#define LOGCONSOLE(...)                                                                                                            \
70c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine    {                                                                                                                              \
71c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine        printf(__VA_ARGS__);                                                                                                       \
72c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine        printf("\n");                                                                                                              \
73c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine    }
745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#endif
755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
76414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Muellerusing namespace std;
77414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller
78d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wunamespace core_validation {
79d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu
805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisusing std::unordered_map;
815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisusing std::unordered_set;
825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// WSI Image Objects bypass usual Image Object creation methods.  A special Memory
845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Object value will be used to identify them internally.
855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic const VkDeviceMemory MEMTRACKER_SWAP_CHAIN_IMAGE_KEY = (VkDeviceMemory)(-1);
86888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis// 2nd special memory handle used to flag object as unbound from memory
87888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlisstatic const VkDeviceMemory MEMORY_UNBOUND = VkDeviceMemory(~((uint64_t)(0)) - 1);
88b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis
895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstruct devExts {
90e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool wsi_enabled;
91c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young    bool wsi_display_swapchain_enabled;
923f687bf405355f3eec6bd1bc0e8d04daba37a0f9Tobin Ehlis    unordered_map<VkSwapchainKHR, unique_ptr<SWAPCHAIN_NODE>> swapchainMap;
935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<VkImage, VkSwapchainKHR> imageToSwapchainMap;
945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis};
955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// fwd decls
975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstruct shader_module;
985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
99f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesstruct instance_layer_data {
100d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes    VkInstance instance = VK_NULL_HANDLE;
101d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes    unique_ptr<INSTANCE_STATE> instance_state = nullptr;
102d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes    debug_report_data *report_data = nullptr;
1035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    std::vector<VkDebugReportCallbackEXT> logging_callback;
1049172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    VkLayerInstanceDispatchTable dispatch_table;
1059172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes
106f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes    unordered_map<VkPhysicalDevice, PHYSICAL_DEVICE_STATE> physical_device_map;
107747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    unordered_map<VkSurfaceKHR, SURFACE_STATE> surface_map;
108747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
109747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    bool surfaceExtensionEnabled = false;
110747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    bool displayExtensionEnabled = false;
111747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_ANDROID_KHR
112747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    bool androidSurfaceExtensionEnabled = false;
113747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif
114747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_MIR_KHR
115747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    bool mirSurfaceExtensionEnabled = false;
116747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif
117747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WAYLAND_KHR
118747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    bool waylandSurfaceExtensionEnabled = false;
119747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif
120747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WIN32_KHR
121747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    bool win32SurfaceExtensionEnabled = false;
122747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif
123747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XCB_KHR
124747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    bool xcbSurfaceExtensionEnabled = false;
125747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif
126747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XLIB_KHR
127747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    bool xlibSurfaceExtensionEnabled = false;
128747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif
129f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes};
130f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes
131f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesstruct layer_data {
132f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes    debug_report_data *report_data = nullptr;
1334a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkLayerDispatchTable dispatch_table;
134f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes    unique_ptr<INSTANCE_STATE> instance_state = nullptr;
13594c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis
136d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes    devExts device_extensions = {};
137cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski    unordered_set<VkQueue> queues;  // All queues under given device
1385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Global set of all cmdBuffers that are inFlight on this device
1395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_set<VkCommandBuffer> globalInFlightCmdBuffers;
1405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Layer specific data
141cb9ce9e05b8e939d3da35c64997c70049877f4feTobin Ehlis    unordered_map<VkSampler, unique_ptr<SAMPLER_NODE>> samplerMap;
14279fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis    unordered_map<VkImageView, unique_ptr<IMAGE_VIEW_STATE>> imageViewMap;
1436d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis    unordered_map<VkImage, unique_ptr<IMAGE_NODE>> imageMap;
14439267c0c27b8f032f05a6747eb02d4508247fdc1Tobin Ehlis    unordered_map<VkBufferView, unique_ptr<BUFFER_VIEW_STATE>> bufferViewMap;
1458718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis    unordered_map<VkBuffer, unique_ptr<BUFFER_NODE>> bufferMap;
1465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<VkPipeline, PIPELINE_NODE *> pipelineMap;
1478d6a38de0389036581ada119e548180c614fe0efChris Forbes    unordered_map<VkCommandPool, COMMAND_POOL_NODE> commandPoolMap;
1485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<VkDescriptorPool, DESCRIPTOR_POOL_NODE *> descriptorPoolMap;
149397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis    unordered_map<VkDescriptorSet, cvdescriptorset::DescriptorSet *> setMap;
150cb9ce9e05b8e939d3da35c64997c70049877f4feTobin Ehlis    unordered_map<VkDescriptorSetLayout, cvdescriptorset::DescriptorSetLayout *> descriptorSetLayoutMap;
1515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<VkPipelineLayout, PIPELINE_LAYOUT_NODE> pipelineLayoutMap;
15257fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis    unordered_map<VkDeviceMemory, unique_ptr<DEVICE_MEM_INFO>> memObjMap;
1535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<VkFence, FENCE_NODE> fenceMap;
1545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<VkQueue, QUEUE_NODE> queueMap;
1555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<VkEvent, EVENT_NODE> eventMap;
1565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<QueryObject, bool> queryToStateMap;
1575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<VkQueryPool, QUERY_POOL_NODE> queryPoolMap;
1585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<VkSemaphore, SEMAPHORE_NODE> semaphoreMap;
15972d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis    unordered_map<VkCommandBuffer, GLOBAL_CB_NODE *> commandBufferMap;
16004861caca7eb93a5241b164e8480bb93c826902cTobin Ehlis    unordered_map<VkFramebuffer, unique_ptr<FRAMEBUFFER_NODE>> frameBufferMap;
1615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<VkImage, vector<ImageSubresourcePair>> imageSubresourceMap;
1625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> imageLayoutMap;
163fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes    unordered_map<VkRenderPass, unique_ptr<RENDER_PASS_NODE>> renderPassMap;
164918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes    unordered_map<VkShaderModule, unique_ptr<shader_module>> shaderModuleMap;
165d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes    VkDevice device = VK_NULL_HANDLE;
1665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
167f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes    instance_layer_data *instance_data = nullptr;  // from device to enclosing instance
16807a464bd7fec9583f346b8c4b8d43c88d2e9ffa4Chris Forbes
169f71dd305f197826a61f398bff725267a20ea1d90Chris Forbes    VkPhysicalDeviceFeatures enabled_features = {};
1705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Device specific data
171d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes    PHYS_DEV_PROPERTIES_NODE phys_dev_properties = {};
172d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes    VkPhysicalDeviceMemoryProperties phys_dev_mem_props = {};
1735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis};
1745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
175b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis// TODO : Do we need to guard access to layer_data_map w/ lock?
176b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlisstatic unordered_map<void *, layer_data *> layer_data_map;
177f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesstatic unordered_map<void *, instance_layer_data *> instance_layer_data_map;
178b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis
179e11120777bcd1543455d1de54b89292879bcd2bbChia-I Wustatic const VkLayerProperties global_layer = {
180f1ea418f193d10a8455cdf47e0eeeeb1f4d8b5bfJon Ashburn    "VK_LAYER_LUNARG_core_validation", VK_LAYER_API_VERSION, 1, "LunarG Validation Layer",
181e11120777bcd1543455d1de54b89292879bcd2bbChia-I Wu};
1825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlistemplate <class TCreateInfo> void ValidateLayerOrdering(const TCreateInfo &createInfo) {
1845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    bool foundLayer = false;
1855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < createInfo.enabledLayerCount; ++i) {
186e11120777bcd1543455d1de54b89292879bcd2bbChia-I Wu        if (!strcmp(createInfo.ppEnabledLayerNames[i], global_layer.layerName)) {
1875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            foundLayer = true;
1885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
1895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // This has to be logged to console as we don't have a callback at this point.
1905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (!foundLayer && !strcmp(createInfo.ppEnabledLayerNames[0], "VK_LAYER_GOOGLE_unique_objects")) {
1915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            LOGCONSOLE("Cannot activate layer VK_LAYER_GOOGLE_unique_objects prior to activating %s.",
192e11120777bcd1543455d1de54b89292879bcd2bbChia-I Wu                       global_layer.layerName);
1935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
1945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
1955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
1965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Code imported from shader_checker
1985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic void build_def_index(shader_module *);
1995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// A forward iterator over spirv instructions. Provides easy access to len, opcode, and content words
2015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// without the caller needing to care too much about the physical SPIRV module layout.
2025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstruct spirv_inst_iter {
2035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    std::vector<uint32_t>::const_iterator zero;
2045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    std::vector<uint32_t>::const_iterator it;
2055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
206b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes    uint32_t len() {
207b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes        auto result = *it >> 16;
208b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes        assert(result > 0);
209b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes        return result;
210b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes    }
211b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes
2125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t opcode() { return *it & 0x0ffffu; }
213b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes
214b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes    uint32_t const &word(unsigned n) {
215b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes        assert(n < len());
216b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes        return it[n];
217b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes    }
218b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes
2195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t offset() { return (uint32_t)(it - zero); }
2205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    spirv_inst_iter() {}
2225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    spirv_inst_iter(std::vector<uint32_t>::const_iterator zero, std::vector<uint32_t>::const_iterator it) : zero(zero), it(it) {}
2245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    bool operator==(spirv_inst_iter const &other) { return it == other.it; }
2265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    bool operator!=(spirv_inst_iter const &other) { return it != other.it; }
2285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    spirv_inst_iter operator++(int) { /* x++ */
2305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        spirv_inst_iter ii = *this;
2315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        it += len();
2325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return ii;
2335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
2345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    spirv_inst_iter operator++() { /* ++x; */
2365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        it += len();
2375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return *this;
2385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
2395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    /* The iterator and the value are the same thing. */
2415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    spirv_inst_iter &operator*() { return *this; }
2425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    spirv_inst_iter const &operator*() const { return *this; }
2435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis};
2445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstruct shader_module {
2465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    /* the spirv image itself */
2475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    vector<uint32_t> words;
2485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    /* a mapping of <id> to the first word of its def. this is useful because walking type
2495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis     * trees, constant expressions, etc requires jumping all over the instruction stream.
2505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis     */
2515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<unsigned, unsigned> def_index;
2525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    shader_module(VkShaderModuleCreateInfo const *pCreateInfo)
2545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        : words((uint32_t *)pCreateInfo->pCode, (uint32_t *)pCreateInfo->pCode + pCreateInfo->codeSize / sizeof(uint32_t)),
2555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis          def_index() {
2565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        build_def_index(this);
2585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
2595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    /* expose begin() / end() to enable range-based for */
2615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    spirv_inst_iter begin() const { return spirv_inst_iter(words.begin(), words.begin() + 5); } /* first insn */
2625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    spirv_inst_iter end() const { return spirv_inst_iter(words.begin(), words.end()); }         /* just past last insn */
2635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    /* given an offset into the module, produce an iterator there. */
2645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    spirv_inst_iter at(unsigned offset) const { return spirv_inst_iter(words.begin(), words.begin() + offset); }
2655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    /* gets an iterator to the definition of an id */
2675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    spirv_inst_iter get_def(unsigned id) const {
2685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto it = def_index.find(id);
2695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (it == def_index.end()) {
2705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            return end();
2715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
2725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return at(it->second);
2735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
2745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis};
2755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// TODO : This can be much smarter, using separate locks for separate global data
277b9e992386a44404152747d66817a733aa127e281Jeremy Hayesstatic std::mutex global_lock;
278593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
27979fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis// Return IMAGE_VIEW_STATE ptr for specified imageView or else NULL
28079fde938178535f598e030a0e9d19a0cb61b72e0Tobin EhlisIMAGE_VIEW_STATE *getImageViewState(const layer_data *dev_data, VkImageView image_view) {
2812c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis    auto iv_it = dev_data->imageViewMap.find(image_view);
2822c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis    if (iv_it == dev_data->imageViewMap.end()) {
2832c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis        return nullptr;
2842c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis    }
2852c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis    return iv_it->second.get();
2862c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis}
2879a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis// Return sampler node ptr for specified sampler or else NULL
288a682b1c533d9a492243b363c6585c4f03bcd87aaTobin EhlisSAMPLER_NODE *getSamplerNode(const layer_data *dev_data, VkSampler sampler) {
2892c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis    auto sampler_it = dev_data->samplerMap.find(sampler);
2902c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis    if (sampler_it == dev_data->samplerMap.end()) {
2919a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis        return nullptr;
2929a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis    }
2939a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis    return sampler_it->second.get();
2949a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis}
2956d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis// Return image node ptr for specified image or else NULL
296a682b1c533d9a492243b363c6585c4f03bcd87aaTobin EhlisIMAGE_NODE *getImageNode(const layer_data *dev_data, VkImage image) {
2976d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis    auto img_it = dev_data->imageMap.find(image);
2986d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis    if (img_it == dev_data->imageMap.end()) {
2996d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis        return nullptr;
3006d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis    }
3016d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis    return img_it->second.get();
3026d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis}
3038718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis// Return buffer node ptr for specified buffer or else NULL
304a682b1c533d9a492243b363c6585c4f03bcd87aaTobin EhlisBUFFER_NODE *getBufferNode(const layer_data *dev_data, VkBuffer buffer) {
3052c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis    auto buff_it = dev_data->bufferMap.find(buffer);
3062c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis    if (buff_it == dev_data->bufferMap.end()) {
3078718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis        return nullptr;
3088718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis    }
3098718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis    return buff_it->second.get();
3108718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis}
311b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis// Return swapchain node for specified swapchain or else NULL
312a682b1c533d9a492243b363c6585c4f03bcd87aaTobin EhlisSWAPCHAIN_NODE *getSwapchainNode(const layer_data *dev_data, VkSwapchainKHR swapchain) {
313b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis    auto swp_it = dev_data->device_extensions.swapchainMap.find(swapchain);
314b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis    if (swp_it == dev_data->device_extensions.swapchainMap.end()) {
315b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis        return nullptr;
316b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis    }
3173f687bf405355f3eec6bd1bc0e8d04daba37a0f9Tobin Ehlis    return swp_it->second.get();
318b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis}
319170dc65b45f6bcdec47e02b3aa19435e55b32804Tobin Ehlis// Return swapchain for specified image or else NULL
320a682b1c533d9a492243b363c6585c4f03bcd87aaTobin EhlisVkSwapchainKHR getSwapchainFromImage(const layer_data *dev_data, VkImage image) {
321170dc65b45f6bcdec47e02b3aa19435e55b32804Tobin Ehlis    auto img_it = dev_data->device_extensions.imageToSwapchainMap.find(image);
322170dc65b45f6bcdec47e02b3aa19435e55b32804Tobin Ehlis    if (img_it == dev_data->device_extensions.imageToSwapchainMap.end()) {
323170dc65b45f6bcdec47e02b3aa19435e55b32804Tobin Ehlis        return VK_NULL_HANDLE;
324170dc65b45f6bcdec47e02b3aa19435e55b32804Tobin Ehlis    }
325170dc65b45f6bcdec47e02b3aa19435e55b32804Tobin Ehlis    return img_it->second;
326170dc65b45f6bcdec47e02b3aa19435e55b32804Tobin Ehlis}
3272f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis// Return buffer node ptr for specified buffer or else NULL
32839267c0c27b8f032f05a6747eb02d4508247fdc1Tobin EhlisBUFFER_VIEW_STATE *getBufferViewState(const layer_data *my_data, VkBufferView buffer_view) {
3292f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis    auto bv_it = my_data->bufferViewMap.find(buffer_view);
3302f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis    if (bv_it == my_data->bufferViewMap.end()) {
3312f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis        return nullptr;
3322f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis    }
3332f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis    return bv_it->second.get();
3342f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis}
3358718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis
33666fb98d19a758f79dd11ba354e47d0c66c6aac1eChris ForbesFENCE_NODE *getFenceNode(layer_data *dev_data, VkFence fence) {
33766fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes    auto it = dev_data->fenceMap.find(fence);
33866fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes    if (it == dev_data->fenceMap.end()) {
33966fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes        return nullptr;
34066fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes    }
34166fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes    return &it->second;
34266fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes}
34366fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes
3449556936067fd0c4eb74c4a13631bc163b154faedTobin EhlisEVENT_NODE *getEventNode(layer_data *dev_data, VkEvent event) {
3459556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis    auto it = dev_data->eventMap.find(event);
3469556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis    if (it == dev_data->eventMap.end()) {
3479556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis        return nullptr;
3489556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis    }
3499556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis    return &it->second;
3509556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis}
3519556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis
352ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin EhlisQUERY_POOL_NODE *getQueryPoolNode(layer_data *dev_data, VkQueryPool query_pool) {
353ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis    auto it = dev_data->queryPoolMap.find(query_pool);
354ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis    if (it == dev_data->queryPoolMap.end()) {
355ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis        return nullptr;
356ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis    }
357ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis    return &it->second;
358ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis}
359ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis
36066fb98d19a758f79dd11ba354e47d0c66c6aac1eChris ForbesQUEUE_NODE *getQueueNode(layer_data *dev_data, VkQueue queue) {
36166fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes    auto it = dev_data->queueMap.find(queue);
36266fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes    if (it == dev_data->queueMap.end()) {
36366fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes        return nullptr;
36466fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes    }
36566fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes    return &it->second;
36666fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes}
36766fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes
3685e92f3cfdca6a52a3dcefd053c41f728bd036cebChris ForbesSEMAPHORE_NODE *getSemaphoreNode(layer_data *dev_data, VkSemaphore semaphore) {
3695e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes    auto it = dev_data->semaphoreMap.find(semaphore);
3705e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes    if (it == dev_data->semaphoreMap.end()) {
3715e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes        return nullptr;
3725e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes    }
3735e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes    return &it->second;
3745e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes}
3755e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes
3768d6a38de0389036581ada119e548180c614fe0efChris ForbesCOMMAND_POOL_NODE *getCommandPoolNode(layer_data *dev_data, VkCommandPool pool) {
3778d6a38de0389036581ada119e548180c614fe0efChris Forbes    auto it = dev_data->commandPoolMap.find(pool);
3788d6a38de0389036581ada119e548180c614fe0efChris Forbes    if (it == dev_data->commandPoolMap.end()) {
3798d6a38de0389036581ada119e548180c614fe0efChris Forbes        return nullptr;
3808d6a38de0389036581ada119e548180c614fe0efChris Forbes    }
3818d6a38de0389036581ada119e548180c614fe0efChris Forbes    return &it->second;
3828d6a38de0389036581ada119e548180c614fe0efChris Forbes}
3833bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes
384f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris ForbesPHYSICAL_DEVICE_STATE *getPhysicalDeviceState(instance_layer_data *instance_data, VkPhysicalDevice phys) {
385f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes    auto it = instance_data->physical_device_map.find(phys);
386f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes    if (it == instance_data->physical_device_map.end()) {
3873bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes        return nullptr;
3883bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes    }
3893bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes    return &it->second;
3903bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes}
3913bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes
392747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesSURFACE_STATE *getSurfaceState(instance_layer_data *instance_data, VkSurfaceKHR surface) {
393747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    auto it = instance_data->surface_map.find(surface);
394747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    if (it == instance_data->surface_map.end()) {
395747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        return nullptr;
396747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    }
397747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    return &it->second;
398747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
399747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
400888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis// Return ptr to bound memory for given handle of specified type and set sparse param to indicate if binding is sparse
401888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlisstatic VkDeviceMemory *GetObjectMemBinding(layer_data *my_data, uint64_t handle, VkDebugReportObjectTypeEXT type, bool *sparse) {
4025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    switch (type) {
4035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: {
4046d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis        auto img_node = getImageNode(my_data, VkImage(handle));
405888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis        *sparse = img_node->createInfo.flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT;
4066d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis        if (img_node)
4076d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            return &img_node->mem;
4085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        break;
4095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
4105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT: {
4118718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis        auto buff_node = getBufferNode(my_data, VkBuffer(handle));
412888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis        *sparse = buff_node->createInfo.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT;
4138718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis        if (buff_node)
4148718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis            return &buff_node->mem;
4155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        break;
4165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
4175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    default:
4185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        break;
4195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
42094c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis    return nullptr;
4215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
422888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis// Overloaded version of above function that doesn't care about sparse bool
423888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlisstatic VkDeviceMemory *GetObjectMemBinding(layer_data *my_data, uint64_t handle, VkDebugReportObjectTypeEXT type) {
424888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis    bool sparse;
425888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis    return GetObjectMemBinding(my_data, handle, type, &sparse);
426888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis}
42772d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis// prototype
4285121a8dcacb23766ba4455b4eea429f0a3d62099Chris Forbesstatic GLOBAL_CB_NODE *getCBNode(layer_data const *, const VkCommandBuffer);
42972d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis
4305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Helper function to validate correct usage bits set for buffers or images
4315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//  Verify that (actual & desired) flags != 0 or,
4325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//   if strict is true, verify that (actual & desired) flags == desired
4335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//  In case of error, report it via dbg callbacks
4340a1ce3dfd81c9f4efbe46f5ba5ddaea70bc4aa61Chris Forbesstatic bool validate_usage_flags(layer_data *my_data, VkFlags actual, VkFlags desired, VkBool32 strict,
4350a1ce3dfd81c9f4efbe46f5ba5ddaea70bc4aa61Chris Forbes                                     uint64_t obj_handle, VkDebugReportObjectTypeEXT obj_type, char const *ty_str,
4360a1ce3dfd81c9f4efbe46f5ba5ddaea70bc4aa61Chris Forbes                                     char const *func_name, char const *usage_str) {
437e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool correct_usage = false;
43883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
4395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (strict)
4405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        correct_usage = ((actual & desired) == desired);
4415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    else
4425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        correct_usage = ((actual & desired) != 0);
4435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (!correct_usage) {
44483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, obj_type, obj_handle, __LINE__,
44583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            MEMTRACK_INVALID_USAGE_FLAG, "MEM", "Invalid usage flag for %s 0x%" PRIxLEAST64
44683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                                                " used by %s. In this case, %s should have %s set during creation.",
44783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            ty_str, obj_handle, func_name, ty_str, usage_str);
4485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
44983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    return skip_call;
4505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
4515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Helper function to validate usage flags for buffers
453249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis// For given buffer_node send actual vs. desired usage off to helper above where
454249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis//  an error will be flagged if usage is not correct
45559b0561b0bd298885f90b9f524c0583cd8ee6f61Tobin Ehlisstatic bool ValidateImageUsageFlags(layer_data *dev_data, IMAGE_NODE const *image_node, VkFlags desired, VkBool32 strict,
456249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis                                    char const *func_name, char const *usage_string) {
457249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis    return validate_usage_flags(dev_data, image_node->createInfo.usage, desired, strict,
458249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis                                reinterpret_cast<const uint64_t &>(image_node->image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
459249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis                                "image", func_name, usage_string);
460249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis}
461249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis
462249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis// Helper function to validate usage flags for buffers
463ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis// For given buffer_node send actual vs. desired usage off to helper above where
464ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis//  an error will be flagged if usage is not correct
46559b0561b0bd298885f90b9f524c0583cd8ee6f61Tobin Ehlisstatic bool ValidateBufferUsageFlags(layer_data *dev_data, BUFFER_NODE const *buffer_node, VkFlags desired, VkBool32 strict,
466ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis                                     char const *func_name, char const *usage_string) {
467ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    return validate_usage_flags(dev_data, buffer_node->createInfo.usage, desired, strict,
468ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis                                reinterpret_cast<const uint64_t &>(buffer_node->buffer), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT,
469ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis                                "buffer", func_name, usage_string);
470ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis}
471ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis
4725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Return ptr to info in map container containing mem, or NULL if not found
4735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//  Calls to this function should be wrapped in mutex
47457fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin EhlisDEVICE_MEM_INFO *getMemObjInfo(const layer_data *dev_data, const VkDeviceMemory mem) {
47557fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis    auto mem_it = dev_data->memObjMap.find(mem);
47657fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis    if (mem_it == dev_data->memObjMap.end()) {
4775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return NULL;
4785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
47957fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis    return mem_it->second.get();
4805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
4815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic void add_mem_obj_info(layer_data *my_data, void *object, const VkDeviceMemory mem,
4835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                             const VkMemoryAllocateInfo *pAllocateInfo) {
4845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    assert(object != NULL);
4855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
48657fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis    my_data->memObjMap[mem] = unique_ptr<DEVICE_MEM_INFO>(new DEVICE_MEM_INFO(object, mem, pAllocateInfo));
4875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
488dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis
489dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis// Helper function to print lowercase string of object type
490dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis//  TODO: Unify string helper functions, this should really come out of a string helper if not there already
491dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlisstatic const char *object_type_to_string(VkDebugReportObjectTypeEXT type) {
492dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis    switch (type) {
493dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT:
494dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis        return "image";
495dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT:
496dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis        return "buffer";
4977e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT:
4987e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        return "image view";
4997e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT:
5007e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        return "buffer view";
501dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT:
502dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis        return "swapchain";
503dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT:
504dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis        return "descriptor set";
505dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT:
5066f62283faa835f7fd302771a3a693d1aafff4652Tobin Ehlis        return "framebuffer";
507dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT:
508dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis        return "event";
509dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT:
510dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis        return "query pool";
5117e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT:
5127e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        return "descriptor pool";
5137e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT:
5147e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        return "command pool";
515dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT:
516dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis        return "pipeline";
517dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT:
518dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis        return "sampler";
5197e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT:
5207e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        return "renderpass";
5217e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT:
5227e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        return "device memory";
523eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT:
524eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis        return "semaphore";
525dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis    default:
526dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis        return "unknown";
527dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis    }
528dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis}
529dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis
530cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis// For given bound_object_handle, bound to given mem allocation, verify that the range for the bound object is valid
531f989de4217bce0f293121d0da53dc8328276370fTobin Ehlisstatic bool ValidateMemoryIsValid(layer_data *dev_data, VkDeviceMemory mem, uint64_t bound_object_handle,
532dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis                                  VkDebugReportObjectTypeEXT type, const char *functionName) {
533f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis    DEVICE_MEM_INFO *mem_info = getMemObjInfo(dev_data, mem);
534f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis    if (mem_info) {
535f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis        if (!mem_info->bound_ranges[bound_object_handle].valid) {
536f48a83f5b5548cd46a12770c7542ff902537ad3eKarl Schultz            return log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
537ea8e85ade623a09c601d939622cbd7740d8d66c9Tobin Ehlis                           reinterpret_cast<uint64_t &>(mem), __LINE__, MEMTRACK_INVALID_MEM_REGION, "MEM",
538dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis                           "%s: Cannot read invalid region of memory allocation 0x%" PRIx64 " for bound %s object 0x%" PRIx64
539dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis                           ", please fill the memory before using.",
540dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis                           functionName, reinterpret_cast<uint64_t &>(mem), object_type_to_string(type), bound_object_handle);
541f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis        }
542f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis    }
543f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis    return false;
544f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis}
545f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// For given image_node
546f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis//  If mem is special swapchain key, then verify that image_node valid member is true
547f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis//  Else verify that the image's bound memory range is valid
548f989de4217bce0f293121d0da53dc8328276370fTobin Ehlisstatic bool ValidateImageMemoryIsValid(layer_data *dev_data, IMAGE_NODE *image_node, const char *functionName) {
549f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis    if (image_node->mem == MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) {
550f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis        if (!image_node->valid) {
551f48a83f5b5548cd46a12770c7542ff902537ad3eKarl Schultz            return log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
552ea8e85ade623a09c601d939622cbd7740d8d66c9Tobin Ehlis                           reinterpret_cast<uint64_t &>(image_node->mem), __LINE__, MEMTRACK_INVALID_MEM_REGION, "MEM",
553414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                           "%s: Cannot read invalid swapchain image 0x%" PRIx64 ", please fill the memory before using.",
554f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis                           functionName, reinterpret_cast<uint64_t &>(image_node->image));
5555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
5565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
557dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis        return ValidateMemoryIsValid(dev_data, image_node->mem, reinterpret_cast<uint64_t &>(image_node->image),
558dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis                                     VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, functionName);
5595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return false;
5615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
562f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// For given buffer_node, verify that the range it's bound to is valid
563f989de4217bce0f293121d0da53dc8328276370fTobin Ehlisstatic bool ValidateBufferMemoryIsValid(layer_data *dev_data, BUFFER_NODE *buffer_node, const char *functionName) {
564dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis    return ValidateMemoryIsValid(dev_data, buffer_node->mem, reinterpret_cast<uint64_t &>(buffer_node->buffer),
565dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis                                 VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, functionName);
566f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis}
567f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// For the given memory allocation, set the range bound by the given handle object to the valid param value
568f989de4217bce0f293121d0da53dc8328276370fTobin Ehlisstatic void SetMemoryValid(layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, bool valid) {
569f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis    DEVICE_MEM_INFO *mem_info = getMemObjInfo(dev_data, mem);
570f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis    if (mem_info) {
571f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis        mem_info->bound_ranges[handle].valid = valid;
572f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis    }
573f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis}
574f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// For given image node
575f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis//  If mem is special swapchain key, then set entire image_node to valid param value
576f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis//  Else set the image's bound memory range to valid param value
577f989de4217bce0f293121d0da53dc8328276370fTobin Ehlisstatic void SetImageMemoryValid(layer_data *dev_data, IMAGE_NODE *image_node, bool valid) {
578f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis    if (image_node->mem == MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) {
579f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis        image_node->valid = valid;
5805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
581f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis        SetMemoryValid(dev_data, image_node->mem, reinterpret_cast<uint64_t &>(image_node->image), valid);
5825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
584f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// For given buffer node set the buffer's bound memory range to valid param value
585f989de4217bce0f293121d0da53dc8328276370fTobin Ehlisstatic void SetBufferMemoryValid(layer_data *dev_data, BUFFER_NODE *buffer_node, bool valid) {
586f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis    SetMemoryValid(dev_data, buffer_node->mem, reinterpret_cast<uint64_t &>(buffer_node->buffer), valid);
587f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis}
5885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Find CB Info and add mem reference to list container
5895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Find Mem Obj Info and add CB reference to list container
590e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool update_cmd_buf_and_mem_references(layer_data *dev_data, const VkCommandBuffer cb, const VkDeviceMemory mem,
591e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                                              const char *apiName) {
59283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
5935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Skip validation if this image was created through WSI
5955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (mem != MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) {
5965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // First update CB binding in MemObj mini CB list
59857fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis        DEVICE_MEM_INFO *pMemInfo = getMemObjInfo(dev_data, mem);
5995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (pMemInfo) {
600de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis            pMemInfo->command_buffer_bindings.insert(cb);
6015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // Now update CBInfo's Mem reference list
60272d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis            GLOBAL_CB_NODE *pCBNode = getCBNode(dev_data, cb);
6035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // TODO: keep track of all destroyed CBs so we know if this is a stale or simply invalid object
60472d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis            if (pCBNode) {
605c7196adb126cc3c77dc932e29193ca886532bac5Chris Forbes                pCBNode->memObjs.insert(mem);
6065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
6075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
6085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
60983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    return skip_call;
6105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
611ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis
61256f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis// Create binding link between given sampler and command buffer node
61356f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlisvoid AddCommandBufferBindingSampler(GLOBAL_CB_NODE *cb_node, SAMPLER_NODE *sampler_node) {
61456f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis    sampler_node->cb_bindings.insert(cb_node);
61556f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis    cb_node->object_bindings.insert({reinterpret_cast<uint64_t &>(sampler_node->sampler), VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT});
61656f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis}
61756f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis
61856f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis// Create binding link between given image node and command buffer node
619c3eda058338f7ba4e776ec74202b1c95ce6e6220Tobin Ehlisvoid AddCommandBufferBindingImage(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, IMAGE_NODE *img_node) {
620ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    // Skip validation if this image was created through WSI
621ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    if (img_node->mem != MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) {
622ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        // First update CB binding in MemObj mini CB list
623ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        DEVICE_MEM_INFO *pMemInfo = getMemObjInfo(dev_data, img_node->mem);
624ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        if (pMemInfo) {
625de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis            pMemInfo->command_buffer_bindings.insert(cb_node->commandBuffer);
626ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis            // Now update CBInfo's Mem reference list
627ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis            cb_node->memObjs.insert(img_node->mem);
628ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        }
629f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis        // Now update cb binding for image
630bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis        cb_node->object_bindings.insert({reinterpret_cast<uint64_t &>(img_node->image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT});
631f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis        img_node->cb_bindings.insert(cb_node);
632ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    }
633ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis}
634ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis
63503ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis// Create binding link between given image view node and its image with command buffer node
63603ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlisvoid AddCommandBufferBindingImageView(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, IMAGE_VIEW_STATE *view_state) {
63703ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis    // First add bindings for imageView
63803ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis    view_state->cb_bindings.insert(cb_node);
63903ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis    cb_node->object_bindings.insert(
64003ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis        {reinterpret_cast<uint64_t &>(view_state->image_view), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT});
641f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis    auto image_node = getImageNode(dev_data, view_state->create_info.image);
64203ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis    // Add bindings for image within imageView
64303ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis    if (image_node) {
64403ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis        AddCommandBufferBindingImage(dev_data, cb_node, image_node);
64503ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis    }
64603ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis}
64703ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis
648ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis// Create binding link between given buffer node and command buffer node
649c3eda058338f7ba4e776ec74202b1c95ce6e6220Tobin Ehlisvoid AddCommandBufferBindingBuffer(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, BUFFER_NODE *buff_node) {
650ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    // First update CB binding in MemObj mini CB list
651ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    DEVICE_MEM_INFO *pMemInfo = getMemObjInfo(dev_data, buff_node->mem);
652ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    if (pMemInfo) {
653de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        pMemInfo->command_buffer_bindings.insert(cb_node->commandBuffer);
654ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        // Now update CBInfo's Mem reference list
655ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        cb_node->memObjs.insert(buff_node->mem);
656bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis        cb_node->object_bindings.insert({reinterpret_cast<uint64_t &>(buff_node->buffer), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT});
657ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    }
658ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    // Now update cb binding for buffer
659ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    buff_node->cb_bindings.insert(cb_node);
660ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis}
661ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis
66277b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis// Create binding link between given buffer view node and its buffer with command buffer node
66377b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlisvoid AddCommandBufferBindingBufferView(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, BUFFER_VIEW_STATE *view_state) {
66477b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis    // First add bindings for bufferView
66577b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis    view_state->cb_bindings.insert(cb_node);
66677b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis    cb_node->object_bindings.insert(
66777b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis        {reinterpret_cast<uint64_t &>(view_state->buffer_view), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT});
66877b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis    auto buffer_node = getBufferNode(dev_data, view_state->create_info.buffer);
66977b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis    // Add bindings for buffer within bufferView
67077b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis    if (buffer_node) {
67177b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis        AddCommandBufferBindingBuffer(dev_data, cb_node, buffer_node);
67277b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis    }
67377b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis}
67477b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis
675400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis// For every mem obj bound to particular CB, free bindings related to that CB
676400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlisstatic void clear_cmd_buf_and_mem_references(layer_data *dev_data, GLOBAL_CB_NODE *pCBNode) {
67772d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis    if (pCBNode) {
678c7196adb126cc3c77dc932e29193ca886532bac5Chris Forbes        if (pCBNode->memObjs.size() > 0) {
679c7196adb126cc3c77dc932e29193ca886532bac5Chris Forbes            for (auto mem : pCBNode->memObjs) {
68057fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis                DEVICE_MEM_INFO *pInfo = getMemObjInfo(dev_data, mem);
6815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if (pInfo) {
682de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis                    pInfo->command_buffer_bindings.erase(pCBNode->commandBuffer);
6835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
6845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
685c7196adb126cc3c77dc932e29193ca886532bac5Chris Forbes            pCBNode->memObjs.clear();
6865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
68772d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis        pCBNode->validate_functions.clear();
6885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
6895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
690400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis// Overloaded call to above function when GLOBAL_CB_NODE has not already been looked-up
691400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlisstatic void clear_cmd_buf_and_mem_references(layer_data *dev_data, const VkCommandBuffer cb) {
692400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis    clear_cmd_buf_and_mem_references(dev_data, getCBNode(dev_data, cb));
6935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
6945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6951cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis// For given MemObjInfo, report Obj & CB bindings. Clear any object bindings.
6961cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlisstatic bool ReportMemReferencesAndCleanUp(layer_data *dev_data, DEVICE_MEM_INFO *pMemObjInfo) {
69783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
698de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis    size_t cmdBufRefCount = pMemObjInfo->command_buffer_bindings.size();
699de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis    size_t objRefCount = pMemObjInfo->obj_bindings.size();
7005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
701de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis    if ((pMemObjInfo->command_buffer_bindings.size()) != 0) {
70283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
70383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            (uint64_t)pMemObjInfo->mem, __LINE__, MEMTRACK_FREED_MEM_REF, "MEM",
70483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            "Attempting to free memory object 0x%" PRIxLEAST64 " which still contains " PRINTF_SIZE_T_SPECIFIER
70583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            " references",
70683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            (uint64_t)pMemObjInfo->mem, (cmdBufRefCount + objRefCount));
7075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
709de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis    if (cmdBufRefCount > 0 && pMemObjInfo->command_buffer_bindings.size() > 0) {
710de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        for (auto cb : pMemObjInfo->command_buffer_bindings) {
71158070a671b39e2058a799c7b9c932f3f03f2e66dTobin Ehlis            log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
712de886ba66b4535930eda3f737b1460bd62e1b2a5Chris Forbes                    (uint64_t)cb, __LINE__, MEMTRACK_FREED_MEM_REF, "MEM",
713414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                    "Command Buffer 0x%p still has a reference to mem obj 0x%" PRIxLEAST64, cb, (uint64_t)pMemObjInfo->mem);
7145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
7155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Clear the list of hanging references
716de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        pMemObjInfo->command_buffer_bindings.clear();
7175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
719de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis    if (objRefCount > 0 && pMemObjInfo->obj_bindings.size() > 0) {
720de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        for (auto obj : pMemObjInfo->obj_bindings) {
721896fc32d6f25e4bbe916bd27f2d5358d235840d4Chris Forbes            log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, obj.type, obj.handle, __LINE__,
722414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                    MEMTRACK_FREED_MEM_REF, "MEM", "VK Object 0x%" PRIxLEAST64 " still has a reference to mem obj 0x%" PRIxLEAST64,
723896fc32d6f25e4bbe916bd27f2d5358d235840d4Chris Forbes                    obj.handle, (uint64_t)pMemObjInfo->mem);
7241cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis            // Clear mem binding for bound objects
7251cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis            switch (obj.type) {
7261cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis            case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: {
7271cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis                auto image_node = getImageNode(dev_data, reinterpret_cast<VkImage &>(obj.handle));
7281cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis                assert(image_node); // Any destroyed images should already be removed from bindings
729888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                image_node->mem = MEMORY_UNBOUND;
7301cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis                break;
7311cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis            }
7321cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis            case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT: {
7331cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis                auto buff_node = getBufferNode(dev_data, reinterpret_cast<VkBuffer &>(obj.handle));
7341cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis                assert(buff_node); // Any destroyed buffers should already be removed from bindings
735888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                buff_node->mem = MEMORY_UNBOUND;
7361cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis                break;
7371cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis            }
7381cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis            default:
7391cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis                // Should only have buffer or image objects bound to memory
7401cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis                assert(0);
7411cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis            }
7425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
7435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Clear the list of hanging references
744de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        pMemObjInfo->obj_bindings.clear();
7455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
74683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    return skip_call;
7475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
7485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
749e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool freeMemObjInfo(layer_data *dev_data, void *object, VkDeviceMemory mem, bool internal) {
75083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
7515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Parse global list to find info w/ mem
75257fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis    DEVICE_MEM_INFO *pInfo = getMemObjInfo(dev_data, mem);
7535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pInfo) {
754ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        // TODO: Verify against Valid Use section
755ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        // Clear any CB bindings for completed CBs
756ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        //   TODO : Is there a better place to do this?
757ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller
758ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        assert(pInfo->object != VK_NULL_HANDLE);
759ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        // clear_cmd_buf_and_mem_references removes elements from
760de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        // pInfo->command_buffer_bindings -- this copy not needed in c++14,
761ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        // and probably not needed in practice in c++11
762de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        auto bindings = pInfo->command_buffer_bindings;
763ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        for (auto cb : bindings) {
764ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller            if (!dev_data->globalInFlightCmdBuffers.count(cb)) {
765ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller                clear_cmd_buf_and_mem_references(dev_data, cb);
7665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
767ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        }
7681cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis        // Now check for any remaining references to this mem obj and remove bindings
769de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        if (pInfo->command_buffer_bindings.size() || pInfo->obj_bindings.size()) {
7701cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis            skip_call |= ReportMemReferencesAndCleanUp(dev_data, pInfo);
7715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
772ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        // Delete mem obj info
773ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        dev_data->memObjMap.erase(dev_data->memObjMap.find(mem));
774ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller    } else if (VK_NULL_HANDLE != mem) {
775ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        // The request is to free an invalid, non-zero handle
776ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        skip_call = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
777ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller                            VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
778ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller                            reinterpret_cast<uint64_t &>(mem), __LINE__,
779ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller                            MEMTRACK_INVALID_MEM_OBJ,
780ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller                            "MEM", "Request to delete memory object 0x%"
781ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller                            PRIxLEAST64 " not present in memory Object Map",
782ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller                            reinterpret_cast<uint64_t &>(mem));
7835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
78483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    return skip_call;
7855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
7865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
7875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Remove object binding performs 3 tasks:
7885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// 1. Remove ObjectInfo from MemObjInfo list container of obj bindings & free it
789c025ba3a7a8ad299af93449fbc234b6631d6f9ebChris Forbes// 2. Clear mem binding for image/buffer by setting its handle to 0
7905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// TODO : This only applied to Buffer, Image, and Swapchain objects now, how should it be updated/customized?
7910a1ce3dfd81c9f4efbe46f5ba5ddaea70bc4aa61Chris Forbesstatic bool clear_object_binding(layer_data *dev_data, uint64_t handle, VkDebugReportObjectTypeEXT type) {
7925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TODO : Need to customize images/buffers/swapchains to track mem binding and clear it here appropriately
79383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
794888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis    VkDeviceMemory *pMemBinding = GetObjectMemBinding(dev_data, handle, type);
79594c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis    if (pMemBinding) {
79657fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis        DEVICE_MEM_INFO *pMemObjInfo = getMemObjInfo(dev_data, *pMemBinding);
7975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // TODO : Make sure this is a reasonable way to reset mem binding
79894c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis        *pMemBinding = VK_NULL_HANDLE;
7995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (pMemObjInfo) {
800c025ba3a7a8ad299af93449fbc234b6631d6f9ebChris Forbes            // This obj is bound to a memory object. Remove the reference to this object in that memory object's list,
8015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // and set the objects memory binding pointer to NULL.
802de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis            if (!pMemObjInfo->obj_bindings.erase({handle, type})) {
80383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                skip_call |=
80458070a671b39e2058a799c7b9c932f3f03f2e66dTobin Ehlis                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, type, handle, __LINE__, MEMTRACK_INVALID_OBJECT,
805414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                            "MEM", "While trying to clear mem binding for %s obj 0x%" PRIxLEAST64
806414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                   ", unable to find that object referenced by mem obj 0x%" PRIxLEAST64,
8075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            object_type_to_string(type), handle, (uint64_t)pMemObjInfo->mem);
8085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
8095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
8105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
81183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    return skip_call;
8125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
8135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
814888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis// For given mem object, verify that it is not null or UNBOUND, if it is, report error. Return skip value.
815888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlisbool VerifyBoundMemoryIsValid(const layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, const char *api_name,
816888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                              const char *type_name) {
817888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis    bool result = false;
818888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis    if (VK_NULL_HANDLE == mem) {
819888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis        result = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, handle,
820888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                         __LINE__, MEMTRACK_OBJECT_NOT_BOUND, "MEM",
821888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                         "%s: Vk%s object 0x%" PRIxLEAST64 " used with no memory bound. Memory should be bound by calling "
822888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                         "vkBind%sMemory().",
823888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                         api_name, type_name, handle, type_name);
824888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis    } else if (MEMORY_UNBOUND == mem) {
825888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis        result = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, handle,
826888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                         __LINE__, MEMTRACK_OBJECT_NOT_BOUND, "MEM",
827888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                         "%s: Vk%s object 0x%" PRIxLEAST64 " used with no memory bound and previously bound memory was freed. "
828888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                         "Memory must not be freed prior to this operation.",
829888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                         api_name, type_name, handle);
830888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis    }
831888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis    return result;
832888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis}
833888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis
834b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski// Check to see if memory was ever bound to this image
835694002f8c182c84fc2b670f1cbb1a838119b1c14Tobin Ehlisbool ValidateMemoryIsBoundToImage(const layer_data *dev_data, const IMAGE_NODE *image_node, const char *api_name) {
836b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski    bool result = false;
837b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski    if (0 == (static_cast<uint32_t>(image_node->createInfo.flags) & VK_IMAGE_CREATE_SPARSE_BINDING_BIT)) {
838888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis        result = VerifyBoundMemoryIsValid(dev_data, image_node->mem, reinterpret_cast<const uint64_t &>(image_node->image),
839888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                                          api_name, "Image");
840b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski    }
841b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski    return result;
842b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski}
843b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski
844b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski// Check to see if memory was bound to this buffer
845694002f8c182c84fc2b670f1cbb1a838119b1c14Tobin Ehlisbool ValidateMemoryIsBoundToBuffer(const layer_data *dev_data, const BUFFER_NODE *buffer_node, const char *api_name) {
846b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski    bool result = false;
84712e3a5f6e672b103f705424595ffe3c4687492ceTobin Ehlis    if (0 == (static_cast<uint32_t>(buffer_node->createInfo.flags) & VK_BUFFER_CREATE_SPARSE_BINDING_BIT)) {
848888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis        result = VerifyBoundMemoryIsValid(dev_data, buffer_node->mem, reinterpret_cast<const uint64_t &>(buffer_node->buffer),
849888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                                          api_name, "Buffer");
850b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski    }
851b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski    return result;
852b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski}
853b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski
8545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// For NULL mem case, output warning
8555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Make sure given object is in global object map
8565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//  IF a previous binding existed, output validation error
8575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//  Otherwise, add reference from objectInfo to memoryInfo
8585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//  Add reference off of objInfo
859888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlisstatic bool SetMemBinding(layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, VkDebugReportObjectTypeEXT type,
860888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                          const char *apiName) {
86183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
8625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Handle NULL case separately, just clear previous binding & decrement reference
8635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (mem == VK_NULL_HANDLE) {
86483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, type, handle, __LINE__, MEMTRACK_INVALID_MEM_OBJ,
86583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            "MEM", "In %s, attempting to Bind Obj(0x%" PRIxLEAST64 ") to NULL", apiName, handle);
8665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
867888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis        bool sparse = false;
868888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis        VkDeviceMemory *mem_binding = GetObjectMemBinding(dev_data, handle, type, &sparse);
869888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis        assert(mem_binding);
870888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis        DEVICE_MEM_INFO *mem_info = getMemObjInfo(dev_data, mem);
871888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis        if (mem_info) {
872888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis            DEVICE_MEM_INFO *prev_binding = getMemObjInfo(dev_data, *mem_binding);
873888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis            if (prev_binding) {
874888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                skip_call |=
875888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
876888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                            reinterpret_cast<uint64_t &>(mem), __LINE__, MEMTRACK_REBIND_OBJECT, "MEM",
877888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                            "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64
878888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                            ") which has already been bound to mem object 0x%" PRIxLEAST64,
879888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                            apiName, reinterpret_cast<uint64_t &>(mem), handle, reinterpret_cast<uint64_t &>(prev_binding->mem));
880888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis            } else if ((*mem_binding == MEMORY_UNBOUND) && (!sparse)) {
881888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                skip_call |=
882888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
883888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                            reinterpret_cast<uint64_t &>(mem), __LINE__, MEMTRACK_REBIND_OBJECT, "MEM",
884888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                            "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64
885888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                            ") which was previous bound to memory that has since been freed. Memory bindings are immutable in "
886888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                            "Vulkan so this attempt to bind to new memory is not allowed.",
887888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                            apiName, reinterpret_cast<uint64_t &>(mem), handle);
8882e415b757c1e43fda35311aad026af8d5c96681cTobin Ehlis            } else {
889888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                mem_info->obj_bindings.insert({handle, type});
8902e415b757c1e43fda35311aad026af8d5c96681cTobin Ehlis                // For image objects, make sure default memory state is correctly set
8912e415b757c1e43fda35311aad026af8d5c96681cTobin Ehlis                // TODO : What's the best/correct way to handle this?
8922e415b757c1e43fda35311aad026af8d5c96681cTobin Ehlis                if (VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT == type) {
8936d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis                    auto const image_node = getImageNode(dev_data, VkImage(handle));
8946d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis                    if (image_node) {
8956d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis                        VkImageCreateInfo ici = image_node->createInfo;
8962e415b757c1e43fda35311aad026af8d5c96681cTobin Ehlis                        if (ici.usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
8972e415b757c1e43fda35311aad026af8d5c96681cTobin Ehlis                            // TODO::  More memory state transition stuff.
8985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        }
8995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
9005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
901888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis                *mem_binding = mem;
9025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
9035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
9045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
90583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    return skip_call;
9065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
9075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
9085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// For NULL mem case, clear any previous binding Else...
9095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Make sure given object is in its object map
9105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//  IF a previous binding existed, update binding
9115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//  Add reference from objectInfo to memoryInfo
9125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//  Add reference off of object's binding info
9130a1ce3dfd81c9f4efbe46f5ba5ddaea70bc4aa61Chris Forbes// Return VK_TRUE if addition is successful, VK_FALSE otherwise
9140a1ce3dfd81c9f4efbe46f5ba5ddaea70bc4aa61Chris Forbesstatic bool set_sparse_mem_binding(layer_data *dev_data, VkDeviceMemory mem, uint64_t handle,
9150a1ce3dfd81c9f4efbe46f5ba5ddaea70bc4aa61Chris Forbes                                       VkDebugReportObjectTypeEXT type, const char *apiName) {
91683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = VK_FALSE;
9175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Handle NULL case separately, just clear previous binding & decrement reference
9185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (mem == VK_NULL_HANDLE) {
91983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call = clear_object_binding(dev_data, handle, type);
9205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
921888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis        VkDeviceMemory *pMemBinding = GetObjectMemBinding(dev_data, handle, type);
9222e415b757c1e43fda35311aad026af8d5c96681cTobin Ehlis        assert(pMemBinding);
92357fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis        DEVICE_MEM_INFO *pInfo = getMemObjInfo(dev_data, mem);
9242e415b757c1e43fda35311aad026af8d5c96681cTobin Ehlis        if (pInfo) {
925de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis            pInfo->obj_bindings.insert({handle, type});
9262e415b757c1e43fda35311aad026af8d5c96681cTobin Ehlis            // Need to set mem binding for this object
9272e415b757c1e43fda35311aad026af8d5c96681cTobin Ehlis            *pMemBinding = mem;
9285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
9295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
93083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    return skip_call;
9315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
9325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
933caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis// For handle of given object type, return memory binding
934caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlisstatic bool get_mem_for_type(layer_data *dev_data, uint64_t handle, VkDebugReportObjectTypeEXT type, VkDeviceMemory *mem) {
935caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis    bool skip_call = false;
9365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    *mem = VK_NULL_HANDLE;
937caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis    switch (type) {
938caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT:
939caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis        *mem = getImageNode(dev_data, VkImage(handle))->mem;
940caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis        break;
941caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT:
942caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis        *mem = getBufferNode(dev_data, VkBuffer(handle))->mem;
943caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis        break;
944caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis    default:
945caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis        assert(0);
9465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
947caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis    if (!*mem) {
948caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis        skip_call = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, type, handle, __LINE__, MEMTRACK_INVALID_OBJECT,
949caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis                            "MEM", "Trying to get mem binding for %s object 0x%" PRIxLEAST64
950caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis                                   " but binding is NULL. Has memory been bound to this object?",
951caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis                            object_type_to_string(type), handle);
952caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis    }
953caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis    return skip_call;
954caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis}
955caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis
9565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Print details of MemObjInfo list
9570a1ce3dfd81c9f4efbe46f5ba5ddaea70bc4aa61Chris Forbesstatic void print_mem_list(layer_data *dev_data) {
9585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Early out if info is not requested
95958070a671b39e2058a799c7b9c932f3f03f2e66dTobin Ehlis    if (!(dev_data->report_data->active_flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT)) {
9605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return;
9615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
9625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
9635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Just printing each msg individually for now, may want to package these into single large print
96458070a671b39e2058a799c7b9c932f3f03f2e66dTobin Ehlis    log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0, __LINE__,
9655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            MEMTRACK_NONE, "MEM", "Details of Memory Object list (of size " PRINTF_SIZE_T_SPECIFIER " elements)",
96658070a671b39e2058a799c7b9c932f3f03f2e66dTobin Ehlis            dev_data->memObjMap.size());
96758070a671b39e2058a799c7b9c932f3f03f2e66dTobin Ehlis    log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0, __LINE__,
9685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            MEMTRACK_NONE, "MEM", "=============================");
9695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
97058070a671b39e2058a799c7b9c932f3f03f2e66dTobin Ehlis    if (dev_data->memObjMap.size() <= 0)
9715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return;
9725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
97358070a671b39e2058a799c7b9c932f3f03f2e66dTobin Ehlis    for (auto ii = dev_data->memObjMap.begin(); ii != dev_data->memObjMap.end(); ++ii) {
97457fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis        auto mem_info = (*ii).second.get();
9755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
97658070a671b39e2058a799c7b9c932f3f03f2e66dTobin Ehlis        log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0,
97757fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis                __LINE__, MEMTRACK_NONE, "MEM", "    ===MemObjInfo at 0x%p===", (void *)mem_info);
97858070a671b39e2058a799c7b9c932f3f03f2e66dTobin Ehlis        log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0,
97957fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis                __LINE__, MEMTRACK_NONE, "MEM", "    Mem object: 0x%" PRIxLEAST64, (uint64_t)(mem_info->mem));
98058070a671b39e2058a799c7b9c932f3f03f2e66dTobin Ehlis        log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0,
981c025ba3a7a8ad299af93449fbc234b6631d6f9ebChris Forbes                __LINE__, MEMTRACK_NONE, "MEM", "    Ref Count: " PRINTF_SIZE_T_SPECIFIER,
982de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis                mem_info->command_buffer_bindings.size() + mem_info->obj_bindings.size());
983de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        if (0 != mem_info->alloc_info.allocationSize) {
984de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis            string pAllocInfoMsg = vk_print_vkmemoryallocateinfo(&mem_info->alloc_info, "MEM(INFO):         ");
98558070a671b39e2058a799c7b9c932f3f03f2e66dTobin Ehlis            log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0,
9865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    __LINE__, MEMTRACK_NONE, "MEM", "    Mem Alloc info:\n%s", pAllocInfoMsg.c_str());
9875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
98858070a671b39e2058a799c7b9c932f3f03f2e66dTobin Ehlis            log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0,
9895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    __LINE__, MEMTRACK_NONE, "MEM", "    Mem Alloc info is NULL (alloc done by vkCreateSwapchainKHR())");
9905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
9915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
99258070a671b39e2058a799c7b9c932f3f03f2e66dTobin Ehlis        log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0,
9935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                __LINE__, MEMTRACK_NONE, "MEM", "    VK OBJECT Binding list of size " PRINTF_SIZE_T_SPECIFIER " elements:",
994de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis                mem_info->obj_bindings.size());
995de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        if (mem_info->obj_bindings.size() > 0) {
996de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis            for (auto obj : mem_info->obj_bindings) {
99758070a671b39e2058a799c7b9c932f3f03f2e66dTobin Ehlis                log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
998414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        0, __LINE__, MEMTRACK_NONE, "MEM", "       VK OBJECT 0x%" PRIx64, obj.handle);
9995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
10005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
10015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
100258070a671b39e2058a799c7b9c932f3f03f2e66dTobin Ehlis        log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0,
10035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                __LINE__, MEMTRACK_NONE, "MEM",
10045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                "    VK Command Buffer (CB) binding list of size " PRINTF_SIZE_T_SPECIFIER " elements",
1005de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis                mem_info->command_buffer_bindings.size());
1006de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        if (mem_info->command_buffer_bindings.size() > 0) {
1007de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis            for (auto cb : mem_info->command_buffer_bindings) {
100858070a671b39e2058a799c7b9c932f3f03f2e66dTobin Ehlis                log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
1009414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        0, __LINE__, MEMTRACK_NONE, "MEM", "      VK CB 0x%p", cb);
10105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
10115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
10125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
10135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
10145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
10150a1ce3dfd81c9f4efbe46f5ba5ddaea70bc4aa61Chris Forbesstatic void printCBList(layer_data *my_data) {
101672d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis    GLOBAL_CB_NODE *pCBInfo = NULL;
10175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
10185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Early out if info is not requested
10195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (!(my_data->report_data->active_flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT)) {
10205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return;
10215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
10225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
10235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    log_msg(my_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0, __LINE__,
102472d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis            MEMTRACK_NONE, "MEM", "Details of CB list (of size " PRINTF_SIZE_T_SPECIFIER " elements)",
102572d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis            my_data->commandBufferMap.size());
10265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    log_msg(my_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0, __LINE__,
10275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            MEMTRACK_NONE, "MEM", "==================");
10285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
102972d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis    if (my_data->commandBufferMap.size() <= 0)
10305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return;
10315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
103272d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis    for (auto &cb_node : my_data->commandBufferMap) {
103372d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis        pCBInfo = cb_node.second;
10345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
10355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        log_msg(my_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0,
1036414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                __LINE__, MEMTRACK_NONE, "MEM", "    CB Info (0x%p) has CB 0x%p", (void *)pCBInfo, (void *)pCBInfo->commandBuffer);
10375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1038c7196adb126cc3c77dc932e29193ca886532bac5Chris Forbes        if (pCBInfo->memObjs.size() <= 0)
10395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            continue;
1040c7196adb126cc3c77dc932e29193ca886532bac5Chris Forbes        for (auto obj : pCBInfo->memObjs) {
10415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            log_msg(my_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0,
1042414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                    __LINE__, MEMTRACK_NONE, "MEM", "      Mem obj 0x%" PRIx64, (uint64_t)obj);
10435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
10445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
10455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
10465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
10475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Return a string representation of CMD_TYPE enum
10485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic string cmdTypeToString(CMD_TYPE cmd) {
10495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    switch (cmd) {
10505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_BINDPIPELINE:
10515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_BINDPIPELINE";
10525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_BINDPIPELINEDELTA:
10535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_BINDPIPELINEDELTA";
10545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_SETVIEWPORTSTATE:
10555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_SETVIEWPORTSTATE";
10565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_SETLINEWIDTHSTATE:
10575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_SETLINEWIDTHSTATE";
10585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_SETDEPTHBIASSTATE:
10595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_SETDEPTHBIASSTATE";
10605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_SETBLENDSTATE:
10615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_SETBLENDSTATE";
10625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_SETDEPTHBOUNDSSTATE:
10635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_SETDEPTHBOUNDSSTATE";
10645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_SETSTENCILREADMASKSTATE:
10655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_SETSTENCILREADMASKSTATE";
10665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_SETSTENCILWRITEMASKSTATE:
10675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_SETSTENCILWRITEMASKSTATE";
10685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_SETSTENCILREFERENCESTATE:
10695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_SETSTENCILREFERENCESTATE";
10705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_BINDDESCRIPTORSETS:
10715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_BINDDESCRIPTORSETS";
10725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_BINDINDEXBUFFER:
10735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_BINDINDEXBUFFER";
10745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_BINDVERTEXBUFFER:
10755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_BINDVERTEXBUFFER";
10765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_DRAW:
10775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_DRAW";
10785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_DRAWINDEXED:
10795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_DRAWINDEXED";
10805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_DRAWINDIRECT:
10815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_DRAWINDIRECT";
10825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_DRAWINDEXEDINDIRECT:
10835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_DRAWINDEXEDINDIRECT";
10845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_DISPATCH:
10855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_DISPATCH";
10865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_DISPATCHINDIRECT:
10875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_DISPATCHINDIRECT";
10885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_COPYBUFFER:
10895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_COPYBUFFER";
10905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_COPYIMAGE:
10915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_COPYIMAGE";
10925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_BLITIMAGE:
10935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_BLITIMAGE";
10945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_COPYBUFFERTOIMAGE:
10955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_COPYBUFFERTOIMAGE";
10965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_COPYIMAGETOBUFFER:
10975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_COPYIMAGETOBUFFER";
10985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_CLONEIMAGEDATA:
10995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_CLONEIMAGEDATA";
11005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_UPDATEBUFFER:
11015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_UPDATEBUFFER";
11025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_FILLBUFFER:
11035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_FILLBUFFER";
11045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_CLEARCOLORIMAGE:
11055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_CLEARCOLORIMAGE";
11065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_CLEARATTACHMENTS:
11075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_CLEARCOLORATTACHMENT";
11085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_CLEARDEPTHSTENCILIMAGE:
11095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_CLEARDEPTHSTENCILIMAGE";
11105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_RESOLVEIMAGE:
11115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_RESOLVEIMAGE";
11125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_SETEVENT:
11135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_SETEVENT";
11145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_RESETEVENT:
11155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_RESETEVENT";
11165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_WAITEVENTS:
11175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_WAITEVENTS";
11185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_PIPELINEBARRIER:
11195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_PIPELINEBARRIER";
11205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_BEGINQUERY:
11215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_BEGINQUERY";
11225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_ENDQUERY:
11235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_ENDQUERY";
11245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_RESETQUERYPOOL:
11255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_RESETQUERYPOOL";
11265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_COPYQUERYPOOLRESULTS:
11275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_COPYQUERYPOOLRESULTS";
11285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_WRITETIMESTAMP:
11295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_WRITETIMESTAMP";
11305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_INITATOMICCOUNTERS:
11315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_INITATOMICCOUNTERS";
11325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_LOADATOMICCOUNTERS:
11335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_LOADATOMICCOUNTERS";
11345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_SAVEATOMICCOUNTERS:
11355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_SAVEATOMICCOUNTERS";
11365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_BEGINRENDERPASS:
11375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_BEGINRENDERPASS";
11385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case CMD_ENDRENDERPASS:
11395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "CMD_ENDRENDERPASS";
11405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    default:
11415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "UNKNOWN";
11425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
11435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
11445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
11455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// SPIRV utility functions
11465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic void build_def_index(shader_module *module) {
11475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (auto insn : *module) {
11485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        switch (insn.opcode()) {
11495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        /* Types */
11505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpTypeVoid:
11515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpTypeBool:
11525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpTypeInt:
11535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpTypeFloat:
11545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpTypeVector:
11555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpTypeMatrix:
11565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpTypeImage:
11575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpTypeSampler:
11585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpTypeSampledImage:
11595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpTypeArray:
11605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpTypeRuntimeArray:
11615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpTypeStruct:
11625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpTypeOpaque:
11635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpTypePointer:
11645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpTypeFunction:
11655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpTypeEvent:
11665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpTypeDeviceEvent:
11675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpTypeReserveId:
11685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpTypeQueue:
11695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpTypePipe:
11705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            module->def_index[insn.word(1)] = insn.offset();
11715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            break;
11725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
11735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        /* Fixed constants */
11745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpConstantTrue:
11755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpConstantFalse:
11765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpConstant:
11775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpConstantComposite:
11785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpConstantSampler:
11795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpConstantNull:
11805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            module->def_index[insn.word(2)] = insn.offset();
11815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            break;
11825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
11835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        /* Specialization constants */
11845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpSpecConstantTrue:
11855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpSpecConstantFalse:
11865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpSpecConstant:
11875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpSpecConstantComposite:
11885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpSpecConstantOp:
11895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            module->def_index[insn.word(2)] = insn.offset();
11905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            break;
11915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
11925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        /* Variables */
11935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpVariable:
11945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            module->def_index[insn.word(2)] = insn.offset();
11955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            break;
11965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
11975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        /* Functions */
11985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpFunction:
11995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            module->def_index[insn.word(2)] = insn.offset();
12005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            break;
12015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
12025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        default:
12035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            /* We don't care about any other defs for now. */
12045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            break;
12055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
12065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
12075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
12085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
12095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic spirv_inst_iter find_entrypoint(shader_module *src, char const *name, VkShaderStageFlagBits stageBits) {
12105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (auto insn : *src) {
12115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (insn.opcode() == spv::OpEntryPoint) {
12125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            auto entrypointName = (char const *)&insn.word(3);
12135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            auto entrypointStageBits = 1u << insn.word(1);
12145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
12155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (!strcmp(entrypointName, name) && (entrypointStageBits & stageBits)) {
12165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                return insn;
12175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
12185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
12195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
12205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
12215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return src->end();
12225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
12235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
12245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic char const *storage_class_name(unsigned sc) {
12255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    switch (sc) {
12265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::StorageClassInput:
12275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "input";
12285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::StorageClassOutput:
12295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "output";
12305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::StorageClassUniformConstant:
12315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "const uniform";
12325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::StorageClassUniform:
12335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "uniform";
12345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::StorageClassWorkgroup:
12355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "workgroup local";
12365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::StorageClassCrossWorkgroup:
12375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "workgroup global";
12385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::StorageClassPrivate:
12395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "private global";
12405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::StorageClassFunction:
12415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "function";
12425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::StorageClassGeneric:
12435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "generic";
12445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::StorageClassAtomicCounter:
12455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "atomic counter";
12465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::StorageClassImage:
12475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "image";
12485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::StorageClassPushConstant:
12495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "push constant";
12505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    default:
12515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return "unknown";
12525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
12535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
12545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
12555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis/* get the value of an integral constant */
12565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisunsigned get_constant_value(shader_module const *src, unsigned id) {
12575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    auto value = src->get_def(id);
12585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    assert(value != src->end());
12595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
12605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (value.opcode() != spv::OpConstant) {
12615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        /* TODO: Either ensure that the specialization transform is already performed on a module we're
12625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            considering here, OR -- specialize on the fly now.
12635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            */
12645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return 1;
12655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
12665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
12675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return value.word(3);
12685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
12695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
12709ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes
12719ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbesstatic void describe_type_inner(std::ostringstream &ss, shader_module const *src, unsigned type) {
12725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    auto insn = src->get_def(type);
12735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    assert(insn != src->end());
12745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
12755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    switch (insn.opcode()) {
12765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeBool:
12779ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        ss << "bool";
12789ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        break;
12795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeInt:
12809ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        ss << (insn.word(3) ? 's' : 'u') << "int" << insn.word(2);
12819ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        break;
12825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeFloat:
12839ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        ss << "float" << insn.word(2);
12849ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        break;
12855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeVector:
12869ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        ss << "vec" << insn.word(3) << " of ";
12879ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        describe_type_inner(ss, src, insn.word(2));
12889ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        break;
12895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeMatrix:
12909ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        ss << "mat" << insn.word(3) << " of ";
12919ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        describe_type_inner(ss, src, insn.word(2));
12929ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        break;
12935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeArray:
12949ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        ss << "arr[" << get_constant_value(src, insn.word(3)) << "] of ";
12959ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        describe_type_inner(ss, src, insn.word(2));
12969ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        break;
12975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypePointer:
12989ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        ss << "ptr to " << storage_class_name(insn.word(2)) << " ";
12999ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        describe_type_inner(ss, src, insn.word(3));
13009ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        break;
13015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeStruct: {
13029ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        ss << "struct of (";
13035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (unsigned i = 2; i < insn.len(); i++) {
13049ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes            describe_type_inner(ss, src, insn.word(i));
13059ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes            if (i == insn.len() - 1) {
13069ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes                ss << ")";
13079ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes            } else {
13089ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes                ss << ", ";
13099ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes            }
13105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
13119ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        break;
13125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
13135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeSampler:
13149ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        ss << "sampler";
13159ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        break;
13165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeSampledImage:
13179ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        ss << "sampler+";
13189ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        describe_type_inner(ss, src, insn.word(2));
13199ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        break;
13205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeImage:
13219ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        ss << "image(dim=" << insn.word(3) << ", sampled=" << insn.word(7) << ")";
13229ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        break;
13235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    default:
13249ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        ss << "oddtype";
13259ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes        break;
13265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
13275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
13285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
13299ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes
13309ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbesstatic std::string describe_type(shader_module const *src, unsigned type) {
13319ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes    std::ostringstream ss;
13329ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes    describe_type_inner(ss, src, type);
13339ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes    return ss.str();
13349ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes}
13359ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes
13369ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes
133737576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbesstatic bool is_narrow_numeric_type(spirv_inst_iter type)
133837576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes{
133937576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes    if (type.opcode() != spv::OpTypeInt && type.opcode() != spv::OpTypeFloat)
134037576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes        return false;
134137576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes    return type.word(2) < 64;
134237576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes}
134337576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes
134437576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes
134537576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbesstatic bool types_match(shader_module const *a, shader_module const *b, unsigned a_type, unsigned b_type, bool a_arrayed, bool b_arrayed, bool relaxed) {
13465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    /* walk two type trees together, and complain about differences */
13475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    auto a_insn = a->get_def(a_type);
13485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    auto b_insn = b->get_def(b_type);
13495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    assert(a_insn != a->end());
13505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    assert(b_insn != b->end());
13515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
13527c755c8aca6857046df9516d8336416165969cb9Chris Forbes    if (a_arrayed && a_insn.opcode() == spv::OpTypeArray) {
135337576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes        return types_match(a, b, a_insn.word(2), b_type, false, b_arrayed, relaxed);
13547c755c8aca6857046df9516d8336416165969cb9Chris Forbes    }
13557c755c8aca6857046df9516d8336416165969cb9Chris Forbes
13565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (b_arrayed && b_insn.opcode() == spv::OpTypeArray) {
13575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        /* we probably just found the extra level of arrayness in b_type: compare the type inside it to a_type */
135837576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes        return types_match(a, b, a_type, b_insn.word(2), a_arrayed, false, relaxed);
135937576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes    }
136037576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes
136137576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes    if (a_insn.opcode() == spv::OpTypeVector && relaxed && is_narrow_numeric_type(b_insn)) {
136237576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes        return types_match(a, b, a_insn.word(2), b_type, a_arrayed, b_arrayed, false);
13635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
13645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
13655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (a_insn.opcode() != b_insn.opcode()) {
13665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return false;
13675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
13685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
13697c755c8aca6857046df9516d8336416165969cb9Chris Forbes    if (a_insn.opcode() == spv::OpTypePointer) {
13707c755c8aca6857046df9516d8336416165969cb9Chris Forbes        /* match on pointee type. storage class is expected to differ */
137137576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes        return types_match(a, b, a_insn.word(3), b_insn.word(3), a_arrayed, b_arrayed, relaxed);
13727c755c8aca6857046df9516d8336416165969cb9Chris Forbes    }
13737c755c8aca6857046df9516d8336416165969cb9Chris Forbes
13747c755c8aca6857046df9516d8336416165969cb9Chris Forbes    if (a_arrayed || b_arrayed) {
13757c755c8aca6857046df9516d8336416165969cb9Chris Forbes        /* if we havent resolved array-of-verts by here, we're not going to. */
13767c755c8aca6857046df9516d8336416165969cb9Chris Forbes        return false;
13777c755c8aca6857046df9516d8336416165969cb9Chris Forbes    }
13787c755c8aca6857046df9516d8336416165969cb9Chris Forbes
13795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    switch (a_insn.opcode()) {
13805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeBool:
13817c755c8aca6857046df9516d8336416165969cb9Chris Forbes        return true;
13825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeInt:
13835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        /* match on width, signedness */
13847c755c8aca6857046df9516d8336416165969cb9Chris Forbes        return a_insn.word(2) == b_insn.word(2) && a_insn.word(3) == b_insn.word(3);
13855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeFloat:
13865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        /* match on width */
13877c755c8aca6857046df9516d8336416165969cb9Chris Forbes        return a_insn.word(2) == b_insn.word(2);
13885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeVector:
138937576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes        /* match on element type, count. */
139037576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes        if (!types_match(a, b, a_insn.word(2), b_insn.word(2), a_arrayed, b_arrayed, false))
139137576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes            return false;
139237576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes        if (relaxed && is_narrow_numeric_type(a->get_def(a_insn.word(2)))) {
139337576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes            return a_insn.word(3) >= b_insn.word(3);
139437576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes        }
139537576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes        else {
139637576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes            return a_insn.word(3) == b_insn.word(3);
139737576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes        }
13985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeMatrix:
139937576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes        /* match on element type, count. */
140037576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes        return types_match(a, b, a_insn.word(2), b_insn.word(2), a_arrayed, b_arrayed, false) && a_insn.word(3) == b_insn.word(3);
14015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeArray:
14025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        /* match on element type, count. these all have the same layout. we don't get here if
14035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis         * b_arrayed. This differs from vector & matrix types in that the array size is the id of a constant instruction,
14045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis         * not a literal within OpTypeArray */
140537576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes        return types_match(a, b, a_insn.word(2), b_insn.word(2), a_arrayed, b_arrayed, false) &&
14065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis               get_constant_value(a, a_insn.word(3)) == get_constant_value(b, b_insn.word(3));
14075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeStruct:
14085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        /* match on all element types */
14095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        {
14105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (a_insn.len() != b_insn.len()) {
14115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                return false; /* structs cannot match if member counts differ */
14125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
14135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
14145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            for (unsigned i = 2; i < a_insn.len(); i++) {
141537576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes                if (!types_match(a, b, a_insn.word(i), b_insn.word(i), a_arrayed, b_arrayed, false)) {
14165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    return false;
14175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
14185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
14195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
14205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            return true;
14215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
14225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    default:
14235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        /* remaining types are CLisms, or may not appear in the interfaces we
14245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis         * are interested in. Just claim no match.
14255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis         */
14265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return false;
14275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
14285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
14295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
14305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic int value_or_default(std::unordered_map<unsigned, unsigned> const &map, unsigned id, int def) {
14315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    auto it = map.find(id);
14325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (it == map.end())
14335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return def;
14345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    else
14355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return it->second;
14365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
14375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
14385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic unsigned get_locations_consumed_by_type(shader_module const *src, unsigned type, bool strip_array_level) {
14395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    auto insn = src->get_def(type);
14405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    assert(insn != src->end());
14415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
14425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    switch (insn.opcode()) {
14435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypePointer:
14445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        /* see through the ptr -- this is only ever at the toplevel for graphics shaders;
14455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis         * we're never actually passing pointers around. */
14465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return get_locations_consumed_by_type(src, insn.word(3), strip_array_level);
14475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeArray:
14485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (strip_array_level) {
14495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            return get_locations_consumed_by_type(src, insn.word(2), false);
14505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
14515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            return get_constant_value(src, insn.word(3)) * get_locations_consumed_by_type(src, insn.word(2), false);
14525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
14535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeMatrix:
14545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        /* num locations is the dimension * element size */
14555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return insn.word(3) * get_locations_consumed_by_type(src, insn.word(2), false);
1456cc52143fc093e1e62d2dacc4abc3966e04b6f6d6Chris Forbes    case spv::OpTypeVector: {
1457cc52143fc093e1e62d2dacc4abc3966e04b6f6d6Chris Forbes        auto scalar_type = src->get_def(insn.word(2));
1458cc52143fc093e1e62d2dacc4abc3966e04b6f6d6Chris Forbes        auto bit_width = (scalar_type.opcode() == spv::OpTypeInt || scalar_type.opcode() == spv::OpTypeFloat) ?
1459cc52143fc093e1e62d2dacc4abc3966e04b6f6d6Chris Forbes            scalar_type.word(2) : 32;
1460cc52143fc093e1e62d2dacc4abc3966e04b6f6d6Chris Forbes
1461cc52143fc093e1e62d2dacc4abc3966e04b6f6d6Chris Forbes        /* locations are 128-bit wide; 3- and 4-component vectors of 64 bit
1462cc52143fc093e1e62d2dacc4abc3966e04b6f6d6Chris Forbes         * types require two. */
1463cc52143fc093e1e62d2dacc4abc3966e04b6f6d6Chris Forbes        return (bit_width * insn.word(3) + 127) / 128;
1464cc52143fc093e1e62d2dacc4abc3966e04b6f6d6Chris Forbes    }
14655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    default:
14665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        /* everything else is just 1. */
14675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return 1;
14685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
14695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        /* TODO: extend to handle 64bit scalar types, whose vectors may need
14705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis         * multiple locations. */
14715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
14725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
14735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1474c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbesstatic unsigned get_locations_consumed_by_format(VkFormat format) {
1475c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes    switch (format) {
1476c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes    case VK_FORMAT_R64G64B64A64_SFLOAT:
1477c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes    case VK_FORMAT_R64G64B64A64_SINT:
1478c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes    case VK_FORMAT_R64G64B64A64_UINT:
1479c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes    case VK_FORMAT_R64G64B64_SFLOAT:
1480c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes    case VK_FORMAT_R64G64B64_SINT:
1481c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes    case VK_FORMAT_R64G64B64_UINT:
1482c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes        return 2;
1483c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes    default:
1484c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes        return 1;
1485c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes    }
1486c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes}
1487c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes
14885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlistypedef std::pair<unsigned, unsigned> location_t;
14895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlistypedef std::pair<unsigned, unsigned> descriptor_slot_t;
14905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
14915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstruct interface_var {
14925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t id;
14935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t type_id;
14945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t offset;
1495b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes    bool is_patch;
1496fff9393206f66a154438e16fa0562c989f425498Chris Forbes    bool is_block_member;
14975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    /* TODO: collect the name, too? Isn't required to be present. */
14985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis};
14995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1500031261d21af8907953dd763398ce9a23e65b8749Chris Forbesstruct shader_stage_attributes {
1501031261d21af8907953dd763398ce9a23e65b8749Chris Forbes    char const *const name;
1502031261d21af8907953dd763398ce9a23e65b8749Chris Forbes    bool arrayed_input;
1503031261d21af8907953dd763398ce9a23e65b8749Chris Forbes    bool arrayed_output;
1504031261d21af8907953dd763398ce9a23e65b8749Chris Forbes};
1505031261d21af8907953dd763398ce9a23e65b8749Chris Forbes
1506031261d21af8907953dd763398ce9a23e65b8749Chris Forbesstatic shader_stage_attributes shader_stage_attribs[] = {
1507031261d21af8907953dd763398ce9a23e65b8749Chris Forbes    {"vertex shader", false, false},
1508031261d21af8907953dd763398ce9a23e65b8749Chris Forbes    {"tessellation control shader", true, true},
1509031261d21af8907953dd763398ce9a23e65b8749Chris Forbes    {"tessellation evaluation shader", true, false},
1510031261d21af8907953dd763398ce9a23e65b8749Chris Forbes    {"geometry shader", true, false},
1511031261d21af8907953dd763398ce9a23e65b8749Chris Forbes    {"fragment shader", false, false},
1512031261d21af8907953dd763398ce9a23e65b8749Chris Forbes};
1513031261d21af8907953dd763398ce9a23e65b8749Chris Forbes
15145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic spirv_inst_iter get_struct_type(shader_module const *src, spirv_inst_iter def, bool is_array_of_verts) {
15155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    while (true) {
15165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
15175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (def.opcode() == spv::OpTypePointer) {
15185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            def = src->get_def(def.word(3));
15195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else if (def.opcode() == spv::OpTypeArray && is_array_of_verts) {
15205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            def = src->get_def(def.word(2));
15215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            is_array_of_verts = false;
15225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else if (def.opcode() == spv::OpTypeStruct) {
15235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            return def;
15245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
15255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            return src->end();
15265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
15275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
15285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
15295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1530edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic void collect_interface_block_members(shader_module const *src,
15313a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes                                            std::map<location_t, interface_var> *out,
15325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                            std::unordered_map<unsigned, unsigned> const &blocks, bool is_array_of_verts,
1533b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes                                            uint32_t id, uint32_t type_id, bool is_patch) {
15345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    /* Walk down the type_id presented, trying to determine whether it's actually an interface block. */
1535031261d21af8907953dd763398ce9a23e65b8749Chris Forbes    auto type = get_struct_type(src, src->get_def(type_id), is_array_of_verts && !is_patch);
15365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (type == src->end() || blocks.find(type.word(1)) == blocks.end()) {
15375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        /* this isn't an interface block. */
15385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return;
15395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
15405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
15415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    std::unordered_map<unsigned, unsigned> member_components;
15425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
15435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    /* Walk all the OpMemberDecorate for type's result id -- first pass, collect components. */
15445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (auto insn : *src) {
15455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (insn.opcode() == spv::OpMemberDecorate && insn.word(1) == type.word(1)) {
15465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            unsigned member_index = insn.word(2);
15475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
15485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (insn.word(3) == spv::DecorationComponent) {
15495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                unsigned component = insn.word(4);
15505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                member_components[member_index] = component;
15515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
15525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
15535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
15545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
15555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    /* Second pass -- produce the output, from Location decorations */
15565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (auto insn : *src) {
15575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (insn.opcode() == spv::OpMemberDecorate && insn.word(1) == type.word(1)) {
15585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            unsigned member_index = insn.word(2);
15595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            unsigned member_type_id = type.word(2 + member_index);
15605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
15615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (insn.word(3) == spv::DecorationLocation) {
15625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                unsigned location = insn.word(4);
15635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                unsigned num_locations = get_locations_consumed_by_type(src, member_type_id, false);
15645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                auto component_it = member_components.find(member_index);
15655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                unsigned component = component_it == member_components.end() ? 0 : component_it->second;
15665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
15675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                for (unsigned int offset = 0; offset < num_locations; offset++) {
15685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    interface_var v;
15695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    v.id = id;
15705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    /* TODO: member index in interface_var too? */
15715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    v.type_id = member_type_id;
15725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    v.offset = offset;
1573b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes                    v.is_patch = is_patch;
1574fff9393206f66a154438e16fa0562c989f425498Chris Forbes                    v.is_block_member = true;
15753a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes                    (*out)[std::make_pair(location + offset, component)] = v;
15765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
15775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
15785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
15795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
15805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
15815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
15823a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbesstatic std::map<location_t, interface_var> collect_interface_by_location(
15833a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes        shader_module const *src, spirv_inst_iter entrypoint,
15843a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes        spv::StorageClass sinterface, bool is_array_of_verts) {
15853a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes
15865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    std::unordered_map<unsigned, unsigned> var_locations;
15875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    std::unordered_map<unsigned, unsigned> var_builtins;
15885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    std::unordered_map<unsigned, unsigned> var_components;
15895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    std::unordered_map<unsigned, unsigned> blocks;
1590b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes    std::unordered_map<unsigned, unsigned> var_patch;
15915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
15925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (auto insn : *src) {
15935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
15945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        /* We consider two interface models: SSO rendezvous-by-location, and
15955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis         * builtins. Complain about anything that fits neither model.
15965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis         */
15975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (insn.opcode() == spv::OpDecorate) {
15985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (insn.word(2) == spv::DecorationLocation) {
15995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                var_locations[insn.word(1)] = insn.word(3);
16005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
16015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
16025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (insn.word(2) == spv::DecorationBuiltIn) {
16035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                var_builtins[insn.word(1)] = insn.word(3);
16045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
16055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
16065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (insn.word(2) == spv::DecorationComponent) {
16075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                var_components[insn.word(1)] = insn.word(3);
16085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
16095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
16105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (insn.word(2) == spv::DecorationBlock) {
16115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                blocks[insn.word(1)] = 1;
16125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
1613b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes
1614b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes            if (insn.word(2) == spv::DecorationPatch) {
1615b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes                var_patch[insn.word(1)] = 1;
1616b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes            }
16175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
16185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
16195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
16205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    /* TODO: handle grouped decorations */
16215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    /* TODO: handle index=1 dual source outputs from FS -- two vars will
162281264ddfa672e895a201f034617eca45bf8b9059Eric Engestrom     * have the same location, and we DON'T want to clobber. */
16235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
16245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    /* find the end of the entrypoint's name string. additional zero bytes follow the actual null
16255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis       terminator, to fill out the rest of the word - so we only need to look at the last byte in
16265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis       the word to determine which word contains the terminator. */
1627c15b801a6e1a5dd5eed09e689aecdde7c4a90a5bMichael Mc Donnell    uint32_t word = 3;
16285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    while (entrypoint.word(word) & 0xff000000u) {
16295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        ++word;
16305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
16315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    ++word;
16325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
16333a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes    std::map<location_t, interface_var> out;
16343a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes
16355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (; word < entrypoint.len(); word++) {
16365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto insn = src->get_def(entrypoint.word(word));
16375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        assert(insn != src->end());
16385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        assert(insn.opcode() == spv::OpVariable);
16395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
16401d5109d5e0dcc530b27e632e73e1be5e12a28dcdJamie Madill        if (insn.word(3) == static_cast<uint32_t>(sinterface)) {
16415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            unsigned id = insn.word(2);
16425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            unsigned type = insn.word(1);
16435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
16445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            int location = value_or_default(var_locations, id, -1);
16455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            int builtin = value_or_default(var_builtins, id, -1);
16465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            unsigned component = value_or_default(var_components, id, 0); /* unspecified is OK, is 0 */
1647b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes            bool is_patch = var_patch.find(id) != var_patch.end();
16485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
16495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            /* All variables and interface block members in the Input or Output storage classes
16505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis             * must be decorated with either a builtin or an explicit location.
16515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis             *
16525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis             * TODO: integrate the interface block support here. For now, don't complain --
16535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis             * a valid SPIRV module will only hit this path for the interface block case, as the
16545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis             * individual members of the type are decorated, rather than variable declarations.
16555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis             */
16565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
16575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (location != -1) {
16585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                /* A user-defined interface variable, with a location. Where a variable
16595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                 * occupied multiple locations, emit one result for each. */
16607c755c8aca6857046df9516d8336416165969cb9Chris Forbes                unsigned num_locations = get_locations_consumed_by_type(src, type, is_array_of_verts && !is_patch);
16615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                for (unsigned int offset = 0; offset < num_locations; offset++) {
16625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    interface_var v;
16635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    v.id = id;
16645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    v.type_id = type;
16655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    v.offset = offset;
1666b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes                    v.is_patch = is_patch;
1667fff9393206f66a154438e16fa0562c989f425498Chris Forbes                    v.is_block_member = false;
16685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    out[std::make_pair(location + offset, component)] = v;
16695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
16705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            } else if (builtin == -1) {
16715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                /* An interface block instance */
16723a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes                collect_interface_block_members(src, &out, blocks, is_array_of_verts, id, type, is_patch);
16735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
16745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
16755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
16763a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes
16773a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes    return out;
16785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
16795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
16803a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbesstatic std::vector<std::pair<uint32_t, interface_var>> collect_interface_by_input_attachment_index(
16813a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes        debug_report_data *report_data, shader_module const *src,
16823a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes        std::unordered_set<uint32_t> const &accessible_ids) {
16833a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes
16843a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes    std::vector<std::pair<uint32_t, interface_var>> out;
1685745d49409296f060402b57950384caadb636a2b2Chris Forbes
1686745d49409296f060402b57950384caadb636a2b2Chris Forbes    for (auto insn : *src) {
1687745d49409296f060402b57950384caadb636a2b2Chris Forbes        if (insn.opcode() == spv::OpDecorate) {
1688745d49409296f060402b57950384caadb636a2b2Chris Forbes            if (insn.word(2) == spv::DecorationInputAttachmentIndex) {
1689745d49409296f060402b57950384caadb636a2b2Chris Forbes                auto attachment_index = insn.word(3);
1690745d49409296f060402b57950384caadb636a2b2Chris Forbes                auto id = insn.word(1);
1691745d49409296f060402b57950384caadb636a2b2Chris Forbes
1692745d49409296f060402b57950384caadb636a2b2Chris Forbes                if (accessible_ids.count(id)) {
1693745d49409296f060402b57950384caadb636a2b2Chris Forbes                    auto def = src->get_def(id);
1694745d49409296f060402b57950384caadb636a2b2Chris Forbes                    assert(def != src->end());
1695745d49409296f060402b57950384caadb636a2b2Chris Forbes
1696745d49409296f060402b57950384caadb636a2b2Chris Forbes                    if (def.opcode() == spv::OpVariable && insn.word(3) == spv::StorageClassUniformConstant) {
1697e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes                        auto num_locations = get_locations_consumed_by_type(src, def.word(1), false);
1698e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes                        for (unsigned int offset = 0; offset < num_locations; offset++) {
1699e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes                            interface_var v;
1700e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes                            v.id = id;
1701e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes                            v.type_id = def.word(1);
1702e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes                            v.offset = offset;
1703e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes                            v.is_patch = false;
1704e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes                            v.is_block_member = false;
1705e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes                            out.emplace_back(attachment_index + offset, v);
1706e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes                        }
1707745d49409296f060402b57950384caadb636a2b2Chris Forbes                    }
1708745d49409296f060402b57950384caadb636a2b2Chris Forbes                }
1709745d49409296f060402b57950384caadb636a2b2Chris Forbes            }
1710745d49409296f060402b57950384caadb636a2b2Chris Forbes        }
1711745d49409296f060402b57950384caadb636a2b2Chris Forbes    }
17123a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes
17133a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes    return out;
1714745d49409296f060402b57950384caadb636a2b2Chris Forbes}
1715745d49409296f060402b57950384caadb636a2b2Chris Forbes
17163a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbesstatic std::vector<std::pair<descriptor_slot_t, interface_var>> collect_interface_by_descriptor_slot(
17173a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes        debug_report_data *report_data, shader_module const *src,
17183a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes        std::unordered_set<uint32_t> const &accessible_ids) {
17195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
17205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    std::unordered_map<unsigned, unsigned> var_sets;
17215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    std::unordered_map<unsigned, unsigned> var_bindings;
17225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
17235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (auto insn : *src) {
17245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        /* All variables in the Uniform or UniformConstant storage classes are required to be decorated with both
17255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis         * DecorationDescriptorSet and DecorationBinding.
17265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis         */
17275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (insn.opcode() == spv::OpDecorate) {
17285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (insn.word(2) == spv::DecorationDescriptorSet) {
17295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                var_sets[insn.word(1)] = insn.word(3);
17305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
17315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
17325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (insn.word(2) == spv::DecorationBinding) {
17335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                var_bindings[insn.word(1)] = insn.word(3);
17345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
17355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
17365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
17375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
17383a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes    std::vector<std::pair<descriptor_slot_t, interface_var>> out;
17393a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes
17405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (auto id : accessible_ids) {
17415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto insn = src->get_def(id);
17425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        assert(insn != src->end());
17435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
17445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (insn.opcode() == spv::OpVariable &&
17455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            (insn.word(3) == spv::StorageClassUniform || insn.word(3) == spv::StorageClassUniformConstant)) {
17465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            unsigned set = value_or_default(var_sets, insn.word(2), 0);
17475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            unsigned binding = value_or_default(var_bindings, insn.word(2), 0);
17485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
17495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            interface_var v;
17505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            v.id = insn.word(2);
17515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            v.type_id = insn.word(1);
1752b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes            v.offset = 0;
1753b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes            v.is_patch = false;
1754fff9393206f66a154438e16fa0562c989f425498Chris Forbes            v.is_block_member = false;
1755cefd4dd8e03c5dae11a05d04a03cb856190358e0Chris Forbes            out.emplace_back(std::make_pair(set, binding), v);
17565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
17575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
17583a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes
17593a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes    return out;
17605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
17615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1762edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_interface_between_stages(debug_report_data *report_data, shader_module const *producer,
1763031261d21af8907953dd763398ce9a23e65b8749Chris Forbes                                              spirv_inst_iter producer_entrypoint, shader_stage_attributes const *producer_stage,
17645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                              shader_module const *consumer, spirv_inst_iter consumer_entrypoint,
1765031261d21af8907953dd763398ce9a23e65b8749Chris Forbes                                              shader_stage_attributes const *consumer_stage) {
17665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    bool pass = true;
17675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
17683a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes    auto outputs = collect_interface_by_location(producer, producer_entrypoint, spv::StorageClassOutput, producer_stage->arrayed_output);
17693a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes    auto inputs = collect_interface_by_location(consumer, consumer_entrypoint, spv::StorageClassInput, consumer_stage->arrayed_input);
17705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
17715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    auto a_it = outputs.begin();
17725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    auto b_it = inputs.begin();
17735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
17745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    /* maps sorted by key (location); walk them together to find mismatches */
17755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    while ((outputs.size() > 0 && a_it != outputs.end()) || (inputs.size() && b_it != inputs.end())) {
17765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        bool a_at_end = outputs.size() == 0 || a_it == outputs.end();
17775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        bool b_at_end = inputs.size() == 0 || b_it == inputs.end();
17785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto a_first = a_at_end ? std::make_pair(0u, 0u) : a_it->first;
17795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto b_first = b_at_end ? std::make_pair(0u, 0u) : b_it->first;
17805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
17815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (b_at_end || ((!a_at_end) && (a_first < b_first))) {
1782edef66e03ed509994449d598f4fadea1a487d41bChris Forbes            if (log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0,
1783080afef66a53dbdd085698b713697296458edfd9Chris Forbes                        __LINE__, SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC",
1784031261d21af8907953dd763398ce9a23e65b8749Chris Forbes                        "%s writes to output location %u.%u which is not consumed by %s", producer_stage->name, a_first.first,
1785031261d21af8907953dd763398ce9a23e65b8749Chris Forbes                        a_first.second, consumer_stage->name)) {
17865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                pass = false;
17875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
17885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            a_it++;
17895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else if (a_at_end || a_first > b_first) {
1790edef66e03ed509994449d598f4fadea1a487d41bChris Forbes            if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0,
17915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        __LINE__, SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC",
1792031261d21af8907953dd763398ce9a23e65b8749Chris Forbes                        "%s consumes input location %u.%u which is not written by %s", consumer_stage->name, b_first.first, b_first.second,
1793031261d21af8907953dd763398ce9a23e65b8749Chris Forbes                        producer_stage->name)) {
17945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                pass = false;
17955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
17965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            b_it++;
17975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
1798fff9393206f66a154438e16fa0562c989f425498Chris Forbes            // subtleties of arrayed interfaces:
1799fff9393206f66a154438e16fa0562c989f425498Chris Forbes            // - if is_patch, then the member is not arrayed, even though the interface may be.
1800fff9393206f66a154438e16fa0562c989f425498Chris Forbes            // - if is_block_member, then the extra array level of an arrayed interface is not
1801fff9393206f66a154438e16fa0562c989f425498Chris Forbes            //   expressed in the member type -- it's expressed in the block type.
18020f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes            if (!types_match(producer, consumer, a_it->second.type_id, b_it->second.type_id,
1803fff9393206f66a154438e16fa0562c989f425498Chris Forbes                             producer_stage->arrayed_output && !a_it->second.is_patch && !a_it->second.is_block_member,
1804fff9393206f66a154438e16fa0562c989f425498Chris Forbes                             consumer_stage->arrayed_input && !b_it->second.is_patch && !b_it->second.is_block_member,
180537576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes                             true)) {
1806edef66e03ed509994449d598f4fadea1a487d41bChris Forbes                if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0,
18075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            __LINE__, SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", "Type mismatch on location %u.%u: '%s' vs '%s'",
18089ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes                            a_first.first, a_first.second,
18099ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes                            describe_type(producer, a_it->second.type_id).c_str(),
18109ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes                            describe_type(consumer, b_it->second.type_id).c_str())) {
18115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    pass = false;
18125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
18135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
18140f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes            if (a_it->second.is_patch != b_it->second.is_patch) {
1815edef66e03ed509994449d598f4fadea1a487d41bChris Forbes                if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/ 0,
18160f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes                            __LINE__, SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC",
1817f706c50be3a9d4d1e131c2f43ee2fb443f028d30Chris Forbes                            "Decoration mismatch on location %u.%u: is per-%s in %s stage but "
18180f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes                            "per-%s in %s stage", a_first.first, a_first.second,
18190f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes                            a_it->second.is_patch ? "patch" : "vertex", producer_stage->name,
18200f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes                            b_it->second.is_patch ? "patch" : "vertex", consumer_stage->name)) {
18210f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes                    pass = false;
18220f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes                }
18230f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes            }
18245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            a_it++;
18255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            b_it++;
18265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
18275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
18285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
18295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return pass;
18305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
18315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
18325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisenum FORMAT_TYPE {
18335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    FORMAT_TYPE_UNDEFINED,
18345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    FORMAT_TYPE_FLOAT, /* UNORM, SNORM, FLOAT, USCALED, SSCALED, SRGB -- anything we consider float in the shader */
18355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    FORMAT_TYPE_SINT,
18365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    FORMAT_TYPE_UINT,
18375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis};
18385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
18395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic unsigned get_format_type(VkFormat fmt) {
18405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    switch (fmt) {
18415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_UNDEFINED:
18425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return FORMAT_TYPE_UNDEFINED;
18435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_R8_SINT:
18445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_R8G8_SINT:
18455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_R8G8B8_SINT:
18465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_R8G8B8A8_SINT:
18475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_R16_SINT:
18485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_R16G16_SINT:
18495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_R16G16B16_SINT:
18505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_R16G16B16A16_SINT:
18515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_R32_SINT:
18525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_R32G32_SINT:
18535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_R32G32B32_SINT:
18545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_R32G32B32A32_SINT:
185531c2b86c259f87e539d544702c30e3c368e6b905Chris Forbes    case VK_FORMAT_R64_SINT:
185631c2b86c259f87e539d544702c30e3c368e6b905Chris Forbes    case VK_FORMAT_R64G64_SINT:
185731c2b86c259f87e539d544702c30e3c368e6b905Chris Forbes    case VK_FORMAT_R64G64B64_SINT:
185831c2b86c259f87e539d544702c30e3c368e6b905Chris Forbes    case VK_FORMAT_R64G64B64A64_SINT:
18595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_B8G8R8_SINT:
18605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_B8G8R8A8_SINT:
1861f0e6d40360fcfcc98df5ada68c14b08f11eec531Chris Forbes    case VK_FORMAT_A8B8G8R8_SINT_PACK32:
18625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_A2B10G10R10_SINT_PACK32:
18635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_A2R10G10B10_SINT_PACK32:
18645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return FORMAT_TYPE_SINT;
18655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_R8_UINT:
18665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_R8G8_UINT:
18675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_R8G8B8_UINT:
18685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_R8G8B8A8_UINT:
18695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_R16_UINT:
18705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_R16G16_UINT:
18715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_R16G16B16_UINT:
18725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_R16G16B16A16_UINT:
18735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_R32_UINT:
18745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_R32G32_UINT:
18755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_R32G32B32_UINT:
18765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_R32G32B32A32_UINT:
187731c2b86c259f87e539d544702c30e3c368e6b905Chris Forbes    case VK_FORMAT_R64_UINT:
187831c2b86c259f87e539d544702c30e3c368e6b905Chris Forbes    case VK_FORMAT_R64G64_UINT:
187931c2b86c259f87e539d544702c30e3c368e6b905Chris Forbes    case VK_FORMAT_R64G64B64_UINT:
188031c2b86c259f87e539d544702c30e3c368e6b905Chris Forbes    case VK_FORMAT_R64G64B64A64_UINT:
18815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_B8G8R8_UINT:
18825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_B8G8R8A8_UINT:
1883f0e6d40360fcfcc98df5ada68c14b08f11eec531Chris Forbes    case VK_FORMAT_A8B8G8R8_UINT_PACK32:
18845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_A2B10G10R10_UINT_PACK32:
18855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_FORMAT_A2R10G10B10_UINT_PACK32:
18865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return FORMAT_TYPE_UINT;
18875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    default:
18885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return FORMAT_TYPE_FLOAT;
18895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
18905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
18915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
18925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis/* characterizes a SPIR-V type appearing in an interface to a FF stage,
18935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis * for comparison to a VkFormat's characterization above. */
18945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic unsigned get_fundamental_type(shader_module const *src, unsigned type) {
18955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    auto insn = src->get_def(type);
18965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    assert(insn != src->end());
18975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
18985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    switch (insn.opcode()) {
18995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeInt:
19005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return insn.word(3) ? FORMAT_TYPE_SINT : FORMAT_TYPE_UINT;
19015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeFloat:
19025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return FORMAT_TYPE_FLOAT;
19035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeVector:
19045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return get_fundamental_type(src, insn.word(2));
19055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeMatrix:
19065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return get_fundamental_type(src, insn.word(2));
19075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeArray:
19085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return get_fundamental_type(src, insn.word(2));
19095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypePointer:
19105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return get_fundamental_type(src, insn.word(3));
1911f95c35481cba95e16f9e70a62df61b49e2085076Chris Forbes    case spv::OpTypeImage:
1912f95c35481cba95e16f9e70a62df61b49e2085076Chris Forbes        return get_fundamental_type(src, insn.word(2));
1913f95c35481cba95e16f9e70a62df61b49e2085076Chris Forbes
19145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    default:
19155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return FORMAT_TYPE_UNDEFINED;
19165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
19175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
19185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
19195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic uint32_t get_shader_stage_id(VkShaderStageFlagBits stage) {
19205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t bit_pos = u_ffs(stage);
19215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return bit_pos - 1;
19225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
19235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1924edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_vi_consistency(debug_report_data *report_data, VkPipelineVertexInputStateCreateInfo const *vi) {
19255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    /* walk the binding descriptions, which describe the step rate and stride of each vertex buffer.
19265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis     * each binding should be specified only once.
19275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis     */
19285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    std::unordered_map<uint32_t, VkVertexInputBindingDescription const *> bindings;
19295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    bool pass = true;
19305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
19315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (unsigned i = 0; i < vi->vertexBindingDescriptionCount; i++) {
19325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto desc = &vi->pVertexBindingDescriptions[i];
19335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto &binding = bindings[desc->binding];
19345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (binding) {
1935edef66e03ed509994449d598f4fadea1a487d41bChris Forbes            if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0,
19365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        __LINE__, SHADER_CHECKER_INCONSISTENT_VI, "SC",
19375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        "Duplicate vertex input binding descriptions for binding %d", desc->binding)) {
19385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                pass = false;
19395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
19405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
19415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            binding = desc;
19425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
19435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
19445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
19455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return pass;
19465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
19475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1948edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_vi_against_vs_inputs(debug_report_data *report_data, VkPipelineVertexInputStateCreateInfo const *vi,
19495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                          shader_module const *vs, spirv_inst_iter entrypoint) {
19505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    bool pass = true;
19515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
19523a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes    auto inputs = collect_interface_by_location(vs, entrypoint, spv::StorageClassInput, false);
19535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
19545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    /* Build index by location */
19555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    std::map<uint32_t, VkVertexInputAttributeDescription const *> attribs;
19565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (vi) {
1957c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes        for (unsigned i = 0; i < vi->vertexAttributeDescriptionCount; i++) {
1958c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes            auto num_locations = get_locations_consumed_by_format(vi->pVertexAttributeDescriptions[i].format);
1959c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes            for (auto j = 0u; j < num_locations; j++) {
1960c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes                attribs[vi->pVertexAttributeDescriptions[i].location + j] = &vi->pVertexAttributeDescriptions[i];
1961c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes            }
1962c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes        }
19635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
19645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
19655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    auto it_a = attribs.begin();
19665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    auto it_b = inputs.begin();
19671730e0dd28b3abc660b4e4704cf6d414f7fd4ad6Chris Forbes    bool used = false;
19685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
19695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    while ((attribs.size() > 0 && it_a != attribs.end()) || (inputs.size() > 0 && it_b != inputs.end())) {
19705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        bool a_at_end = attribs.size() == 0 || it_a == attribs.end();
19715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        bool b_at_end = inputs.size() == 0 || it_b == inputs.end();
19725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto a_first = a_at_end ? 0 : it_a->first;
19735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto b_first = b_at_end ? 0 : it_b->first.first;
19745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (!a_at_end && (b_at_end || a_first < b_first)) {
19751730e0dd28b3abc660b4e4704cf6d414f7fd4ad6Chris Forbes            if (!used && log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0,
1976080afef66a53dbdd085698b713697296458edfd9Chris Forbes                        __LINE__, SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC",
19775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        "Vertex attribute at location %d not consumed by VS", a_first)) {
19785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                pass = false;
19795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
19801730e0dd28b3abc660b4e4704cf6d414f7fd4ad6Chris Forbes            used = false;
19815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            it_a++;
19825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else if (!b_at_end && (a_at_end || b_first < a_first)) {
1983edef66e03ed509994449d598f4fadea1a487d41bChris Forbes            if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/ 0,
19844b5890faffa54a735782a6b0a628a991ddc86944Mike Weiblen                        __LINE__, SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC", "Vertex shader consumes input at location %d but not provided",
19855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        b_first)) {
19865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                pass = false;
19875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
19885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            it_b++;
19895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
19905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            unsigned attrib_type = get_format_type(it_a->second->format);
19915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            unsigned input_type = get_fundamental_type(vs, it_b->second.type_id);
19925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
19935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            /* type checking */
19945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (attrib_type != FORMAT_TYPE_UNDEFINED && input_type != FORMAT_TYPE_UNDEFINED && attrib_type != input_type) {
1995edef66e03ed509994449d598f4fadea1a487d41bChris Forbes                if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0,
19965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            __LINE__, SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC",
19974b5890faffa54a735782a6b0a628a991ddc86944Mike Weiblen                            "Attribute type of `%s` at location %d does not match vertex shader input type of `%s`",
19989ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes                            string_VkFormat(it_a->second->format), a_first,
19999ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes                            describe_type(vs, it_b->second.type_id).c_str())) {
20005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    pass = false;
20015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
20025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
20035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
20045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            /* OK! */
20051730e0dd28b3abc660b4e4704cf6d414f7fd4ad6Chris Forbes            used = true;
20065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            it_b++;
20075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
20085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
20095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
20105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return pass;
20115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
20125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2013edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_fs_outputs_against_render_pass(debug_report_data *report_data, shader_module const *fs,
20148da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis                                                    spirv_inst_iter entrypoint, VkRenderPassCreateInfo const *rpci,
20158da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis                                                    uint32_t subpass_index) {
2016025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes    std::map<uint32_t, VkFormat> color_attachments;
20178da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis    auto subpass = rpci->pSubpasses[subpass_index];
20188da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis    for (auto i = 0u; i < subpass.colorAttachmentCount; ++i) {
2019d9da90d92748c37962766868f8b0354637672c2aTobin Ehlis        uint32_t attachment = subpass.pColorAttachments[i].attachment;
2020d9da90d92748c37962766868f8b0354637672c2aTobin Ehlis        if (attachment == VK_ATTACHMENT_UNUSED)
2021d9da90d92748c37962766868f8b0354637672c2aTobin Ehlis            continue;
2022d9da90d92748c37962766868f8b0354637672c2aTobin Ehlis        if (rpci->pAttachments[attachment].format != VK_FORMAT_UNDEFINED) {
2023d9da90d92748c37962766868f8b0354637672c2aTobin Ehlis            color_attachments[i] = rpci->pAttachments[attachment].format;
2024025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes        }
2025025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes    }
2026025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes
20275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    bool pass = true;
20285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
20295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    /* TODO: dual source blend index (spv::DecIndex, zero if not provided) */
20305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
20313a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes    auto outputs = collect_interface_by_location(fs, entrypoint, spv::StorageClassOutput, false);
20325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2033025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes    auto it_a = outputs.begin();
2034025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes    auto it_b = color_attachments.begin();
20355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2036025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes    /* Walk attachment list and outputs together */
2037025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes
2038025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes    while ((outputs.size() > 0 && it_a != outputs.end()) || (color_attachments.size() > 0 && it_b != color_attachments.end())) {
2039025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes        bool a_at_end = outputs.size() == 0 || it_a == outputs.end();
2040025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes        bool b_at_end = color_attachments.size() == 0 || it_b == color_attachments.end();
20415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2042025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes        if (!a_at_end && (b_at_end || it_a->first.first < it_b->first)) {
2043edef66e03ed509994449d598f4fadea1a487d41bChris Forbes            if (log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0,
20445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        __LINE__, SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC",
2045025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes                        "FS writes to output location %d with no matching attachment", it_a->first.first)) {
20465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                pass = false;
20475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
2048025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes            it_a++;
2049025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes        } else if (!b_at_end && (a_at_end || it_a->first.first > it_b->first)) {
2050edef66e03ed509994449d598f4fadea1a487d41bChris Forbes            if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0,
2051025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes                        __LINE__, SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC", "Attachment %d not written by FS", it_b->first)) {
20525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                pass = false;
20535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
2054025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes            it_b++;
20555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
2056025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes            unsigned output_type = get_fundamental_type(fs, it_a->second.type_id);
2057025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes            unsigned att_type = get_format_type(it_b->second);
20585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
20595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            /* type checking */
20605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (att_type != FORMAT_TYPE_UNDEFINED && output_type != FORMAT_TYPE_UNDEFINED && att_type != output_type) {
2061edef66e03ed509994449d598f4fadea1a487d41bChris Forbes                if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0,
20625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            __LINE__, SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC",
2063025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes                            "Attachment %d of type `%s` does not match FS output type of `%s`", it_b->first,
2064025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes                            string_VkFormat(it_b->second),
2065025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes                            describe_type(fs, it_a->second.type_id).c_str())) {
20665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    pass = false;
20675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
20685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
20695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
20705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            /* OK! */
2071025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes            it_a++;
2072025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes            it_b++;
20735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
20745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
20755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
20765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return pass;
20775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
20785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
20795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis/* For some analyses, we need to know about all ids referenced by the static call tree of a particular
20805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis * entrypoint. This is important for identifying the set of shader resources actually used by an entrypoint,
20815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis * for example.
20825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis * Note: we only explore parts of the image which might actually contain ids we care about for the above analyses.
20835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis *  - NOT the shader input/output interfaces.
20845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis *
20855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis * TODO: The set of interesting opcodes here was determined by eyeballing the SPIRV spec. It might be worth
20865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis * converting parts of this to be generated from the machine-readable spec instead.
20875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis */
20883a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbesstatic std::unordered_set<uint32_t> mark_accessible_ids(shader_module const *src, spirv_inst_iter entrypoint) {
20893a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes    std::unordered_set<uint32_t> ids;
20905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    std::unordered_set<uint32_t> worklist;
20915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    worklist.insert(entrypoint.word(2));
20925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
20935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    while (!worklist.empty()) {
20945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto id_iter = worklist.begin();
20955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto id = *id_iter;
20965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        worklist.erase(id_iter);
20975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
20985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto insn = src->get_def(id);
20995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (insn == src->end()) {
210081264ddfa672e895a201f034617eca45bf8b9059Eric Engestrom            /* id is something we didn't collect in build_def_index. that's OK -- we'll stumble
21015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis             * across all kinds of things here that we may not care about. */
21025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            continue;
21035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
21045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
21055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        /* try to add to the output set */
21065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (!ids.insert(id).second) {
21075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            continue; /* if we already saw this id, we don't want to walk it again. */
21085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
21095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
21105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        switch (insn.opcode()) {
21115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case spv::OpFunction:
21125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            /* scan whole body of the function, enlisting anything interesting */
21135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            while (++insn, insn.opcode() != spv::OpFunctionEnd) {
21145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                switch (insn.opcode()) {
21155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpLoad:
21165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpAtomicLoad:
21175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpAtomicExchange:
21185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpAtomicCompareExchange:
21195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpAtomicCompareExchangeWeak:
21205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpAtomicIIncrement:
21215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpAtomicIDecrement:
21225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpAtomicIAdd:
21235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpAtomicISub:
21245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpAtomicSMin:
21255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpAtomicUMin:
21265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpAtomicSMax:
21275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpAtomicUMax:
21285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpAtomicAnd:
21295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpAtomicOr:
21305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpAtomicXor:
21315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    worklist.insert(insn.word(3)); /* ptr */
21325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    break;
21335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpStore:
21345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpAtomicStore:
21355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    worklist.insert(insn.word(1)); /* ptr */
21365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    break;
21375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpAccessChain:
21385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpInBoundsAccessChain:
21395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    worklist.insert(insn.word(3)); /* base ptr */
21405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    break;
21415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpSampledImage:
21425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageSampleImplicitLod:
21435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageSampleExplicitLod:
21445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageSampleDrefImplicitLod:
21455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageSampleDrefExplicitLod:
21465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageSampleProjImplicitLod:
21475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageSampleProjExplicitLod:
21485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageSampleProjDrefImplicitLod:
21495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageSampleProjDrefExplicitLod:
21505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageFetch:
21515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageGather:
21525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageDrefGather:
21535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageRead:
21545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImage:
21555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageQueryFormat:
21565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageQueryOrder:
21575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageQuerySizeLod:
21585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageQuerySize:
21595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageQueryLod:
21605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageQueryLevels:
21615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageQuerySamples:
21625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageSparseSampleImplicitLod:
21635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageSparseSampleExplicitLod:
21645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageSparseSampleDrefImplicitLod:
21655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageSparseSampleDrefExplicitLod:
21665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageSparseSampleProjImplicitLod:
21675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageSparseSampleProjExplicitLod:
21685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageSparseSampleProjDrefImplicitLod:
21695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageSparseSampleProjDrefExplicitLod:
21705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageSparseFetch:
21715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageSparseGather:
21725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageSparseDrefGather:
21735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageTexelPointer:
21745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    worklist.insert(insn.word(3)); /* image or sampled image */
21755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    break;
21765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpImageWrite:
21775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    worklist.insert(insn.word(1)); /* image -- different operand order to above */
21785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    break;
21795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpFunctionCall:
2180c15b801a6e1a5dd5eed09e689aecdde7c4a90a5bMichael Mc Donnell                    for (uint32_t i = 3; i < insn.len(); i++) {
21815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        worklist.insert(insn.word(i)); /* fn itself, and all args */
21825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
21835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    break;
21845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
21855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                case spv::OpExtInst:
2186c15b801a6e1a5dd5eed09e689aecdde7c4a90a5bMichael Mc Donnell                    for (uint32_t i = 5; i < insn.len(); i++) {
21875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        worklist.insert(insn.word(i)); /* operands to ext inst */
21885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
21895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    break;
21905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
21915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
21925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            break;
21935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
21945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
21953a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes
21963a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes    return ids;
21975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
21985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2199edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_push_constant_block_against_pipeline(debug_report_data *report_data,
2200416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis                                                          std::vector<VkPushConstantRange> const *push_constant_ranges,
22015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                          shader_module const *src, spirv_inst_iter type,
22025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                          VkShaderStageFlagBits stage) {
22035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    bool pass = true;
22045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
22055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    /* strip off ptrs etc */
22065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    type = get_struct_type(src, type, false);
22075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    assert(type != src->end());
22085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
22095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    /* validate directly off the offsets. this isn't quite correct for arrays
22105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis     * and matrices, but is a good first step. TODO: arrays, matrices, weird
22115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis     * sizes */
22125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (auto insn : *src) {
22135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (insn.opcode() == spv::OpMemberDecorate && insn.word(1) == type.word(1)) {
22145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
22155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (insn.word(3) == spv::DecorationOffset) {
22165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                unsigned offset = insn.word(4);
22175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                auto size = 4; /* bytes; TODO: calculate this based on the type */
22185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
22195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                bool found_range = false;
2220416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis                for (auto const &range : *push_constant_ranges) {
22215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    if (range.offset <= offset && range.offset + range.size >= offset + size) {
22225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        found_range = true;
22235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
22245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        if ((range.stageFlags & stage) == 0) {
2225edef66e03ed509994449d598f4fadea1a487d41bChris Forbes                            if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0,
2226080afef66a53dbdd085698b713697296458edfd9Chris Forbes                                        __LINE__, SHADER_CHECKER_PUSH_CONSTANT_NOT_ACCESSIBLE_FROM_STAGE, "SC",
22275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                        "Push constant range covering variable starting at "
22285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                        "offset %u not accessible from stage %s",
22295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                        offset, string_VkShaderStageFlagBits(stage))) {
22305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                pass = false;
22315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            }
22325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        }
22335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
22345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        break;
22355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
22365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
22375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
22385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if (!found_range) {
2239edef66e03ed509994449d598f4fadea1a487d41bChris Forbes                    if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0,
2240080afef66a53dbdd085698b713697296458edfd9Chris Forbes                                __LINE__, SHADER_CHECKER_PUSH_CONSTANT_OUT_OF_RANGE, "SC",
22415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                "Push constant range covering variable starting at "
22425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                "offset %u not declared in layout",
22435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                offset)) {
22445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        pass = false;
22455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
22465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
22475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
22485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
22495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
22505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
22515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return pass;
22525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
22535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2254edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_push_constant_usage(debug_report_data *report_data,
2255416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis                                         std::vector<VkPushConstantRange> const *push_constant_ranges, shader_module const *src,
22565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                         std::unordered_set<uint32_t> accessible_ids, VkShaderStageFlagBits stage) {
22575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    bool pass = true;
22585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
22595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (auto id : accessible_ids) {
22605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto def_insn = src->get_def(id);
22615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (def_insn.opcode() == spv::OpVariable && def_insn.word(3) == spv::StorageClassPushConstant) {
2262416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis            pass &= validate_push_constant_block_against_pipeline(report_data, push_constant_ranges, src,
2263416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis                                                                  src->get_def(def_insn.word(1)), stage);
22645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
22655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
22665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
22675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return pass;
22685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
22695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2270fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis// For given pipelineLayout verify that the set_layout_node at slot.first
2271fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis//  has the requested binding at slot.second and return ptr to that binding
22724a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbesstatic VkDescriptorSetLayoutBinding const * get_descriptor_binding(PIPELINE_LAYOUT_NODE const *pipelineLayout, descriptor_slot_t slot) {
22735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
22745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (!pipelineLayout)
227537083dec1ff1ca643bfc06b5308ca5ac718d58b0Chris Forbes        return nullptr;
22765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2277416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis    if (slot.first >= pipelineLayout->set_layouts.size())
227837083dec1ff1ca643bfc06b5308ca5ac718d58b0Chris Forbes        return nullptr;
22795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2280416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis    return pipelineLayout->set_layouts[slot.first]->GetDescriptorSetLayoutBindingPtrFromBinding(slot.second);
22815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
22825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
22835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Block of code at start here for managing/tracking Pipeline state that this layer cares about
22845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
22855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic uint64_t g_drawCount[NUM_DRAW_TYPES] = {0, 0, 0, 0};
22865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
22875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// TODO : Should be tracking lastBound per commandBuffer and when draws occur, report based on that cmd buffer lastBound
22885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//   Then need to synchronize the accesses based on cmd buffer so that if I'm reading state on one cmd buffer, updates
22895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//   to that same cmd buffer by separate thread are not changing state from underneath us
22905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Track the last cmd buffer touched by this thread
22915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2292e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool hasDrawCmd(GLOBAL_CB_NODE *pCB) {
22935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < NUM_DRAW_TYPES; i++) {
22945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (pCB->drawCount[i])
2295e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves            return true;
22965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
2297e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    return false;
22985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
22995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
23005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Check object status for selected flag state
2301e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool validate_status(layer_data *my_data, GLOBAL_CB_NODE *pNode, CBStatusFlags status_mask, VkFlags msg_flags,
2302e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                            DRAW_STATE_ERROR error_code, const char *fail_msg) {
23033d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    if (!(pNode->status & status_mask)) {
23043d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        return log_msg(my_data->report_data, msg_flags, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
23053d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                       reinterpret_cast<const uint64_t &>(pNode->commandBuffer), __LINE__, error_code, "DS",
2306414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                       "CB object 0x%" PRIxLEAST64 ": %s", reinterpret_cast<const uint64_t &>(pNode->commandBuffer), fail_msg);
23075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
2308e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    return false;
23095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
23105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
23115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Retrieve pipeline node ptr for given pipeline object
231216387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbesstatic PIPELINE_NODE *getPipeline(layer_data const *my_data, VkPipeline pipeline) {
2313ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes    auto it = my_data->pipelineMap.find(pipeline);
2314ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes    if (it == my_data->pipelineMap.end()) {
2315ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes        return nullptr;
23165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
2317ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes    return it->second;
23185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
23195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
232016387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbesstatic RENDER_PASS_NODE *getRenderPass(layer_data const *my_data, VkRenderPass renderpass) {
232116387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes    auto it = my_data->renderPassMap.find(renderpass);
232216387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes    if (it == my_data->renderPassMap.end()) {
232316387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes        return nullptr;
232416387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes    }
2325fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes    return it->second.get();
232616387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes}
232716387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes
232804861caca7eb93a5241b164e8480bb93c826902cTobin Ehlisstatic FRAMEBUFFER_NODE *getFramebuffer(const layer_data *my_data, VkFramebuffer framebuffer) {
2329f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes    auto it = my_data->frameBufferMap.find(framebuffer);
2330f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes    if (it == my_data->frameBufferMap.end()) {
2331f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes        return nullptr;
2332f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes    }
233304861caca7eb93a5241b164e8480bb93c826902cTobin Ehlis    return it->second.get();
2334f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes}
2335f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes
2336e3f7c45fd64a44a67ce96c89e2bbee426c6ecf24Tobin Ehliscvdescriptorset::DescriptorSetLayout const *getDescriptorSetLayout(layer_data const *my_data, VkDescriptorSetLayout dsLayout) {
233711f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes    auto it = my_data->descriptorSetLayoutMap.find(dsLayout);
233811f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes    if (it == my_data->descriptorSetLayoutMap.end()) {
233911f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes        return nullptr;
234011f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes    }
234111f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes    return it->second;
234211f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes}
234311f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes
23444a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbesstatic PIPELINE_LAYOUT_NODE const *getPipelineLayout(layer_data const *my_data, VkPipelineLayout pipeLayout) {
23454a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes    auto it = my_data->pipelineLayoutMap.find(pipeLayout);
23464a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes    if (it == my_data->pipelineLayoutMap.end()) {
23474a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes        return nullptr;
23484a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes    }
23494a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes    return &it->second;
23504a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes}
23514a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes
2352e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves// Return true if for a given PSO, the given state enum is dynamic, else return false
2353e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool isDynamic(const PIPELINE_NODE *pPipeline, const VkDynamicState state) {
23545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pPipeline && pPipeline->graphicsPipelineCI.pDynamicState) {
23555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t i = 0; i < pPipeline->graphicsPipelineCI.pDynamicState->dynamicStateCount; i++) {
23565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (state == pPipeline->graphicsPipelineCI.pDynamicState->pDynamicStates[i])
2357e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                return true;
23585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
23595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
2360e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    return false;
23615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
23625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
23635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate state stored as flags at time of draw call
2364e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool validate_draw_state_flags(layer_data *dev_data, GLOBAL_CB_NODE *pCB, const PIPELINE_NODE *pPipe, bool indexedDraw) {
23659c4006684a13db43f0dbc8d0015a9ef34872ca09Chris Forbes    bool result = false;
2366ca546210846c65808717f8875deae39bd227c240Tobin Ehlis    if (pPipe->graphicsPipelineCI.pInputAssemblyState &&
2367ca546210846c65808717f8875deae39bd227c240Tobin Ehlis        ((pPipe->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST) ||
2368ca546210846c65808717f8875deae39bd227c240Tobin Ehlis         (pPipe->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP))) {
23693d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        result |= validate_status(dev_data, pCB, CBSTATUS_LINE_WIDTH_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
23703d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                                  DRAWSTATE_LINE_WIDTH_NOT_BOUND, "Dynamic line width state not set for this command buffer");
23713d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    }
237245824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves    if (pPipe->graphicsPipelineCI.pRasterizationState &&
237345824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves        (pPipe->graphicsPipelineCI.pRasterizationState->depthBiasEnable == VK_TRUE)) {
23743d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        result |= validate_status(dev_data, pCB, CBSTATUS_DEPTH_BIAS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
23753d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                                  DRAWSTATE_DEPTH_BIAS_NOT_BOUND, "Dynamic depth bias state not set for this command buffer");
23763d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    }
23773d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    if (pPipe->blendConstantsEnabled) {
23783d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        result |= validate_status(dev_data, pCB, CBSTATUS_BLEND_CONSTANTS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
23793d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                                  DRAWSTATE_BLEND_NOT_BOUND, "Dynamic blend constants state not set for this command buffer");
23803d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    }
238145824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves    if (pPipe->graphicsPipelineCI.pDepthStencilState &&
238245824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves        (pPipe->graphicsPipelineCI.pDepthStencilState->depthBoundsTestEnable == VK_TRUE)) {
23833d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        result |= validate_status(dev_data, pCB, CBSTATUS_DEPTH_BOUNDS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
23843d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                                  DRAWSTATE_DEPTH_BOUNDS_NOT_BOUND, "Dynamic depth bounds state not set for this command buffer");
23853d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    }
238645824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves    if (pPipe->graphicsPipelineCI.pDepthStencilState &&
238745824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves        (pPipe->graphicsPipelineCI.pDepthStencilState->stencilTestEnable == VK_TRUE)) {
23883d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_READ_MASK_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
23893d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                                  DRAWSTATE_STENCIL_NOT_BOUND, "Dynamic stencil read mask state not set for this command buffer");
23903d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_WRITE_MASK_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
23913d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                                  DRAWSTATE_STENCIL_NOT_BOUND, "Dynamic stencil write mask state not set for this command buffer");
23923d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_REFERENCE_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
23933d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                                  DRAWSTATE_STENCIL_NOT_BOUND, "Dynamic stencil reference state not set for this command buffer");
23943d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    }
23953d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    if (indexedDraw) {
23963d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        result |= validate_status(dev_data, pCB, CBSTATUS_INDEX_BUFFER_BOUND, VK_DEBUG_REPORT_ERROR_BIT_EXT,
23973d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                                  DRAWSTATE_INDEX_BUFFER_NOT_BOUND,
23985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                  "Index buffer object not bound to this command buffer when Indexed Draw attempted");
23993d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    }
24005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
24015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
24025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
24035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Verify attachment reference compatibility according to spec
24045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//  If one array is larger, treat missing elements of shorter array as VK_ATTACHMENT_UNUSED & other array much match this
24055ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski//  If both AttachmentReference arrays have requested index, check their corresponding AttachmentDescriptions
24065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//   to make sure that format and samples counts match.
24075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//  If not, they are not compatible.
24085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic bool attachment_references_compatible(const uint32_t index, const VkAttachmentReference *pPrimary,
24095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                             const uint32_t primaryCount, const VkAttachmentDescription *pPrimaryAttachments,
24105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                             const VkAttachmentReference *pSecondary, const uint32_t secondaryCount,
24115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                             const VkAttachmentDescription *pSecondaryAttachments) {
2412e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis    // Check potential NULL cases first to avoid nullptr issues later
2413e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis    if (pPrimary == nullptr) {
2414e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis        if (pSecondary == nullptr) {
2415e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis            return true;
2416e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis        }
2417e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis        return false;
2418e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis    } else if (pSecondary == nullptr) {
2419e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis        return false;
2420e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis    }
24215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (index >= primaryCount) { // Check secondary as if primary is VK_ATTACHMENT_UNUSED
242206e963555b0df747c98c43816c16647349d21001Mark Young        if (VK_ATTACHMENT_UNUSED == pSecondary[index].attachment)
242306e963555b0df747c98c43816c16647349d21001Mark Young            return true;
24245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else if (index >= secondaryCount) { // Check primary as if secondary is VK_ATTACHMENT_UNUSED
242506e963555b0df747c98c43816c16647349d21001Mark Young        if (VK_ATTACHMENT_UNUSED == pPrimary[index].attachment)
242606e963555b0df747c98c43816c16647349d21001Mark Young            return true;
24275ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski    } else { // Format and sample count must match
24285ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski        if ((pPrimary[index].attachment == VK_ATTACHMENT_UNUSED) && (pSecondary[index].attachment == VK_ATTACHMENT_UNUSED)) {
24295ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski            return true;
24305ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski        } else if ((pPrimary[index].attachment == VK_ATTACHMENT_UNUSED) || (pSecondary[index].attachment == VK_ATTACHMENT_UNUSED)) {
24315ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski            return false;
24325ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski        }
24335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if ((pPrimaryAttachments[pPrimary[index].attachment].format ==
24345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis             pSecondaryAttachments[pSecondary[index].attachment].format) &&
24355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            (pPrimaryAttachments[pPrimary[index].attachment].samples ==
24365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis             pSecondaryAttachments[pSecondary[index].attachment].samples))
24375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            return true;
24385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
24395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Format and sample counts didn't match
24405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return false;
24415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
2442a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis// TODO : Scrub verify_renderpass_compatibility() and validateRenderPassCompatibility() and unify them and/or share code
24438da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis// For given primary RenderPass object and secondry RenderPassCreateInfo, verify that they're compatible
2444a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool verify_renderpass_compatibility(const layer_data *my_data, const VkRenderPassCreateInfo *primaryRPCI,
24458da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis                                            const VkRenderPassCreateInfo *secondaryRPCI, string &errorMsg) {
24465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (primaryRPCI->subpassCount != secondaryRPCI->subpassCount) {
2447c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes        stringstream errorStr;
24485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        errorStr << "RenderPass for primary cmdBuffer has " << primaryRPCI->subpassCount
24495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                 << " subpasses but renderPass for secondary cmdBuffer has " << secondaryRPCI->subpassCount << " subpasses.";
24505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        errorMsg = errorStr.str();
24515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return false;
24525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
24535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t spIndex = 0;
24545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (spIndex = 0; spIndex < primaryRPCI->subpassCount; ++spIndex) {
24555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // For each subpass, verify that corresponding color, input, resolve & depth/stencil attachment references are compatible
24565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        uint32_t primaryColorCount = primaryRPCI->pSubpasses[spIndex].colorAttachmentCount;
24575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        uint32_t secondaryColorCount = secondaryRPCI->pSubpasses[spIndex].colorAttachmentCount;
24585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        uint32_t colorMax = std::max(primaryColorCount, secondaryColorCount);
24595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t cIdx = 0; cIdx < colorMax; ++cIdx) {
24605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (!attachment_references_compatible(cIdx, primaryRPCI->pSubpasses[spIndex].pColorAttachments, primaryColorCount,
24615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                  primaryRPCI->pAttachments, secondaryRPCI->pSubpasses[spIndex].pColorAttachments,
24625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                  secondaryColorCount, secondaryRPCI->pAttachments)) {
2463c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes                stringstream errorStr;
24645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                errorStr << "color attachments at index " << cIdx << " of subpass index " << spIndex << " are not compatible.";
24655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                errorMsg = errorStr.str();
24665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                return false;
24675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            } else if (!attachment_references_compatible(cIdx, primaryRPCI->pSubpasses[spIndex].pResolveAttachments,
24685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                         primaryColorCount, primaryRPCI->pAttachments,
24695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                         secondaryRPCI->pSubpasses[spIndex].pResolveAttachments,
24705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                         secondaryColorCount, secondaryRPCI->pAttachments)) {
2471c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes                stringstream errorStr;
24725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                errorStr << "resolve attachments at index " << cIdx << " of subpass index " << spIndex << " are not compatible.";
24735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                errorMsg = errorStr.str();
24745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                return false;
24755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
24765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
2477fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes
2478fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes        if (!attachment_references_compatible(0, primaryRPCI->pSubpasses[spIndex].pDepthStencilAttachment,
2479fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes                                              1, primaryRPCI->pAttachments,
2480fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes                                              secondaryRPCI->pSubpasses[spIndex].pDepthStencilAttachment,
2481fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes                                              1, secondaryRPCI->pAttachments)) {
2482c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes            stringstream errorStr;
2483fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes            errorStr << "depth/stencil attachments of subpass index " << spIndex << " are not compatible.";
2484fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes            errorMsg = errorStr.str();
2485fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes            return false;
2486fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes        }
2487fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes
24885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        uint32_t primaryInputCount = primaryRPCI->pSubpasses[spIndex].inputAttachmentCount;
24895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        uint32_t secondaryInputCount = secondaryRPCI->pSubpasses[spIndex].inputAttachmentCount;
24905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        uint32_t inputMax = std::max(primaryInputCount, secondaryInputCount);
24915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t i = 0; i < inputMax; ++i) {
24925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (!attachment_references_compatible(i, primaryRPCI->pSubpasses[spIndex].pInputAttachments, primaryColorCount,
24935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                  primaryRPCI->pAttachments, secondaryRPCI->pSubpasses[spIndex].pInputAttachments,
24945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                  secondaryColorCount, secondaryRPCI->pAttachments)) {
2495c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes                stringstream errorStr;
24965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                errorStr << "input attachments at index " << i << " of subpass index " << spIndex << " are not compatible.";
24975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                errorMsg = errorStr.str();
24985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                return false;
24995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
25005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
25015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
25025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return true;
25035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
25045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2505397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis// For given cvdescriptorset::DescriptorSet, verify that its Set is compatible w/ the setLayout corresponding to
2506397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis// pipelineLayout[layoutIndex]
2507397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlisstatic bool verify_set_layout_compatibility(layer_data *my_data, const cvdescriptorset::DescriptorSet *pSet,
250869b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis                                            PIPELINE_LAYOUT_NODE const *pipeline_layout, const uint32_t layoutIndex,
250969b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis                                            string &errorMsg) {
2510416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis    auto num_sets = pipeline_layout->set_layouts.size();
25119b5d124aff50234cb0450e1b805baef577c90d83Tobin Ehlis    if (layoutIndex >= num_sets) {
2512c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes        stringstream errorStr;
251369b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis        errorStr << "VkPipelineLayout (" << pipeline_layout->layout << ") only contains " << num_sets
251469b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis                 << " setLayouts corresponding to sets 0-" << num_sets - 1 << ", but you're attempting to bind set to index "
251569b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis                 << layoutIndex;
25165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        errorMsg = errorStr.str();
25175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return false;
25185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
2519416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis    auto layout_node = pipeline_layout->set_layouts[layoutIndex];
2520397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis    return pSet->IsCompatible(layout_node, &errorMsg);
25215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
25225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
25235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate that data for each specialization entry is fully contained within the buffer.
2524edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_specialization_offsets(debug_report_data *report_data, VkPipelineShaderStageCreateInfo const *info) {
2525e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool pass = true;
25265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
25275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkSpecializationInfo const *spec = info->pSpecializationInfo;
25285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
25295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (spec) {
25305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (auto i = 0u; i < spec->mapEntryCount; i++) {
25315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (spec->pMapEntries[i].offset + spec->pMapEntries[i].size > spec->dataSize) {
2532edef66e03ed509994449d598f4fadea1a487d41bChris Forbes                if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
25335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            /*dev*/ 0, __LINE__, SHADER_CHECKER_BAD_SPECIALIZATION, "SC",
25345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            "Specialization entry %u (for constant id %u) references memory outside provided "
25355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            "specialization data (bytes %u.." PRINTF_SIZE_T_SPECIFIER "; " PRINTF_SIZE_T_SPECIFIER
25365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            " bytes provided)",
25375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            i, spec->pMapEntries[i].constantID, spec->pMapEntries[i].offset,
25385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            spec->pMapEntries[i].offset + spec->pMapEntries[i].size - 1, spec->dataSize)) {
25395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2540e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                    pass = false;
25415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
25425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
25435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
25445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
25455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
25465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return pass;
25475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
25485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2549edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool descriptor_type_match(shader_module const *module, uint32_t type_id,
25501b8c581791ac3c05d7829e04a2d8ecb964b8f2a6Chris Forbes                                  VkDescriptorType descriptor_type, unsigned &descriptor_count) {
25515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    auto type = module->get_def(type_id);
25525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
25531b8c581791ac3c05d7829e04a2d8ecb964b8f2a6Chris Forbes    descriptor_count = 1;
25541b8c581791ac3c05d7829e04a2d8ecb964b8f2a6Chris Forbes
25557b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes    /* Strip off any array or ptrs. Where we remove array levels, adjust the
25567b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes     * descriptor count for each dimension. */
25575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    while (type.opcode() == spv::OpTypeArray || type.opcode() == spv::OpTypePointer) {
25587b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes        if (type.opcode() == spv::OpTypeArray) {
25597b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes            descriptor_count *= get_constant_value(module, type.word(3));
25607b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes            type = module->get_def(type.word(2));
25617b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes        }
25627b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes        else {
25637b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes            type = module->get_def(type.word(3));
25647b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes        }
25655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
25665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
25675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    switch (type.opcode()) {
25685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeStruct: {
25695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (auto insn : *module) {
25705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (insn.opcode() == spv::OpDecorate && insn.word(1) == type.word(1)) {
25715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if (insn.word(2) == spv::DecorationBlock) {
25725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    return descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
25735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                           descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
25745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                } else if (insn.word(2) == spv::DecorationBufferBlock) {
25755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    return descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER ||
25765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                           descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
25775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
25785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
25795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
25805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
25815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        /* Invalid */
25825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return false;
25835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
25845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
25855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeSampler:
258667d9e049b7eb6a440707031b8eb7ddd21061e1abChris Forbes        return descriptor_type == VK_DESCRIPTOR_TYPE_SAMPLER ||
258767d9e049b7eb6a440707031b8eb7ddd21061e1abChris Forbes            descriptor_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
25885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
25895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeSampledImage:
259035cd175466f88e5a0a081b29c59c3246d5bf7f78Chris Forbes        if (descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) {
259135cd175466f88e5a0a081b29c59c3246d5bf7f78Chris Forbes            /* Slight relaxation for some GLSL historical madness: samplerBuffer
259235cd175466f88e5a0a081b29c59c3246d5bf7f78Chris Forbes             * doesn't really have a sampler, and a texel buffer descriptor
259335cd175466f88e5a0a081b29c59c3246d5bf7f78Chris Forbes             * doesn't really provide one. Allow this slight mismatch.
259435cd175466f88e5a0a081b29c59c3246d5bf7f78Chris Forbes             */
259535cd175466f88e5a0a081b29c59c3246d5bf7f78Chris Forbes            auto image_type = module->get_def(type.word(2));
259635cd175466f88e5a0a081b29c59c3246d5bf7f78Chris Forbes            auto dim = image_type.word(3);
259735cd175466f88e5a0a081b29c59c3246d5bf7f78Chris Forbes            auto sampled = image_type.word(7);
259835cd175466f88e5a0a081b29c59c3246d5bf7f78Chris Forbes            return dim == spv::DimBuffer && sampled == 1;
259935cd175466f88e5a0a081b29c59c3246d5bf7f78Chris Forbes        }
26005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return descriptor_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
26015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
26025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case spv::OpTypeImage: {
26035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        /* Many descriptor types backing image types-- depends on dimension
26045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis         * and whether the image will be used with a sampler. SPIRV for
26055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis         * Vulkan requires that sampled be 1 or 2 -- leaving the decision to
26065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis         * runtime is unacceptable.
26075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis         */
26085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto dim = type.word(3);
26095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto sampled = type.word(7);
26105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
26115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (dim == spv::DimSubpassData) {
26125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            return descriptor_type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
26135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else if (dim == spv::DimBuffer) {
26145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (sampled == 1) {
26155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                return descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
26165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            } else {
26175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                return descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
26185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
26195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else if (sampled == 1) {
262067d9e049b7eb6a440707031b8eb7ddd21061e1abChris Forbes            return descriptor_type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
262167d9e049b7eb6a440707031b8eb7ddd21061e1abChris Forbes                descriptor_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
26225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
26235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            return descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
26245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
26255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
26265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
26275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    /* We shouldn't really see any other junk types -- but if we do, they're
26285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis     * a mismatch.
26295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis     */
26305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    default:
26315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return false; /* Mismatch */
26325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
26335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
26345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
26354110a6be7a8a287d459475926985f71c27d01298Chris Forbesstatic bool require_feature(debug_report_data *report_data, VkBool32 feature, char const *feature_name) {
2636a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes    if (!feature) {
26374110a6be7a8a287d459475926985f71c27d01298Chris Forbes        if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0,
2638080afef66a53dbdd085698b713697296458edfd9Chris Forbes                    __LINE__, SHADER_CHECKER_FEATURE_NOT_ENABLED, "SC",
2639a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                    "Shader requires VkPhysicalDeviceFeatures::%s but is not "
2640a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                    "enabled on the device",
2641a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                    feature_name)) {
2642a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            return false;
2643a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes        }
2644a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes    }
2645a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2646a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes    return true;
2647a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes}
2648a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
264969f9a551bfb1fd5334950f9685c12c5adda23dfbChris Forbesstatic bool validate_shader_capabilities(debug_report_data *report_data, shader_module const *src,
265069f9a551bfb1fd5334950f9685c12c5adda23dfbChris Forbes                                         VkPhysicalDeviceFeatures const *enabledFeatures) {
2651e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool pass = true;
2652a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2653a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2654a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes    for (auto insn : *src) {
2655a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes        if (insn.opcode() == spv::OpCapability) {
2656a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            switch (insn.word(1)) {
2657a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityMatrix:
2658a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityShader:
2659a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityInputAttachment:
2660a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilitySampled1D:
2661a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityImage1D:
2662a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilitySampledBuffer:
2663a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityImageBuffer:
2664a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityImageQuery:
2665a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityDerivativeControl:
2666a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                // Always supported by a Vulkan 1.0 implementation -- no feature bits.
2667a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                break;
2668a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2669a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityGeometry:
26704110a6be7a8a287d459475926985f71c27d01298Chris Forbes                pass &= require_feature(report_data, enabledFeatures->geometryShader, "geometryShader");
2671a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                break;
2672a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2673a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityTessellation:
26744110a6be7a8a287d459475926985f71c27d01298Chris Forbes                pass &= require_feature(report_data, enabledFeatures->tessellationShader, "tessellationShader");
2675a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                break;
2676a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2677a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityFloat64:
26784110a6be7a8a287d459475926985f71c27d01298Chris Forbes                pass &= require_feature(report_data, enabledFeatures->shaderFloat64, "shaderFloat64");
2679a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                break;
2680a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2681a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityInt64:
26824110a6be7a8a287d459475926985f71c27d01298Chris Forbes                pass &= require_feature(report_data, enabledFeatures->shaderInt64, "shaderInt64");
2683a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                break;
2684a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2685a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityTessellationPointSize:
2686a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityGeometryPointSize:
26874110a6be7a8a287d459475926985f71c27d01298Chris Forbes                pass &= require_feature(report_data, enabledFeatures->shaderTessellationAndGeometryPointSize,
2688a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                                        "shaderTessellationAndGeometryPointSize");
2689a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                break;
2690a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2691a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityImageGatherExtended:
26924110a6be7a8a287d459475926985f71c27d01298Chris Forbes                pass &= require_feature(report_data, enabledFeatures->shaderImageGatherExtended, "shaderImageGatherExtended");
2693a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                break;
2694a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2695a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityStorageImageMultisample:
26964110a6be7a8a287d459475926985f71c27d01298Chris Forbes                pass &= require_feature(report_data, enabledFeatures->shaderStorageImageMultisample, "shaderStorageImageMultisample");
2697a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                break;
2698a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2699a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityUniformBufferArrayDynamicIndexing:
27004110a6be7a8a287d459475926985f71c27d01298Chris Forbes                pass &= require_feature(report_data, enabledFeatures->shaderUniformBufferArrayDynamicIndexing,
2701a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                                        "shaderUniformBufferArrayDynamicIndexing");
2702a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                break;
2703a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2704a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilitySampledImageArrayDynamicIndexing:
27054110a6be7a8a287d459475926985f71c27d01298Chris Forbes                pass &= require_feature(report_data, enabledFeatures->shaderSampledImageArrayDynamicIndexing,
2706a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                                        "shaderSampledImageArrayDynamicIndexing");
2707a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                break;
2708a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2709a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityStorageBufferArrayDynamicIndexing:
27104110a6be7a8a287d459475926985f71c27d01298Chris Forbes                pass &= require_feature(report_data, enabledFeatures->shaderStorageBufferArrayDynamicIndexing,
2711a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                                        "shaderStorageBufferArrayDynamicIndexing");
2712a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                break;
2713a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2714a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityStorageImageArrayDynamicIndexing:
27154110a6be7a8a287d459475926985f71c27d01298Chris Forbes                pass &= require_feature(report_data, enabledFeatures->shaderStorageImageArrayDynamicIndexing,
2716a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                                        "shaderStorageImageArrayDynamicIndexing");
2717a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                break;
2718a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2719a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityClipDistance:
27204110a6be7a8a287d459475926985f71c27d01298Chris Forbes                pass &= require_feature(report_data, enabledFeatures->shaderClipDistance, "shaderClipDistance");
2721a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                break;
2722a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2723a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityCullDistance:
27244110a6be7a8a287d459475926985f71c27d01298Chris Forbes                pass &= require_feature(report_data, enabledFeatures->shaderCullDistance, "shaderCullDistance");
2725a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                break;
2726a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2727a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityImageCubeArray:
27284110a6be7a8a287d459475926985f71c27d01298Chris Forbes                pass &= require_feature(report_data, enabledFeatures->imageCubeArray, "imageCubeArray");
2729a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                break;
2730a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2731a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilitySampleRateShading:
27324110a6be7a8a287d459475926985f71c27d01298Chris Forbes                pass &= require_feature(report_data, enabledFeatures->sampleRateShading, "sampleRateShading");
2733a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                break;
2734a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2735a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilitySparseResidency:
27364110a6be7a8a287d459475926985f71c27d01298Chris Forbes                pass &= require_feature(report_data, enabledFeatures->shaderResourceResidency, "shaderResourceResidency");
2737a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                break;
2738a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2739a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityMinLod:
27404110a6be7a8a287d459475926985f71c27d01298Chris Forbes                pass &= require_feature(report_data, enabledFeatures->shaderResourceMinLod, "shaderResourceMinLod");
2741a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                break;
2742a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2743a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilitySampledCubeArray:
27444110a6be7a8a287d459475926985f71c27d01298Chris Forbes                pass &= require_feature(report_data, enabledFeatures->imageCubeArray, "imageCubeArray");
2745a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                break;
2746a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2747a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityImageMSArray:
27484110a6be7a8a287d459475926985f71c27d01298Chris Forbes                pass &= require_feature(report_data, enabledFeatures->shaderStorageImageMultisample, "shaderStorageImageMultisample");
2749a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                break;
2750a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2751a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityStorageImageExtendedFormats:
27524110a6be7a8a287d459475926985f71c27d01298Chris Forbes                pass &= require_feature(report_data, enabledFeatures->shaderStorageImageExtendedFormats,
2753a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                                        "shaderStorageImageExtendedFormats");
2754a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                break;
2755a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2756a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityInterpolationFunction:
27574110a6be7a8a287d459475926985f71c27d01298Chris Forbes                pass &= require_feature(report_data, enabledFeatures->sampleRateShading, "sampleRateShading");
2758a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                break;
2759a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2760a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityStorageImageReadWithoutFormat:
27614110a6be7a8a287d459475926985f71c27d01298Chris Forbes                pass &= require_feature(report_data, enabledFeatures->shaderStorageImageReadWithoutFormat,
2762a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                                        "shaderStorageImageReadWithoutFormat");
2763a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                break;
2764a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2765a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityStorageImageWriteWithoutFormat:
27664110a6be7a8a287d459475926985f71c27d01298Chris Forbes                pass &= require_feature(report_data, enabledFeatures->shaderStorageImageWriteWithoutFormat,
2767a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                                        "shaderStorageImageWriteWithoutFormat");
2768a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                break;
2769a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2770a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            case spv::CapabilityMultiViewport:
27714110a6be7a8a287d459475926985f71c27d01298Chris Forbes                pass &= require_feature(report_data, enabledFeatures->multiViewport, "multiViewport");
2772a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                break;
2773a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2774a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            default:
27754110a6be7a8a287d459475926985f71c27d01298Chris Forbes                if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0,
2776a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                            __LINE__, SHADER_CHECKER_BAD_CAPABILITY, "SC",
2777a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                            "Shader declares capability %u, not supported in Vulkan.",
2778a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                            insn.word(1)))
2779e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                    pass = false;
2780a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes                break;
2781a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes            }
2782a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes        }
2783a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes    }
2784a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2785a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes    return pass;
2786a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes}
2787a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes
2788b2a61f3cd17c68887759817059fa1872f1e1464aChris Forbes
2789b2a61f3cd17c68887759817059fa1872f1e1464aChris Forbesstatic uint32_t descriptor_type_to_reqs(shader_module const *module, uint32_t type_id) {
27902aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes    auto type = module->get_def(type_id);
27912aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes
27922aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes    while (true) {
27932aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes        switch (type.opcode()) {
27942aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes        case spv::OpTypeArray:
27952aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes        case spv::OpTypeSampledImage:
27962aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes            type = module->get_def(type.word(2));
27972aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes            break;
27982aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes        case spv::OpTypePointer:
27992aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes            type = module->get_def(type.word(3));
28002aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes            break;
28012aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes        case spv::OpTypeImage: {
28022aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes            auto dim = type.word(3);
28032aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes            auto arrayed = type.word(5);
28042aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes            auto msaa = type.word(6);
28052aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes
28062aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes            switch (dim) {
28072aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes            case spv::Dim1D:
2808488514f7ca0a92f1d493e5da62ab697e65731854Chris Forbes                return arrayed ? DESCRIPTOR_REQ_VIEW_TYPE_1D_ARRAY : DESCRIPTOR_REQ_VIEW_TYPE_1D;
28092aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes            case spv::Dim2D:
28102aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes                return (msaa ? DESCRIPTOR_REQ_MULTI_SAMPLE : DESCRIPTOR_REQ_SINGLE_SAMPLE) |
2811488514f7ca0a92f1d493e5da62ab697e65731854Chris Forbes                    (arrayed ? DESCRIPTOR_REQ_VIEW_TYPE_2D_ARRAY : DESCRIPTOR_REQ_VIEW_TYPE_2D);
28122aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes            case spv::Dim3D:
28132aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes                return DESCRIPTOR_REQ_VIEW_TYPE_3D;
28142aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes            case spv::DimCube:
2815488514f7ca0a92f1d493e5da62ab697e65731854Chris Forbes                return arrayed ? DESCRIPTOR_REQ_VIEW_TYPE_CUBE_ARRAY : DESCRIPTOR_REQ_VIEW_TYPE_CUBE;
281628db3859aeeca6ab2fcbe51e016c2b785d158edcChris Forbes            case spv::DimSubpassData:
281728db3859aeeca6ab2fcbe51e016c2b785d158edcChris Forbes                return msaa ? DESCRIPTOR_REQ_MULTI_SAMPLE : DESCRIPTOR_REQ_SINGLE_SAMPLE;
281828db3859aeeca6ab2fcbe51e016c2b785d158edcChris Forbes            default:  // buffer, etc.
28192aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes                return 0;
28202aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes            }
28212aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes        }
28222aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes        default:
28232aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes            return 0;
28242aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes        }
28252aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes    }
2826b2a61f3cd17c68887759817059fa1872f1e1464aChris Forbes}
2827b2a61f3cd17c68887759817059fa1872f1e1464aChris Forbes
2828b2a61f3cd17c68887759817059fa1872f1e1464aChris Forbes
2829ed399f66e0512ef077d0e0a7cb903248726d2424Chris Forbesstatic bool validate_pipeline_shader_stage(debug_report_data *report_data,
2830ed399f66e0512ef077d0e0a7cb903248726d2424Chris Forbes                                           VkPipelineShaderStageCreateInfo const *pStage,
2831ed399f66e0512ef077d0e0a7cb903248726d2424Chris Forbes                                           PIPELINE_NODE *pipeline,
2832ed399f66e0512ef077d0e0a7cb903248726d2424Chris Forbes                                           shader_module **out_module,
2833ed399f66e0512ef077d0e0a7cb903248726d2424Chris Forbes                                           spirv_inst_iter *out_entrypoint,
283469f9a551bfb1fd5334950f9685c12c5adda23dfbChris Forbes                                           VkPhysicalDeviceFeatures const *enabledFeatures,
2835ed399f66e0512ef077d0e0a7cb903248726d2424Chris Forbes                                           std::unordered_map<VkShaderModule,
2836ed399f66e0512ef077d0e0a7cb903248726d2424Chris Forbes                                           std::unique_ptr<shader_module>> const &shaderModuleMap) {
2837e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool pass = true;
283869f9a551bfb1fd5334950f9685c12c5adda23dfbChris Forbes    auto module_it = shaderModuleMap.find(pStage->module);
283969f9a551bfb1fd5334950f9685c12c5adda23dfbChris Forbes    auto module = *out_module = module_it->second.get();
284078be5018e238bd464b1f1c55138df277c0c18922Chris Forbes
284178be5018e238bd464b1f1c55138df277c0c18922Chris Forbes    /* find the entrypoint */
284278be5018e238bd464b1f1c55138df277c0c18922Chris Forbes    auto entrypoint = *out_entrypoint = find_entrypoint(module, pStage->pName, pStage->stage);
284378be5018e238bd464b1f1c55138df277c0c18922Chris Forbes    if (entrypoint == module->end()) {
2844557cdd5218accf51ca894a14b7c6eeeb733f5cbbChris Forbes        if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0,
2845080afef66a53dbdd085698b713697296458edfd9Chris Forbes                    __LINE__, SHADER_CHECKER_MISSING_ENTRYPOINT, "SC",
284678be5018e238bd464b1f1c55138df277c0c18922Chris Forbes                    "No entrypoint found named `%s` for stage %s", pStage->pName,
284778be5018e238bd464b1f1c55138df277c0c18922Chris Forbes                    string_VkShaderStageFlagBits(pStage->stage))) {
28480cfa9c3a1747749777581684536218f83c3977a9Chris Forbes            return false;   // no point continuing beyond here, any analysis is just going to be garbage.
284978be5018e238bd464b1f1c55138df277c0c18922Chris Forbes        }
285078be5018e238bd464b1f1c55138df277c0c18922Chris Forbes    }
285178be5018e238bd464b1f1c55138df277c0c18922Chris Forbes
285278be5018e238bd464b1f1c55138df277c0c18922Chris Forbes    /* validate shader capabilities against enabled device features */
2853557cdd5218accf51ca894a14b7c6eeeb733f5cbbChris Forbes    pass &= validate_shader_capabilities(report_data, module, enabledFeatures);
285478be5018e238bd464b1f1c55138df277c0c18922Chris Forbes
285578be5018e238bd464b1f1c55138df277c0c18922Chris Forbes    /* mark accessible ids */
28563a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes    auto accessible_ids = mark_accessible_ids(module, entrypoint);
285778be5018e238bd464b1f1c55138df277c0c18922Chris Forbes
285878be5018e238bd464b1f1c55138df277c0c18922Chris Forbes    /* validate descriptor set layout against what the entrypoint actually uses */
28593a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes    auto descriptor_uses = collect_interface_by_descriptor_slot(report_data, module, accessible_ids);
286078be5018e238bd464b1f1c55138df277c0c18922Chris Forbes
28612e0eca3d6fad72a29ae072e3895e29a2d2d66476Tobin Ehlis    auto pipelineLayout = pipeline->pipeline_layout;
2862ed399f66e0512ef077d0e0a7cb903248726d2424Chris Forbes
28630cfa9c3a1747749777581684536218f83c3977a9Chris Forbes    pass &= validate_specialization_offsets(report_data, pStage);
2864416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis    pass &= validate_push_constant_usage(report_data, &pipelineLayout.push_constant_ranges, module, accessible_ids, pStage->stage);
286578be5018e238bd464b1f1c55138df277c0c18922Chris Forbes
286678be5018e238bd464b1f1c55138df277c0c18922Chris Forbes    /* validate descriptor use */
286778be5018e238bd464b1f1c55138df277c0c18922Chris Forbes    for (auto use : descriptor_uses) {
286878be5018e238bd464b1f1c55138df277c0c18922Chris Forbes        // While validating shaders capture which slots are used by the pipeline
2869b2a61f3cd17c68887759817059fa1872f1e1464aChris Forbes        auto & reqs = pipeline->active_slots[use.first.first][use.first.second];
2870b2a61f3cd17c68887759817059fa1872f1e1464aChris Forbes        reqs = descriptor_req(reqs | descriptor_type_to_reqs(module, use.second.type_id));
287178be5018e238bd464b1f1c55138df277c0c18922Chris Forbes
2872fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis        /* verify given pipelineLayout has requested setLayout with requested binding */
2873c8268861aaa8f9c47920065d6323e4609e5081b0Tobin Ehlis        const auto &binding = get_descriptor_binding(&pipelineLayout, use.first);
287478be5018e238bd464b1f1c55138df277c0c18922Chris Forbes        unsigned required_descriptor_count;
287578be5018e238bd464b1f1c55138df277c0c18922Chris Forbes
287678be5018e238bd464b1f1c55138df277c0c18922Chris Forbes        if (!binding) {
2877557cdd5218accf51ca894a14b7c6eeeb733f5cbbChris Forbes            if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0,
2878080afef66a53dbdd085698b713697296458edfd9Chris Forbes                        __LINE__, SHADER_CHECKER_MISSING_DESCRIPTOR, "SC",
287978be5018e238bd464b1f1c55138df277c0c18922Chris Forbes                        "Shader uses descriptor slot %u.%u (used as type `%s`) but not declared in pipeline layout",
288078be5018e238bd464b1f1c55138df277c0c18922Chris Forbes                        use.first.first, use.first.second, describe_type(module, use.second.type_id).c_str())) {
2881e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                pass = false;
288278be5018e238bd464b1f1c55138df277c0c18922Chris Forbes            }
288378be5018e238bd464b1f1c55138df277c0c18922Chris Forbes        } else if (~binding->stageFlags & pStage->stage) {
2884557cdd5218accf51ca894a14b7c6eeeb733f5cbbChris Forbes            if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
288578be5018e238bd464b1f1c55138df277c0c18922Chris Forbes                        /*dev*/ 0, __LINE__, SHADER_CHECKER_DESCRIPTOR_NOT_ACCESSIBLE_FROM_STAGE, "SC",
288678be5018e238bd464b1f1c55138df277c0c18922Chris Forbes                        "Shader uses descriptor slot %u.%u (used "
288778be5018e238bd464b1f1c55138df277c0c18922Chris Forbes                        "as type `%s`) but descriptor not "
288878be5018e238bd464b1f1c55138df277c0c18922Chris Forbes                        "accessible from stage %s",
2889fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis                        use.first.first, use.first.second, describe_type(module, use.second.type_id).c_str(),
289078be5018e238bd464b1f1c55138df277c0c18922Chris Forbes                        string_VkShaderStageFlagBits(pStage->stage))) {
2891e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                pass = false;
289278be5018e238bd464b1f1c55138df277c0c18922Chris Forbes            }
2893edef66e03ed509994449d598f4fadea1a487d41bChris Forbes        } else if (!descriptor_type_match(module, use.second.type_id, binding->descriptorType,
2894fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis                                          /*out*/ required_descriptor_count)) {
2895557cdd5218accf51ca894a14b7c6eeeb733f5cbbChris Forbes            if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__,
2896fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis                        SHADER_CHECKER_DESCRIPTOR_TYPE_MISMATCH, "SC", "Type mismatch on descriptor slot "
2897fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis                                                                       "%u.%u (used as type `%s`) but "
2898fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis                                                                       "descriptor of type %s",
2899fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis                        use.first.first, use.first.second, describe_type(module, use.second.type_id).c_str(),
290078be5018e238bd464b1f1c55138df277c0c18922Chris Forbes                        string_VkDescriptorType(binding->descriptorType))) {
2901e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                pass = false;
290278be5018e238bd464b1f1c55138df277c0c18922Chris Forbes            }
290378be5018e238bd464b1f1c55138df277c0c18922Chris Forbes        } else if (binding->descriptorCount < required_descriptor_count) {
2904557cdd5218accf51ca894a14b7c6eeeb733f5cbbChris Forbes            if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__,
2905fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis                        SHADER_CHECKER_DESCRIPTOR_TYPE_MISMATCH, "SC",
290678be5018e238bd464b1f1c55138df277c0c18922Chris Forbes                        "Shader expects at least %u descriptors for binding %u.%u (used as type `%s`) but only %u provided",
290778be5018e238bd464b1f1c55138df277c0c18922Chris Forbes                        required_descriptor_count, use.first.first, use.first.second,
2908fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis                        describe_type(module, use.second.type_id).c_str(), binding->descriptorCount)) {
2909e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                pass = false;
291078be5018e238bd464b1f1c55138df277c0c18922Chris Forbes            }
291178be5018e238bd464b1f1c55138df277c0c18922Chris Forbes        }
291278be5018e238bd464b1f1c55138df277c0c18922Chris Forbes    }
291378be5018e238bd464b1f1c55138df277c0c18922Chris Forbes
2914c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes    /* validate use of input attachments against subpass structure */
2915c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes    if (pStage->stage == VK_SHADER_STAGE_FRAGMENT_BIT) {
29163a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes        auto input_attachment_uses = collect_interface_by_input_attachment_index(report_data, module, accessible_ids);
2917c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes
2918c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes        auto rpci = pipeline->render_pass_ci.ptr();
2919c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes        auto subpass = pipeline->graphicsPipelineCI.subpass;
2920c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes
2921c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes        for (auto use : input_attachment_uses) {
2922c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes            auto input_attachments = rpci->pSubpasses[subpass].pInputAttachments;
2923c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes            auto index = (input_attachments && use.first < rpci->pSubpasses[subpass].inputAttachmentCount) ?
2924c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes                    input_attachments[use.first].attachment : VK_ATTACHMENT_UNUSED;
2925c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes
2926c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes            if (index == VK_ATTACHMENT_UNUSED) {
2927c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes                if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__,
2928c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes                            SHADER_CHECKER_MISSING_INPUT_ATTACHMENT, "SC",
2929c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes                            "Shader consumes input attachment index %d but not provided in subpass",
2930c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes                            use.first)) {
2931c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes                    pass = false;
2932c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes                }
2933c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes            }
2934eeb9f6a27f1acc11e54080fb3bcda7b513b5c89fChris Forbes            else if (get_format_type(rpci->pAttachments[index].format) !=
2935eeb9f6a27f1acc11e54080fb3bcda7b513b5c89fChris Forbes                    get_fundamental_type(module, use.second.type_id)) {
2936eeb9f6a27f1acc11e54080fb3bcda7b513b5c89fChris Forbes                if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__,
2937eeb9f6a27f1acc11e54080fb3bcda7b513b5c89fChris Forbes                            SHADER_CHECKER_INPUT_ATTACHMENT_TYPE_MISMATCH, "SC",
2938eeb9f6a27f1acc11e54080fb3bcda7b513b5c89fChris Forbes                            "Subpass input attachment %u format of %s does not match type used in shader `%s`",
2939eeb9f6a27f1acc11e54080fb3bcda7b513b5c89fChris Forbes                            use.first, string_VkFormat(rpci->pAttachments[index].format),
2940eeb9f6a27f1acc11e54080fb3bcda7b513b5c89fChris Forbes                            describe_type(module, use.second.type_id).c_str())) {
2941eeb9f6a27f1acc11e54080fb3bcda7b513b5c89fChris Forbes                    pass = false;
2942eeb9f6a27f1acc11e54080fb3bcda7b513b5c89fChris Forbes                }
2943eeb9f6a27f1acc11e54080fb3bcda7b513b5c89fChris Forbes            }
2944c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes        }
2945c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes    }
2946c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes
294778be5018e238bd464b1f1c55138df277c0c18922Chris Forbes    return pass;
294878be5018e238bd464b1f1c55138df277c0c18922Chris Forbes}
294978be5018e238bd464b1f1c55138df277c0c18922Chris Forbes
295078be5018e238bd464b1f1c55138df277c0c18922Chris Forbes
2951a61b537fcb6a4f7b92cd217b3964ad7a48109da1Tobin Ehlis// Validate that the shaders used by the given pipeline and store the active_slots
2952a61b537fcb6a4f7b92cd217b3964ad7a48109da1Tobin Ehlis//  that are actually used by the pipeline into pPipeline->active_slots
2953e4be8c69231df45752686575f22168b6d0fc5687Chris Forbesstatic bool validate_and_capture_pipeline_shader_state(debug_report_data *report_data, PIPELINE_NODE *pPipeline,
295469f9a551bfb1fd5334950f9685c12c5adda23dfbChris Forbes                                                       VkPhysicalDeviceFeatures const *enabledFeatures,
295569f9a551bfb1fd5334950f9685c12c5adda23dfbChris Forbes                                                       std::unordered_map<VkShaderModule, unique_ptr<shader_module>> const & shaderModuleMap) {
29566660d6f3e4e4c895063e8d99098162bd2f508b24Chris Forbes    auto pCreateInfo = pPipeline->graphicsPipelineCI.ptr();
29575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    int vertex_stage = get_shader_stage_id(VK_SHADER_STAGE_VERTEX_BIT);
29585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    int fragment_stage = get_shader_stage_id(VK_SHADER_STAGE_FRAGMENT_BIT);
29595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
29605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    shader_module *shaders[5];
29615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    memset(shaders, 0, sizeof(shaders));
29625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    spirv_inst_iter entrypoints[5];
29635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    memset(entrypoints, 0, sizeof(entrypoints));
29645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkPipelineVertexInputStateCreateInfo const *vi = 0;
2965e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool pass = true;
29665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
29675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) {
29686660d6f3e4e4c895063e8d99098162bd2f508b24Chris Forbes        auto pStage = &pCreateInfo->pStages[i];
296978be5018e238bd464b1f1c55138df277c0c18922Chris Forbes        auto stage_id = get_shader_stage_id(pStage->stage);
2970e4be8c69231df45752686575f22168b6d0fc5687Chris Forbes        pass &= validate_pipeline_shader_stage(report_data, pStage, pPipeline,
297169f9a551bfb1fd5334950f9685c12c5adda23dfbChris Forbes                                               &shaders[stage_id], &entrypoints[stage_id],
297269f9a551bfb1fd5334950f9685c12c5adda23dfbChris Forbes                                               enabledFeatures, shaderModuleMap);
29735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
29745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2975d5365427feb4a6c16371ecb651afa37b89dabd96Chris Forbes    // if the shader stages are no good individually, cross-stage validation is pointless.
2976b7476f4c4998ae20e579bd2d134667b71acdbf91Chris Forbes    if (!pass)
2977b7476f4c4998ae20e579bd2d134667b71acdbf91Chris Forbes        return false;
2978b7476f4c4998ae20e579bd2d134667b71acdbf91Chris Forbes
29795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    vi = pCreateInfo->pVertexInputState;
29805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
29815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (vi) {
2982e4be8c69231df45752686575f22168b6d0fc5687Chris Forbes        pass &= validate_vi_consistency(report_data, vi);
29835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
29845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
29855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (shaders[vertex_stage]) {
2986e4be8c69231df45752686575f22168b6d0fc5687Chris Forbes        pass &= validate_vi_against_vs_inputs(report_data, vi, shaders[vertex_stage], entrypoints[vertex_stage]);
29875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
29885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
29895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    int producer = get_shader_stage_id(VK_SHADER_STAGE_VERTEX_BIT);
29905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    int consumer = get_shader_stage_id(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
29915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
29925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    while (!shaders[producer] && producer != fragment_stage) {
29935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        producer++;
29945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        consumer++;
29955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
29965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
29975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (; producer != fragment_stage && consumer <= fragment_stage; consumer++) {
29985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        assert(shaders[producer]);
29995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (shaders[consumer]) {
3000e4be8c69231df45752686575f22168b6d0fc5687Chris Forbes            pass &= validate_interface_between_stages(report_data,
3001031261d21af8907953dd763398ce9a23e65b8749Chris Forbes                                                      shaders[producer], entrypoints[producer], &shader_stage_attribs[producer],
3002031261d21af8907953dd763398ce9a23e65b8749Chris Forbes                                                      shaders[consumer], entrypoints[consumer], &shader_stage_attribs[consumer]);
30035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
30045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            producer = consumer;
30055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
30065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
30075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
30088da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis    if (shaders[fragment_stage]) {
3009e4be8c69231df45752686575f22168b6d0fc5687Chris Forbes        pass &= validate_fs_outputs_against_render_pass(report_data, shaders[fragment_stage], entrypoints[fragment_stage],
30108da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis                                                        pPipeline->render_pass_ci.ptr(), pCreateInfo->subpass);
30115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
30125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
30135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return pass;
30145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
30155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3016e4be8c69231df45752686575f22168b6d0fc5687Chris Forbesstatic bool validate_compute_pipeline(debug_report_data *report_data, PIPELINE_NODE *pPipeline, VkPhysicalDeviceFeatures const *enabledFeatures,
301769f9a551bfb1fd5334950f9685c12c5adda23dfbChris Forbes                                      std::unordered_map<VkShaderModule, unique_ptr<shader_module>> const & shaderModuleMap) {
30186660d6f3e4e4c895063e8d99098162bd2f508b24Chris Forbes    auto pCreateInfo = pPipeline->computePipelineCI.ptr();
301903857e826cdc6e8d814137fb3245596ca1cb7bc7Chris Forbes
302003857e826cdc6e8d814137fb3245596ca1cb7bc7Chris Forbes    shader_module *module;
302103857e826cdc6e8d814137fb3245596ca1cb7bc7Chris Forbes    spirv_inst_iter entrypoint;
302203857e826cdc6e8d814137fb3245596ca1cb7bc7Chris Forbes
3023e4be8c69231df45752686575f22168b6d0fc5687Chris Forbes    return validate_pipeline_shader_stage(report_data, &pCreateInfo->stage, pPipeline,
302469f9a551bfb1fd5334950f9685c12c5adda23dfbChris Forbes                                          &module, &entrypoint, enabledFeatures, shaderModuleMap);
302503857e826cdc6e8d814137fb3245596ca1cb7bc7Chris Forbes}
30265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Return Set node ptr for specified set or else NULL
3027a682b1c533d9a492243b363c6585c4f03bcd87aaTobin Ehliscvdescriptorset::DescriptorSet *getSetNode(const layer_data *my_data, VkDescriptorSet set) {
3028104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis    auto set_it = my_data->setMap.find(set);
3029104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis    if (set_it == my_data->setMap.end()) {
30305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return NULL;
30315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
3032104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis    return set_it->second;
30335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
30347a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis// For the given command buffer, verify and update the state for activeSetBindingsPairs
30357a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis//  This includes:
30367a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis//  1. Verifying that any dynamic descriptor in that set has a valid dynamic offset bound.
30377a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis//     To be valid, the dynamic offset combined with the offset and range from its
30387a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis//     descriptor update must not overflow the size of its buffer being updated
30397a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis//  2. Grow updateImages for given pCB to include any bound STORAGE_IMAGE descriptor images
30407a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis//  3. Grow updateBuffers for pCB to include buffers from STORAGE*_BUFFER descriptor buffers
3041e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool validate_and_update_drawtime_descriptor_state(
30427a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis    layer_data *dev_data, GLOBAL_CB_NODE *pCB,
30431abb984ebd667af808ed308ddf79cbaeaed129caTobin Ehlis    const vector<std::tuple<cvdescriptorset::DescriptorSet *, std::map<uint32_t, descriptor_req>, std::vector<uint32_t> const *>>
30441abb984ebd667af808ed308ddf79cbaeaed129caTobin Ehlis        &activeSetBindingsPairs,
30451abb984ebd667af808ed308ddf79cbaeaed129caTobin Ehlis    const char *function) {
3046e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool result = false;
3047a61b537fcb6a4f7b92cd217b3964ad7a48109da1Tobin Ehlis    for (auto set_bindings_pair : activeSetBindingsPairs) {
3048dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes        cvdescriptorset::DescriptorSet *set_node = std::get<0>(set_bindings_pair);
3049cb9ce9e05b8e939d3da35c64997c70049877f4feTobin Ehlis        std::string err_str;
3050dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes        if (!set_node->ValidateDrawState(std::get<1>(set_bindings_pair), *std::get<2>(set_bindings_pair),
3051397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis                                         &err_str)) {
3052cb9ce9e05b8e939d3da35c64997c70049877f4feTobin Ehlis            // Report error here
3053397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis            auto set = set_node->GetSet();
3054cb9ce9e05b8e939d3da35c64997c70049877f4feTobin Ehlis            result |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
3055cb9ce9e05b8e939d3da35c64997c70049877f4feTobin Ehlis                              reinterpret_cast<const uint64_t &>(set), __LINE__, DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS",
3056e7f1fab24ce4b59bce87246a510b7e52638f83d0Mark Lobodzinski                              "DS 0x%" PRIxLEAST64 " encountered the following validation error at %s() time: %s",
3057e7f1fab24ce4b59bce87246a510b7e52638f83d0Mark Lobodzinski                              reinterpret_cast<const uint64_t &>(set), function, err_str.c_str());
3058cb9ce9e05b8e939d3da35c64997c70049877f4feTobin Ehlis        }
3059dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes        set_node->GetStorageUpdates(std::get<1>(set_bindings_pair), &pCB->updateBuffers, &pCB->updateImages);
30605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
30615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
30625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
30635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3064eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young// For given pipeline, return number of MSAA samples, or one if MSAA disabled
3065ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbesstatic VkSampleCountFlagBits getNumSamples(PIPELINE_NODE const *pipe) {
3066ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes    if (pipe->graphicsPipelineCI.pMultisampleState != NULL &&
3067ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes        VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO == pipe->graphicsPipelineCI.pMultisampleState->sType) {
3068eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young        return pipe->graphicsPipelineCI.pMultisampleState->rasterizationSamples;
3069eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young    }
3070eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young    return VK_SAMPLE_COUNT_1_BIT;
3071eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young}
3072eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young
3073b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbesstatic void list_bits(std::ostream& s, uint32_t bits) {
3074b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes    for (int i = 0; i < 32 && bits; i++) {
3075b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes        if (bits & (1 << i)) {
3076b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            s << i;
3077b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            bits &= ~(1 << i);
3078b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            if (bits) {
3079b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                s << ",";
3080b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            }
3081b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes        }
3082b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes    }
3083b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes}
3084b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes
3085eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young// Validate draw-time state related to the PSO
308629d196e071b2dc1db47702085469396f2b956820Chris Forbesstatic bool validatePipelineDrawtimeState(layer_data const *my_data,
308729d196e071b2dc1db47702085469396f2b956820Chris Forbes                                          LAST_BOUND_STATE const &state,
308829d196e071b2dc1db47702085469396f2b956820Chris Forbes                                          const GLOBAL_CB_NODE *pCB,
308929d196e071b2dc1db47702085469396f2b956820Chris Forbes                                          PIPELINE_NODE const *pPipeline) {
3090eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young    bool skip_call = false;
309129d196e071b2dc1db47702085469396f2b956820Chris Forbes
309229d196e071b2dc1db47702085469396f2b956820Chris Forbes    // Verify Vtx binding
309329d196e071b2dc1db47702085469396f2b956820Chris Forbes    if (pPipeline->vertexBindingDescriptions.size() > 0) {
309429d196e071b2dc1db47702085469396f2b956820Chris Forbes        for (size_t i = 0; i < pPipeline->vertexBindingDescriptions.size(); i++) {
3095312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis            auto vertex_binding = pPipeline->vertexBindingDescriptions[i].binding;
3096312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis            if ((pCB->currentDrawData.buffers.size() < (vertex_binding + 1)) ||
3097312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis                (pCB->currentDrawData.buffers[vertex_binding] == VK_NULL_HANDLE)) {
3098312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis                skip_call |= log_msg(
3099312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis                    my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
3100312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis                    DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS",
3101312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis                    "The Pipeline State Object (0x%" PRIxLEAST64 ") expects that this Command Buffer's vertex binding Index %u "
3102312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis                    "should be set via vkCmdBindVertexBuffers. This is because VkVertexInputBindingDescription struct "
3103312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis                    "at index " PRINTF_SIZE_T_SPECIFIER " of pVertexBindingDescriptions has a binding value of %u.",
31045c288f35b2eab0dab95d18768235fef6ffd69b30Tobin Ehlis                    (uint64_t)state.pipeline_node->pipeline, vertex_binding, i, vertex_binding);
310529d196e071b2dc1db47702085469396f2b956820Chris Forbes            }
310629d196e071b2dc1db47702085469396f2b956820Chris Forbes        }
310729d196e071b2dc1db47702085469396f2b956820Chris Forbes    } else {
310829d196e071b2dc1db47702085469396f2b956820Chris Forbes        if (!pCB->currentDrawData.buffers.empty()) {
310929d196e071b2dc1db47702085469396f2b956820Chris Forbes            skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0,
31105c288f35b2eab0dab95d18768235fef6ffd69b30Tobin Ehlis                                 0, __LINE__, DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS",
31115c288f35b2eab0dab95d18768235fef6ffd69b30Tobin Ehlis                                 "Vertex buffers are bound to command buffer (0x%" PRIxLEAST64
31125c288f35b2eab0dab95d18768235fef6ffd69b30Tobin Ehlis                                 ") but no vertex buffers are attached to this Pipeline State Object (0x%" PRIxLEAST64 ").",
31135c288f35b2eab0dab95d18768235fef6ffd69b30Tobin Ehlis                                 (uint64_t)pCB->commandBuffer, (uint64_t)state.pipeline_node->pipeline);
311429d196e071b2dc1db47702085469396f2b956820Chris Forbes        }
311529d196e071b2dc1db47702085469396f2b956820Chris Forbes    }
311629d196e071b2dc1db47702085469396f2b956820Chris Forbes    // If Viewport or scissors are dynamic, verify that dynamic count matches PSO count.
311729d196e071b2dc1db47702085469396f2b956820Chris Forbes    // Skip check if rasterization is disabled or there is no viewport.
311829d196e071b2dc1db47702085469396f2b956820Chris Forbes    if ((!pPipeline->graphicsPipelineCI.pRasterizationState ||
311929d196e071b2dc1db47702085469396f2b956820Chris Forbes         (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) &&
312029d196e071b2dc1db47702085469396f2b956820Chris Forbes        pPipeline->graphicsPipelineCI.pViewportState) {
312129d196e071b2dc1db47702085469396f2b956820Chris Forbes        bool dynViewport = isDynamic(pPipeline, VK_DYNAMIC_STATE_VIEWPORT);
312229d196e071b2dc1db47702085469396f2b956820Chris Forbes        bool dynScissor = isDynamic(pPipeline, VK_DYNAMIC_STATE_SCISSOR);
3123b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes
312429d196e071b2dc1db47702085469396f2b956820Chris Forbes        if (dynViewport) {
3125b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            auto requiredViewportsMask = (1 << pPipeline->graphicsPipelineCI.pViewportState->viewportCount) - 1;
3126b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            auto missingViewportMask = ~pCB->viewportMask & requiredViewportsMask;
3127b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            if (missingViewportMask) {
3128b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                std::stringstream ss;
3129b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                ss << "Dynamic viewport(s) ";
3130b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                list_bits(ss, missingViewportMask);
3131b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                ss << " are used by PSO, but were not provided via calls to vkCmdSetViewport().";
3132b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0,
3133b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                                     __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS",
3134b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                                     "%s", ss.str().c_str());
313529d196e071b2dc1db47702085469396f2b956820Chris Forbes            }
313629d196e071b2dc1db47702085469396f2b956820Chris Forbes        }
3137b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes
313829d196e071b2dc1db47702085469396f2b956820Chris Forbes        if (dynScissor) {
3139b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            auto requiredScissorMask = (1 << pPipeline->graphicsPipelineCI.pViewportState->scissorCount) - 1;
3140b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            auto missingScissorMask = ~pCB->scissorMask & requiredScissorMask;
3141b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            if (missingScissorMask) {
3142b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                std::stringstream ss;
3143b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                ss << "Dynamic scissor(s) ";
3144b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                list_bits(ss, missingScissorMask);
3145b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                ss << " are used by PSO, but were not provided via calls to vkCmdSetScissor().";
3146b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0,
3147b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                                     __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS",
3148b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                                     "%s", ss.str().c_str());
314929d196e071b2dc1db47702085469396f2b956820Chris Forbes            }
315029d196e071b2dc1db47702085469396f2b956820Chris Forbes        }
315129d196e071b2dc1db47702085469396f2b956820Chris Forbes    }
315229d196e071b2dc1db47702085469396f2b956820Chris Forbes
315329d196e071b2dc1db47702085469396f2b956820Chris Forbes    // Verify that any MSAA request in PSO matches sample# in bound FB
315429d196e071b2dc1db47702085469396f2b956820Chris Forbes    // Skip the check if rasterization is disabled.
315529d196e071b2dc1db47702085469396f2b956820Chris Forbes    if (!pPipeline->graphicsPipelineCI.pRasterizationState ||
315629d196e071b2dc1db47702085469396f2b956820Chris Forbes        (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) {
315729d196e071b2dc1db47702085469396f2b956820Chris Forbes        VkSampleCountFlagBits pso_num_samples = getNumSamples(pPipeline);
315829d196e071b2dc1db47702085469396f2b956820Chris Forbes        if (pCB->activeRenderPass) {
3159fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes            auto const render_pass_info = pCB->activeRenderPass->createInfo.ptr();
316029d196e071b2dc1db47702085469396f2b956820Chris Forbes            const VkSubpassDescription *subpass_desc = &render_pass_info->pSubpasses[pCB->activeSubpass];
316129d196e071b2dc1db47702085469396f2b956820Chris Forbes            uint32_t i;
316229d196e071b2dc1db47702085469396f2b956820Chris Forbes
316329d196e071b2dc1db47702085469396f2b956820Chris Forbes            const safe_VkPipelineColorBlendStateCreateInfo *color_blend_state = pPipeline->graphicsPipelineCI.pColorBlendState;
316429d196e071b2dc1db47702085469396f2b956820Chris Forbes            if ((color_blend_state != NULL) && (pCB->activeSubpass == pPipeline->graphicsPipelineCI.subpass) &&
316529d196e071b2dc1db47702085469396f2b956820Chris Forbes                (color_blend_state->attachmentCount != subpass_desc->colorAttachmentCount)) {
316629d196e071b2dc1db47702085469396f2b956820Chris Forbes                skip_call |=
3167eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young                        log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
3168ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes                                reinterpret_cast<const uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
3169eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young                                "Render pass subpass %u mismatch with blending state defined and blend state attachment "
3170414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                "count %u while subpass color attachment count %u in Pipeline (0x%" PRIxLEAST64 ")!  These "
3171eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young                                "must be the same at draw-time.",
3172eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young                                pCB->activeSubpass, color_blend_state->attachmentCount, subpass_desc->colorAttachmentCount,
3173ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes                                reinterpret_cast<const uint64_t &>(pPipeline->pipeline));
317429d196e071b2dc1db47702085469396f2b956820Chris Forbes            }
3175eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young
317676957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes            unsigned subpass_num_samples = 0;
31770a7ed0466d3d3c6c71be07d66c200482d9a9d073Chris Forbes
317829d196e071b2dc1db47702085469396f2b956820Chris Forbes            for (i = 0; i < subpass_desc->colorAttachmentCount; i++) {
317976957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes                auto attachment = subpass_desc->pColorAttachments[i].attachment;
318076957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes                if (attachment != VK_ATTACHMENT_UNUSED)
318176957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes                    subpass_num_samples |= (unsigned)render_pass_info->pAttachments[attachment].samples;
318229d196e071b2dc1db47702085469396f2b956820Chris Forbes            }
31830a7ed0466d3d3c6c71be07d66c200482d9a9d073Chris Forbes
318476957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes            if (subpass_desc->pDepthStencilAttachment &&
318576957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes                subpass_desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
318676957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes                auto attachment = subpass_desc->pDepthStencilAttachment->attachment;
318776957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes                subpass_num_samples |= (unsigned)render_pass_info->pAttachments[attachment].samples;
318829d196e071b2dc1db47702085469396f2b956820Chris Forbes            }
3189eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young
31900dc3fd4e57b8531638781daa01a2fb5d1048a6fbJamie Madill            if (subpass_num_samples && static_cast<unsigned>(pso_num_samples) != subpass_num_samples) {
319129d196e071b2dc1db47702085469396f2b956820Chris Forbes                skip_call |=
3192eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young                        log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
3193ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes                                reinterpret_cast<const uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_NUM_SAMPLES_MISMATCH, "DS",
3194414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                "Num samples mismatch! At draw-time in Pipeline (0x%" PRIxLEAST64
3195414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                ") with %u samples while current RenderPass (0x%" PRIxLEAST64 ") w/ %u samples!",
3196ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes                                reinterpret_cast<const uint64_t &>(pPipeline->pipeline), pso_num_samples,
3197ee691f5c5fa87aac3750454d2bca2cb582e4e817Chris Forbes                                reinterpret_cast<const uint64_t &>(pCB->activeRenderPass->renderPass), subpass_num_samples);
3198eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young            }
319929d196e071b2dc1db47702085469396f2b956820Chris Forbes        } else {
320029d196e071b2dc1db47702085469396f2b956820Chris Forbes            skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
320129d196e071b2dc1db47702085469396f2b956820Chris Forbes                                 reinterpret_cast<const uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_NUM_SAMPLES_MISMATCH, "DS",
320229d196e071b2dc1db47702085469396f2b956820Chris Forbes                                 "No active render pass found at draw-time in Pipeline (0x%" PRIxLEAST64 ")!",
320329d196e071b2dc1db47702085469396f2b956820Chris Forbes                                 reinterpret_cast<const uint64_t &>(pPipeline->pipeline));
3204eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young        }
3205eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young    }
3206528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis    // Verify that PSO creation renderPass is compatible with active renderPass
3207528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis    if (pCB->activeRenderPass) {
3208528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis        std::string err_string;
3209a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis        if ((pCB->activeRenderPass->renderPass != pPipeline->graphicsPipelineCI.renderPass) &&
3210fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes            !verify_renderpass_compatibility(my_data, pCB->activeRenderPass->createInfo.ptr(), pPipeline->render_pass_ci.ptr(),
3211528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis                                             err_string)) {
3212528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis            // renderPass that PSO was created with must be compatible with active renderPass that PSO is being used with
3213528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis            skip_call |=
3214528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis                log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
3215528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis                        reinterpret_cast<const uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS",
3216528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis                        "At Draw time the active render pass (0x%" PRIxLEAST64 ") is incompatible w/ gfx pipeline "
3217528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis                        "(0x%" PRIxLEAST64 ") that was created w/ render pass (0x%" PRIxLEAST64 ") due to: %s",
3218528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis                        reinterpret_cast<uint64_t &>(pCB->activeRenderPass->renderPass), reinterpret_cast<uint64_t &>(pPipeline),
3219528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis                        reinterpret_cast<const uint64_t &>(pPipeline->graphicsPipelineCI.renderPass), err_string.c_str());
3220528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis        }
3221c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes
3222c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes        if (pPipeline->graphicsPipelineCI.subpass != pCB->activeSubpass) {
3223c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes            skip_call |=
3224c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes                log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
3225c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes                        reinterpret_cast<uint64_t const &>(pPipeline->pipeline), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS",
3226c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes                        "Pipeline was built for subpass %u but used in subpass %u", pPipeline->graphicsPipelineCI.subpass,
3227c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes                        pCB->activeSubpass);
3228c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes        }
3229528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis    }
323029d196e071b2dc1db47702085469396f2b956820Chris Forbes    // TODO : Add more checks here
323129d196e071b2dc1db47702085469396f2b956820Chris Forbes
3232eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young    return skip_call;
3233eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young}
3234eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young
32355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate overall state at the time of a draw call
3236aa21bc3b3c5c7adfeb488fc80bdcb339d63615b8Tobin Ehlisstatic bool validate_and_update_draw_state(layer_data *my_data, GLOBAL_CB_NODE *cb_node, const bool indexedDraw,
3237e7f1fab24ce4b59bce87246a510b7e52638f83d0Mark Lobodzinski                                           const VkPipelineBindPoint bindPoint, const char *function) {
3238e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool result = false;
3239aa21bc3b3c5c7adfeb488fc80bdcb339d63615b8Tobin Ehlis    auto const &state = cb_node->lastBound[bindPoint];
32405c288f35b2eab0dab95d18768235fef6ffd69b30Tobin Ehlis    PIPELINE_NODE *pPipe = state.pipeline_node;
324122fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis    if (nullptr == pPipe) {
324222fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis        result |= log_msg(
324322fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis            my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__,
324422fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis            DRAWSTATE_INVALID_PIPELINE, "DS",
324522fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis            "At Draw/Dispatch time no valid VkPipeline is bound! This is illegal. Please bind one with vkCmdBindPipeline().");
324622fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis        // Early return as any further checks below will be busted w/o a pipeline
324722fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis        if (result)
324822fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis            return true;
324922fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis    }
32503d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    // First check flag states
32517a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis    if (VK_PIPELINE_BIND_POINT_GRAPHICS == bindPoint)
3252aa21bc3b3c5c7adfeb488fc80bdcb339d63615b8Tobin Ehlis        result = validate_draw_state_flags(my_data, cb_node, pPipe, indexedDraw);
32537a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis
32545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Now complete other state checks
325569b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis    if (VK_NULL_HANDLE != state.pipeline_layout.layout) {
325622fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis        string errorString;
325769b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis        auto pipeline_layout = pPipe->pipeline_layout;
3258169c4506062f06d6676eb4da3c9e0437d1d9d659Chris Forbes
325922fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis        // Need a vector (vs. std::set) of active Sets for dynamicOffset validation in case same set bound w/ different offsets
32601abb984ebd667af808ed308ddf79cbaeaed129caTobin Ehlis        vector<std::tuple<cvdescriptorset::DescriptorSet *, std::map<uint32_t, descriptor_req>, std::vector<uint32_t> const *>>
32611abb984ebd667af808ed308ddf79cbaeaed129caTobin Ehlis            activeSetBindingsPairs;
3262dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes        for (auto & setBindingPair : pPipe->active_slots) {
326322fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis            uint32_t setIndex = setBindingPair.first;
326422fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis            // If valid set is not bound throw an error
326522fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis            if ((state.boundDescriptorSets.size() <= setIndex) || (!state.boundDescriptorSets[setIndex])) {
326622fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis                result |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
326722fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis                                  DRAWSTATE_DESCRIPTOR_SET_NOT_BOUND, "DS",
3268414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                  "VkPipeline 0x%" PRIxLEAST64 " uses set #%u but that set is not bound.", (uint64_t)pPipe->pipeline,
326922fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis                                  setIndex);
327069b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis            } else if (!verify_set_layout_compatibility(my_data, state.boundDescriptorSets[setIndex], &pipeline_layout, setIndex,
327169b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis                                                        errorString)) {
327269b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis                // Set is bound but not compatible w/ overlapping pipeline_layout from PSO
327371511c5a10533c910bfe62c3bcf58e2a4054e7acTobin Ehlis                VkDescriptorSet setHandle = state.boundDescriptorSets[setIndex]->GetSet();
327422fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis                result |=
327522fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis                    log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
327622fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis                            (uint64_t)setHandle, __LINE__, DRAWSTATE_PIPELINE_LAYOUTS_INCOMPATIBLE, "DS",
3277414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                            "VkDescriptorSet (0x%" PRIxLEAST64
3278414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                            ") bound as set #%u is not compatible with overlapping VkPipelineLayout 0x%" PRIxLEAST64 " due to: %s",
327969b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis                            reinterpret_cast<uint64_t &>(setHandle), setIndex, reinterpret_cast<uint64_t &>(pipeline_layout.layout),
328069b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis                            errorString.c_str());
328122fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis            } else { // Valid set is bound and layout compatible, validate that it's updated
328222fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis                // Pull the set node
328371511c5a10533c910bfe62c3bcf58e2a4054e7acTobin Ehlis                cvdescriptorset::DescriptorSet *pSet = state.boundDescriptorSets[setIndex];
3284aa21bc3b3c5c7adfeb488fc80bdcb339d63615b8Tobin Ehlis                // Gather active bindings
3285aa21bc3b3c5c7adfeb488fc80bdcb339d63615b8Tobin Ehlis                std::unordered_set<uint32_t> bindings;
3286aa21bc3b3c5c7adfeb488fc80bdcb339d63615b8Tobin Ehlis                for (auto binding : setBindingPair.second) {
3287aa21bc3b3c5c7adfeb488fc80bdcb339d63615b8Tobin Ehlis                    bindings.insert(binding.first);
3288aa21bc3b3c5c7adfeb488fc80bdcb339d63615b8Tobin Ehlis                }
3289aa21bc3b3c5c7adfeb488fc80bdcb339d63615b8Tobin Ehlis                // Bind this set and its active descriptor resources to the command buffer
3290aa21bc3b3c5c7adfeb488fc80bdcb339d63615b8Tobin Ehlis                pSet->BindCommandBuffer(cb_node, bindings);
329122fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis                // Save vector of all active sets to verify dynamicOffsets below
3292aa21bc3b3c5c7adfeb488fc80bdcb339d63615b8Tobin Ehlis                activeSetBindingsPairs.push_back(std::make_tuple(pSet, setBindingPair.second, &state.dynamicOffsets[setIndex]));
329322fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis                // Make sure set has been updated if it has no immutable samplers
329422fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis                //  If it has immutable samplers, we'll flag error later as needed depending on binding
3295397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis                if (!pSet->IsUpdated()) {
3296aa21bc3b3c5c7adfeb488fc80bdcb339d63615b8Tobin Ehlis                    for (auto binding : bindings) {
3297aa21bc3b3c5c7adfeb488fc80bdcb339d63615b8Tobin Ehlis                        if (!pSet->GetImmutableSamplerPtrFromBinding(binding)) {
329822fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis                            result |= log_msg(
329922fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis                                my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
3300397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis                                (uint64_t)pSet->GetSet(), __LINE__, DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS",
3301414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                "DS 0x%" PRIxLEAST64 " bound but it was never updated. It is now being used to draw so "
330222fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis                                "this will result in undefined behavior.",
3303397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis                                (uint64_t)pSet->GetSet());
3304fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis                        }
33055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
33065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
33075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
330822fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis        }
330922fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis        // For given active slots, verify any dynamic descriptors and record updated images & buffers
3310aa21bc3b3c5c7adfeb488fc80bdcb339d63615b8Tobin Ehlis        result |= validate_and_update_drawtime_descriptor_state(my_data, cb_node, activeSetBindingsPairs, function);
331122fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis    }
3312eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young
3313eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young    // Check general pipeline state that needs to be validated at drawtime
331429d196e071b2dc1db47702085469396f2b956820Chris Forbes    if (VK_PIPELINE_BIND_POINT_GRAPHICS == bindPoint)
3315aa21bc3b3c5c7adfeb488fc80bdcb339d63615b8Tobin Ehlis        result |= validatePipelineDrawtimeState(my_data, state, cb_node, pPipe);
3316eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young
33175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
33185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
33195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3320a27508babf63d50aea75883a3702979193c23683Mark Young// Validate HW line width capabilities prior to setting requested line width.
3321a27508babf63d50aea75883a3702979193c23683Mark Youngstatic bool verifyLineWidth(layer_data *my_data, DRAW_STATE_ERROR dsError, const uint64_t &target, float lineWidth) {
3322a27508babf63d50aea75883a3702979193c23683Mark Young    bool skip_call = false;
3323a27508babf63d50aea75883a3702979193c23683Mark Young
3324a27508babf63d50aea75883a3702979193c23683Mark Young    // First check to see if the physical device supports wide lines.
3325f71dd305f197826a61f398bff725267a20ea1d90Chris Forbes    if ((VK_FALSE == my_data->enabled_features.wideLines) && (1.0f != lineWidth)) {
3326a27508babf63d50aea75883a3702979193c23683Mark Young        skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, target, __LINE__,
3327a27508babf63d50aea75883a3702979193c23683Mark Young                             dsError, "DS", "Attempt to set lineWidth to %f but physical device wideLines feature "
3328a27508babf63d50aea75883a3702979193c23683Mark Young                                            "not supported/enabled so lineWidth must be 1.0f!",
3329a27508babf63d50aea75883a3702979193c23683Mark Young                             lineWidth);
3330a27508babf63d50aea75883a3702979193c23683Mark Young    } else {
3331a27508babf63d50aea75883a3702979193c23683Mark Young        // Otherwise, make sure the width falls in the valid range.
3332a27508babf63d50aea75883a3702979193c23683Mark Young        if ((my_data->phys_dev_properties.properties.limits.lineWidthRange[0] > lineWidth) ||
3333a27508babf63d50aea75883a3702979193c23683Mark Young            (my_data->phys_dev_properties.properties.limits.lineWidthRange[1] < lineWidth)) {
3334a27508babf63d50aea75883a3702979193c23683Mark Young            skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, target,
3335a27508babf63d50aea75883a3702979193c23683Mark Young                                 __LINE__, dsError, "DS", "Attempt to set lineWidth to %f but physical device limits line width "
3336a27508babf63d50aea75883a3702979193c23683Mark Young                                                          "to between [%f, %f]!",
3337a27508babf63d50aea75883a3702979193c23683Mark Young                                 lineWidth, my_data->phys_dev_properties.properties.limits.lineWidthRange[0],
3338a27508babf63d50aea75883a3702979193c23683Mark Young                                 my_data->phys_dev_properties.properties.limits.lineWidthRange[1]);
3339a27508babf63d50aea75883a3702979193c23683Mark Young        }
3340a27508babf63d50aea75883a3702979193c23683Mark Young    }
3341a27508babf63d50aea75883a3702979193c23683Mark Young
3342a27508babf63d50aea75883a3702979193c23683Mark Young    return skip_call;
3343a27508babf63d50aea75883a3702979193c23683Mark Young}
3344a27508babf63d50aea75883a3702979193c23683Mark Young
33455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Verify that create state for a pipeline is valid
3346e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool verifyPipelineCreateState(layer_data *my_data, const VkDevice device, std::vector<PIPELINE_NODE *> pPipelines,
3347e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                                      int pipelineIndex) {
334883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
33495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
33505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    PIPELINE_NODE *pPipeline = pPipelines[pipelineIndex];
33515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
33525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // If create derivative bit is set, check that we've specified a base
33535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // pipeline correctly, and that the base pipeline was created to allow
33545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // derivatives.
33555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pPipeline->graphicsPipelineCI.flags & VK_PIPELINE_CREATE_DERIVATIVE_BIT) {
33565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        PIPELINE_NODE *pBasePipeline = nullptr;
33575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (!((pPipeline->graphicsPipelineCI.basePipelineHandle != VK_NULL_HANDLE) ^
33585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis              (pPipeline->graphicsPipelineCI.basePipelineIndex != -1))) {
335983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
336083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS",
336183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 "Invalid Pipeline CreateInfo: exactly one of base pipeline index and handle must be specified");
33625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else if (pPipeline->graphicsPipelineCI.basePipelineIndex != -1) {
33635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (pPipeline->graphicsPipelineCI.basePipelineIndex >= pipelineIndex) {
336483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                skip_call |=
33655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
33665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS",
33675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            "Invalid Pipeline CreateInfo: base pipeline must occur earlier in array than derivative pipeline.");
33685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            } else {
33695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                pBasePipeline = pPipelines[pPipeline->graphicsPipelineCI.basePipelineIndex];
33705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
33715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else if (pPipeline->graphicsPipelineCI.basePipelineHandle != VK_NULL_HANDLE) {
33725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            pBasePipeline = getPipeline(my_data, pPipeline->graphicsPipelineCI.basePipelineHandle);
33735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
33745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
33755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (pBasePipeline && !(pBasePipeline->graphicsPipelineCI.flags & VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT)) {
337683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
337783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS",
337883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 "Invalid Pipeline CreateInfo: base pipeline does not allow derivatives.");
33795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
33805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
33815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
33825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pPipeline->graphicsPipelineCI.pColorBlendState != NULL) {
3383f71dd305f197826a61f398bff725267a20ea1d90Chris Forbes        if (!my_data->enabled_features.independentBlend) {
33843d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis            if (pPipeline->attachments.size() > 1) {
338526c548826ff0f83d12c769b51e7d6f76d1265c0eChris Forbes                VkPipelineColorBlendAttachmentState *pAttachments = &pPipeline->attachments[0];
3386c7bd67f06427b08ba65cdf2dd529c8234beebdd5Mark Lobodzinski                for (size_t i = 1; i < pPipeline->attachments.size(); i++) {
338706811df0256552cd7da9d7297672af377463fc4aMark Mueller                    // Quoting the spec: "If [the independent blend] feature is not enabled, the VkPipelineColorBlendAttachmentState
338806811df0256552cd7da9d7297672af377463fc4aMark Mueller                    // settings for all color attachments must be identical." VkPipelineColorBlendAttachmentState contains
338906811df0256552cd7da9d7297672af377463fc4aMark Mueller                    // only attachment state, so memcmp is best suited for the comparison
339006811df0256552cd7da9d7297672af377463fc4aMark Mueller                    if (memcmp(static_cast<const void *>(pAttachments), static_cast<const void *>(&pAttachments[i]),
339106811df0256552cd7da9d7297672af377463fc4aMark Mueller                               sizeof(pAttachments[0]))) {
339283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                        skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
339383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                             __LINE__, DRAWSTATE_INDEPENDENT_BLEND, "DS",
339483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                             "Invalid Pipeline CreateInfo: If independent blend feature not "
339583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                             "enabled, all elements of pAttachments must be identical");
339606811df0256552cd7da9d7297672af377463fc4aMark Mueller                        break;
3397c7bd67f06427b08ba65cdf2dd529c8234beebdd5Mark Lobodzinski                    }
33985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
33995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
34005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
3401f71dd305f197826a61f398bff725267a20ea1d90Chris Forbes        if (!my_data->enabled_features.logicOp &&
34025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            (pPipeline->graphicsPipelineCI.pColorBlendState->logicOpEnable != VK_FALSE)) {
340383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |=
34045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
34055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        DRAWSTATE_DISABLED_LOGIC_OP, "DS",
34065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        "Invalid Pipeline CreateInfo: If logic operations feature not enabled, logicOpEnable must be VK_FALSE");
34075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
34085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
34095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3410a61b537fcb6a4f7b92cd217b3964ad7a48109da1Tobin Ehlis    // Ensure the subpass index is valid. If not, then validate_and_capture_pipeline_shader_state
34115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // produces nonsense errors that confuse users. Other layers should already
34125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // emit errors for renderpass being invalid.
341316387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes    auto renderPass = getRenderPass(my_data, pPipeline->graphicsPipelineCI.renderPass);
3414fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes    if (renderPass && pPipeline->graphicsPipelineCI.subpass >= renderPass->createInfo.subpassCount) {
341583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
341683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                             DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", "Invalid Pipeline CreateInfo State: Subpass index %u "
341783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                                                            "is out of range for this renderpass (0..%u)",
3418fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes                             pPipeline->graphicsPipelineCI.subpass, renderPass->createInfo.subpassCount - 1);
34195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
34205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3421f71dd305f197826a61f398bff725267a20ea1d90Chris Forbes    if (!validate_and_capture_pipeline_shader_state(my_data->report_data, pPipeline, &my_data->enabled_features,
342269f9a551bfb1fd5334950f9685c12c5adda23dfbChris Forbes                                                    my_data->shaderModuleMap)) {
342383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call = true;
34245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
342552156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes    // Each shader's stage must be unique
342652156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes    if (pPipeline->duplicate_shaders) {
342752156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes        for (uint32_t stage = VK_SHADER_STAGE_VERTEX_BIT; stage & VK_SHADER_STAGE_ALL_GRAPHICS; stage <<= 1) {
342852156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes            if (pPipeline->duplicate_shaders & stage) {
342983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0,
343083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                     __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS",
343183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                     "Invalid Pipeline CreateInfo State: Multiple shaders provided for stage %s",
343283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                     string_VkShaderStageFlagBits(VkShaderStageFlagBits(stage)));
343352156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes            }
343452156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes        }
343552156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes    }
34365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // VS is required
34375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (!(pPipeline->active_shaders & VK_SHADER_STAGE_VERTEX_BIT)) {
343883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |=
34395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
34405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", "Invalid Pipeline CreateInfo State: Vtx Shader required");
34415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
34425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Either both or neither TC/TE shaders should be defined
34435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (((pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) == 0) !=
34445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        ((pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) == 0)) {
344583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
344683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                             DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS",
344783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                             "Invalid Pipeline CreateInfo State: TE and TC shaders must be included or excluded as a pair");
34485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
34495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Compute shaders should be specified independent of Gfx shaders
34505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if ((pPipeline->active_shaders & VK_SHADER_STAGE_COMPUTE_BIT) &&
34515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        (pPipeline->active_shaders &
34525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis         (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT |
34535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis          VK_SHADER_STAGE_GEOMETRY_BIT | VK_SHADER_STAGE_FRAGMENT_BIT))) {
345483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
345583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                             DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS",
345683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                             "Invalid Pipeline CreateInfo State: Do not specify Compute Shader for Gfx Pipeline");
34575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
34585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive topology is only valid for tessellation pipelines.
34595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Mismatching primitive topology and tessellation fails graphics pipeline creation.
34605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pPipeline->active_shaders & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) &&
3461ca546210846c65808717f8875deae39bd227c240Tobin Ehlis        (!pPipeline->graphicsPipelineCI.pInputAssemblyState ||
3462ca546210846c65808717f8875deae39bd227c240Tobin Ehlis         pPipeline->graphicsPipelineCI.pInputAssemblyState->topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)) {
346383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
346483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                             DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", "Invalid Pipeline CreateInfo State: "
346583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                                                            "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST must be set as IA "
346683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                                                            "topology for tessellation pipelines");
34675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
3468ca546210846c65808717f8875deae39bd227c240Tobin Ehlis    if (pPipeline->graphicsPipelineCI.pInputAssemblyState &&
3469ca546210846c65808717f8875deae39bd227c240Tobin Ehlis        pPipeline->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST) {
34705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (~pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) {
347183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |=
347283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
347383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                        DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", "Invalid Pipeline CreateInfo State: "
347483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                                                       "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive "
347583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                                                       "topology is only valid for tessellation pipelines");
34765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
3477ca546210846c65808717f8875deae39bd227c240Tobin Ehlis        if (!pPipeline->graphicsPipelineCI.pTessellationState) {
347883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
347983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS",
348083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 "Invalid Pipeline CreateInfo State: "
348183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 "pTessellationState is NULL when VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive "
348283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 "topology used. pTessellationState must not be NULL in this case.");
3483ca546210846c65808717f8875deae39bd227c240Tobin Ehlis        } else if (!pPipeline->graphicsPipelineCI.pTessellationState->patchControlPoints ||
3484ca546210846c65808717f8875deae39bd227c240Tobin Ehlis                   (pPipeline->graphicsPipelineCI.pTessellationState->patchControlPoints > 32)) {
348583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
348683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", "Invalid Pipeline CreateInfo State: "
348783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                                                                "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive "
348883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                                                                "topology used with patchControlPoints value %u."
348983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                                                                " patchControlPoints should be >0 and <=32.",
349083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 pPipeline->graphicsPipelineCI.pTessellationState->patchControlPoints);
34915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
34925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
3493a27508babf63d50aea75883a3702979193c23683Mark Young    // If a rasterization state is provided, make sure that the line width conforms to the HW.
3494a27508babf63d50aea75883a3702979193c23683Mark Young    if (pPipeline->graphicsPipelineCI.pRasterizationState) {
3495a27508babf63d50aea75883a3702979193c23683Mark Young        if (!isDynamic(pPipeline, VK_DYNAMIC_STATE_LINE_WIDTH)) {
349683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= verifyLineWidth(my_data, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, reinterpret_cast<uint64_t &>(pPipeline),
349783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                         pPipeline->graphicsPipelineCI.pRasterizationState->lineWidth);
3498a27508babf63d50aea75883a3702979193c23683Mark Young        }
3499a27508babf63d50aea75883a3702979193c23683Mark Young    }
35005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Viewport state must be included if rasterization is enabled.
35015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // If the viewport state is included, the viewport and scissor counts should always match.
35025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // NOTE : Even if these are flagged as dynamic, counts need to be set correctly for shader compiler
35035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (!pPipeline->graphicsPipelineCI.pRasterizationState ||
350445824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves        (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) {
35055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (!pPipeline->graphicsPipelineCI.pViewportState) {
350683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
350783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS", "Gfx Pipeline pViewportState is null. Even if viewport "
350883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                                                            "and scissors are dynamic PSO must include "
350983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                                                            "viewportCount and scissorCount in pViewportState.");
35105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else if (pPipeline->graphicsPipelineCI.pViewportState->scissorCount !=
35115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                   pPipeline->graphicsPipelineCI.pViewportState->viewportCount) {
351283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
351383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS",
351483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 "Gfx Pipeline viewport count (%u) must match scissor count (%u).",
351583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 pPipeline->graphicsPipelineCI.pViewportState->viewportCount,
351683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 pPipeline->graphicsPipelineCI.pViewportState->scissorCount);
35175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
35185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // If viewport or scissor are not dynamic, then verify that data is appropriate for count
3519e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves            bool dynViewport = isDynamic(pPipeline, VK_DYNAMIC_STATE_VIEWPORT);
3520e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves            bool dynScissor = isDynamic(pPipeline, VK_DYNAMIC_STATE_SCISSOR);
35215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (!dynViewport) {
35225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if (pPipeline->graphicsPipelineCI.pViewportState->viewportCount &&
35235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    !pPipeline->graphicsPipelineCI.pViewportState->pViewports) {
352483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                    skip_call |=
352583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                        log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
352683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS",
352783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                "Gfx Pipeline viewportCount is %u, but pViewports is NULL. For non-zero viewportCount, you "
352883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                "must either include pViewports data, or include viewport in pDynamicState and set it with "
352983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                "vkCmdSetViewport().",
353083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                pPipeline->graphicsPipelineCI.pViewportState->viewportCount);
35315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
35325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
35335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (!dynScissor) {
35345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if (pPipeline->graphicsPipelineCI.pViewportState->scissorCount &&
35355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    !pPipeline->graphicsPipelineCI.pViewportState->pScissors) {
353683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                    skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
353783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                         __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS",
353883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                         "Gfx Pipeline scissorCount is %u, but pScissors is NULL. For non-zero scissorCount, you "
353983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                         "must either include pScissors data, or include scissor in pDynamicState and set it with "
354083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                         "vkCmdSetScissor().",
354183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                         pPipeline->graphicsPipelineCI.pViewportState->scissorCount);
35425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
35435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
35445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
35455dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes
35465dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes        // If rasterization is not disabled, and subpass uses a depth/stencil
35475dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes        // attachment, pDepthStencilState must be a pointer to a valid structure
3548fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes        auto subpass_desc = renderPass ? &renderPass->createInfo.pSubpasses[pPipeline->graphicsPipelineCI.subpass] : nullptr;
35495dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes        if (subpass_desc && subpass_desc->pDepthStencilAttachment &&
35505dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes            subpass_desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
35515dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes            if (!pPipeline->graphicsPipelineCI.pDepthStencilState) {
35525dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes                skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
35535dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes                                     __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS",
35545dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes                                     "Invalid Pipeline CreateInfo State: "
35555dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes                                     "pDepthStencilState is NULL when rasterization is enabled and subpass uses a "
35565dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes                                     "depth/stencil attachment");
35575dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes            }
35585dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes        }
35595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
356083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    return skip_call;
35615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
35625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
35635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Free the Pipeline nodes
35645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic void deletePipelines(layer_data *my_data) {
35655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (my_data->pipelineMap.size() <= 0)
35665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return;
3567ca546210846c65808717f8875deae39bd227c240Tobin Ehlis    for (auto &pipe_map_pair : my_data->pipelineMap) {
3568ca546210846c65808717f8875deae39bd227c240Tobin Ehlis        delete pipe_map_pair.second;
35695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
35705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    my_data->pipelineMap.clear();
35715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
35725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
35735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Block of code at start here specifically for managing/tracking DSs
35745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
35755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Return Pool node ptr for specified pool or else NULL
3576e3f7c45fd64a44a67ce96c89e2bbee426c6ecf24Tobin EhlisDESCRIPTOR_POOL_NODE *getPoolNode(const layer_data *dev_data, const VkDescriptorPool pool) {
3577bb7ea477706f90eb2a72887f652795bc79f60ddeTobin Ehlis    auto pool_it = dev_data->descriptorPoolMap.find(pool);
3578bb7ea477706f90eb2a72887f652795bc79f60ddeTobin Ehlis    if (pool_it == dev_data->descriptorPoolMap.end()) {
35795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return NULL;
35805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
3581bb7ea477706f90eb2a72887f652795bc79f60ddeTobin Ehlis    return pool_it->second;
35825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
35835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3584e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves// Return false if update struct is of valid type, otherwise flag error and return code from callback
3585e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool validUpdateStruct(layer_data *my_data, const VkDevice device, const GENERIC_HEADER *pUpdateStruct) {
35865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    switch (pUpdateStruct->sType) {
35875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET:
35885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET:
3589e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        return false;
35905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    default:
35915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
35925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                       DRAWSTATE_INVALID_UPDATE_STRUCT, "DS",
35935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                       "Unexpected UPDATE struct of type %s (value %u) in vkUpdateDescriptors() struct tree",
35945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                       string_VkStructureType(pUpdateStruct->sType), pUpdateStruct->sType);
35955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
35965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
35975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
35985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Set count for given update struct in the last parameter
35995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic uint32_t getUpdateCount(layer_data *my_data, const VkDevice device, const GENERIC_HEADER *pUpdateStruct) {
36005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    switch (pUpdateStruct->sType) {
36015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET:
36025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return ((VkWriteDescriptorSet *)pUpdateStruct)->descriptorCount;
36035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET:
36045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // TODO : Need to understand this case better and make sure code is correct
36055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return ((VkCopyDescriptorSet *)pUpdateStruct)->descriptorCount;
36065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    default:
36075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return 0;
36085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
36095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
36105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
36115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// For given layout and update, return the first overall index of the layout that is updated
3612fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlisstatic uint32_t getUpdateStartIndex(layer_data *my_data, const VkDevice device, const uint32_t binding_start_index,
36135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                    const uint32_t arrayIndex, const GENERIC_HEADER *pUpdateStruct) {
3614fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis    return binding_start_index + arrayIndex;
36155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
36165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// For given layout and update, return the last overall index of the layout that is updated
3617fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlisstatic uint32_t getUpdateEndIndex(layer_data *my_data, const VkDevice device, const uint32_t binding_start_index,
36185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                  const uint32_t arrayIndex, const GENERIC_HEADER *pUpdateStruct) {
36195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t count = getUpdateCount(my_data, device, pUpdateStruct);
3620fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis    return binding_start_index + arrayIndex + count - 1;
36215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
36225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Verify that the descriptor type in the update struct matches what's expected by the layout
3623fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlisstatic bool validateUpdateConsistency(layer_data *my_data, const VkDevice device, const VkDescriptorType layout_type,
3624e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                                      const GENERIC_HEADER *pUpdateStruct, uint32_t startIndex, uint32_t endIndex) {
36255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // First get actual type of update
362683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
36271d5109d5e0dcc530b27e632e73e1be5e12a28dcdJamie Madill    VkDescriptorType actualType = VK_DESCRIPTOR_TYPE_MAX_ENUM;
36285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    switch (pUpdateStruct->sType) {
36295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET:
36305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        actualType = ((VkWriteDescriptorSet *)pUpdateStruct)->descriptorType;
36315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        break;
36325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET:
36335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        /* no need to validate */
3634e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        return false;
36355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        break;
36365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    default:
363783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
363883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                             DRAWSTATE_INVALID_UPDATE_STRUCT, "DS",
363983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                             "Unexpected UPDATE struct of type %s (value %u) in vkUpdateDescriptors() struct tree",
364083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                             string_VkStructureType(pUpdateStruct->sType), pUpdateStruct->sType);
36415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
364283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call) {
3643fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis        if (layout_type != actualType) {
364483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= log_msg(
3645fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis                my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
3646fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis                DRAWSTATE_DESCRIPTOR_TYPE_MISMATCH, "DS",
3647fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis                "Write descriptor update has descriptor type %s that does not match overlapping binding descriptor type of %s!",
3648fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis                string_VkDescriptorType(actualType), string_VkDescriptorType(layout_type));
36495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
36505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
365183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    return skip_call;
36525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
36534a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine//TODO: Consolidate functions
36544a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentinebool FindLayout(const GLOBAL_CB_NODE *pCB, ImageSubresourcePair imgpair, IMAGE_CMD_BUF_LAYOUT_NODE &node, const VkImageAspectFlags aspectMask) {
36554a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    layer_data *my_data = get_my_data_ptr(get_dispatch_key(pCB->commandBuffer), layer_data_map);
36564a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    if (!(imgpair.subresource.aspectMask & aspectMask)) {
36574a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine        return false;
36584a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    }
36594a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    VkImageAspectFlags oldAspectMask = imgpair.subresource.aspectMask;
36604a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    imgpair.subresource.aspectMask = aspectMask;
36614a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    auto imgsubIt = pCB->imageLayoutMap.find(imgpair);
36624a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    if (imgsubIt == pCB->imageLayoutMap.end()) {
36634a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine        return false;
36644a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    }
36654a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    if (node.layout != VK_IMAGE_LAYOUT_MAX_ENUM && node.layout != imgsubIt->second.layout) {
36664a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine        log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
36674a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine                reinterpret_cast<uint64_t&>(imgpair.image), __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS",
36684a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine                "Cannot query for VkImage 0x%" PRIx64 " layout when combined aspect mask %d has multiple layout types: %s and %s",
36694a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine                reinterpret_cast<uint64_t&>(imgpair.image), oldAspectMask, string_VkImageLayout(node.layout), string_VkImageLayout(imgsubIt->second.layout));
36704a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    }
36714a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    if (node.initialLayout != VK_IMAGE_LAYOUT_MAX_ENUM && node.initialLayout != imgsubIt->second.initialLayout) {
36724a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine        log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
36734a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine                reinterpret_cast<uint64_t&>(imgpair.image), __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS",
36744a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine                "Cannot query for VkImage 0x%" PRIx64 " layout when combined aspect mask %d has multiple initial layout types: %s and %s",
36754a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine                reinterpret_cast<uint64_t&>(imgpair.image), oldAspectMask, string_VkImageLayout(node.initialLayout), string_VkImageLayout(imgsubIt->second.initialLayout));
36764a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    }
36774a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    node = imgsubIt->second;
36784a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    return true;
36794a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine}
36804a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine
36814a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentinebool FindLayout(const layer_data *my_data, ImageSubresourcePair imgpair, VkImageLayout &layout, const VkImageAspectFlags aspectMask) {
36824a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    if (!(imgpair.subresource.aspectMask & aspectMask)) {
36834a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine        return false;
36844a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    }
36854a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    VkImageAspectFlags oldAspectMask = imgpair.subresource.aspectMask;
36864a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    imgpair.subresource.aspectMask = aspectMask;
36874a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    auto imgsubIt = my_data->imageLayoutMap.find(imgpair);
36884a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    if (imgsubIt == my_data->imageLayoutMap.end()) {
36894a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine        return false;
36904a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    }
36914a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    if (layout != VK_IMAGE_LAYOUT_MAX_ENUM && layout != imgsubIt->second.layout) {
36924a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine        log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
36934a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine                reinterpret_cast<uint64_t&>(imgpair.image), __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS",
36944a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine                "Cannot query for VkImage 0x%" PRIx64 " layout when combined aspect mask %d has multiple layout types: %s and %s",
36954a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine                reinterpret_cast<uint64_t&>(imgpair.image), oldAspectMask, string_VkImageLayout(layout), string_VkImageLayout(imgsubIt->second.layout));
36964a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    }
36974a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    layout = imgsubIt->second.layout;
36984a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    return true;
36994a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine}
37004a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine
37015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// find layout(s) on the cmd buf level
37025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisbool FindLayout(const GLOBAL_CB_NODE *pCB, VkImage image, VkImageSubresource range, IMAGE_CMD_BUF_LAYOUT_NODE &node) {
37035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    ImageSubresourcePair imgpair = {image, true, range};
37044a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    node = IMAGE_CMD_BUF_LAYOUT_NODE(VK_IMAGE_LAYOUT_MAX_ENUM, VK_IMAGE_LAYOUT_MAX_ENUM);
37054a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    FindLayout(pCB, imgpair, node, VK_IMAGE_ASPECT_COLOR_BIT);
37064a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    FindLayout(pCB, imgpair, node, VK_IMAGE_ASPECT_DEPTH_BIT);
37074a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    FindLayout(pCB, imgpair, node, VK_IMAGE_ASPECT_STENCIL_BIT);
37084a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    FindLayout(pCB, imgpair, node, VK_IMAGE_ASPECT_METADATA_BIT);
37094a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    if (node.layout == VK_IMAGE_LAYOUT_MAX_ENUM) {
37105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        imgpair = {image, false, VkImageSubresource()};
37114a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine        auto imgsubIt = pCB->imageLayoutMap.find(imgpair);
37125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (imgsubIt == pCB->imageLayoutMap.end())
37135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            return false;
37144a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine        node = imgsubIt->second;
37155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
37165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return true;
37175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
37185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
37195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// find layout(s) on the global level
37205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisbool FindLayout(const layer_data *my_data, ImageSubresourcePair imgpair, VkImageLayout &layout) {
37214a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    layout = VK_IMAGE_LAYOUT_MAX_ENUM;
37224a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    FindLayout(my_data, imgpair, layout, VK_IMAGE_ASPECT_COLOR_BIT);
37234a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    FindLayout(my_data, imgpair, layout, VK_IMAGE_ASPECT_DEPTH_BIT);
37244a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    FindLayout(my_data, imgpair, layout, VK_IMAGE_ASPECT_STENCIL_BIT);
37254a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    FindLayout(my_data, imgpair, layout, VK_IMAGE_ASPECT_METADATA_BIT);
37264a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine    if (layout == VK_IMAGE_LAYOUT_MAX_ENUM) {
37275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        imgpair = {imgpair.image, false, VkImageSubresource()};
37284a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine        auto imgsubIt = my_data->imageLayoutMap.find(imgpair);
37295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (imgsubIt == my_data->imageLayoutMap.end())
37305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            return false;
37314a3279bb23b511257d80ec73ce06d6206d7ab503Michael Lentine        layout = imgsubIt->second.layout;
37325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
37335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return true;
37345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
37355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
37365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisbool FindLayout(const layer_data *my_data, VkImage image, VkImageSubresource range, VkImageLayout &layout) {
37375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    ImageSubresourcePair imgpair = {image, true, range};
37385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return FindLayout(my_data, imgpair, layout);
37395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
37405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
37415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisbool FindLayouts(const layer_data *my_data, VkImage image, std::vector<VkImageLayout> &layouts) {
37425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    auto sub_data = my_data->imageSubresourceMap.find(image);
37435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (sub_data == my_data->imageSubresourceMap.end())
37445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return false;
37456d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis    auto img_node = getImageNode(my_data, image);
37466d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis    if (!img_node)
37475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return false;
37485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    bool ignoreGlobal = false;
37495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TODO: Make this robust for >1 aspect mask. Now it will just say ignore
37505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // potential errors in this case.
37516d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis    if (sub_data->second.size() >= (img_node->createInfo.arrayLayers * img_node->createInfo.mipLevels + 1)) {
37525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        ignoreGlobal = true;
37535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
37545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (auto imgsubpair : sub_data->second) {
37555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (ignoreGlobal && !imgsubpair.hasSubresource)
37565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            continue;
37575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto img_data = my_data->imageLayoutMap.find(imgsubpair);
37585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (img_data != my_data->imageLayoutMap.end()) {
37595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            layouts.push_back(img_data->second.layout);
37605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
37615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
37625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return true;
37635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
37645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
37655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Set the layout on the global level
37665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisvoid SetLayout(layer_data *my_data, ImageSubresourcePair imgpair, const VkImageLayout &layout) {
37675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkImage &image = imgpair.image;
37685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TODO (mlentine): Maybe set format if new? Not used atm.
37695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    my_data->imageLayoutMap[imgpair].layout = layout;
37705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TODO (mlentine): Maybe make vector a set?
37715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    auto subresource = std::find(my_data->imageSubresourceMap[image].begin(), my_data->imageSubresourceMap[image].end(), imgpair);
37725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (subresource == my_data->imageSubresourceMap[image].end()) {
37735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        my_data->imageSubresourceMap[image].push_back(imgpair);
37745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
37755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
37765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
37775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Set the layout on the cmdbuf level
377808682cd3f4809493847b6bdf7605e0a2fede0d56Michael Lentinevoid SetLayout(GLOBAL_CB_NODE *pCB, ImageSubresourcePair imgpair, const IMAGE_CMD_BUF_LAYOUT_NODE &node) {
37795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    pCB->imageLayoutMap[imgpair] = node;
37805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TODO (mlentine): Maybe make vector a set?
378108682cd3f4809493847b6bdf7605e0a2fede0d56Michael Lentine    auto subresource =
378208682cd3f4809493847b6bdf7605e0a2fede0d56Michael Lentine        std::find(pCB->imageSubresourceMap[imgpair.image].begin(), pCB->imageSubresourceMap[imgpair.image].end(), imgpair);
378308682cd3f4809493847b6bdf7605e0a2fede0d56Michael Lentine    if (subresource == pCB->imageSubresourceMap[imgpair.image].end()) {
378408682cd3f4809493847b6bdf7605e0a2fede0d56Michael Lentine        pCB->imageSubresourceMap[imgpair.image].push_back(imgpair);
37855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
37865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
37875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
378808682cd3f4809493847b6bdf7605e0a2fede0d56Michael Lentinevoid SetLayout(GLOBAL_CB_NODE *pCB, ImageSubresourcePair imgpair, const VkImageLayout &layout) {
37895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TODO (mlentine): Maybe make vector a set?
379008682cd3f4809493847b6bdf7605e0a2fede0d56Michael Lentine    if (std::find(pCB->imageSubresourceMap[imgpair.image].begin(), pCB->imageSubresourceMap[imgpair.image].end(), imgpair) !=
379108682cd3f4809493847b6bdf7605e0a2fede0d56Michael Lentine        pCB->imageSubresourceMap[imgpair.image].end()) {
37925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->imageLayoutMap[imgpair].layout = layout;
37935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
37945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // TODO (mlentine): Could be expensive and might need to be removed.
37955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        assert(imgpair.hasSubresource);
37965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        IMAGE_CMD_BUF_LAYOUT_NODE node;
37977068a4271b2a542d7e6931104fa62e4a788ed8e5Mark Lobodzinski        if (!FindLayout(pCB, imgpair.image, imgpair.subresource, node)) {
37987068a4271b2a542d7e6931104fa62e4a788ed8e5Mark Lobodzinski            node.initialLayout = layout;
37997068a4271b2a542d7e6931104fa62e4a788ed8e5Mark Lobodzinski        }
380008682cd3f4809493847b6bdf7605e0a2fede0d56Michael Lentine        SetLayout(pCB, imgpair, {node.initialLayout, layout});
38015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
38025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
38035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
380408682cd3f4809493847b6bdf7605e0a2fede0d56Michael Lentinetemplate <class OBJECT, class LAYOUT>
380508682cd3f4809493847b6bdf7605e0a2fede0d56Michael Lentinevoid SetLayout(OBJECT *pObject, ImageSubresourcePair imgpair, const LAYOUT &layout, VkImageAspectFlags aspectMask) {
380608682cd3f4809493847b6bdf7605e0a2fede0d56Michael Lentine    if (imgpair.subresource.aspectMask & aspectMask) {
380708682cd3f4809493847b6bdf7605e0a2fede0d56Michael Lentine        imgpair.subresource.aspectMask = aspectMask;
380808682cd3f4809493847b6bdf7605e0a2fede0d56Michael Lentine        SetLayout(pObject, imgpair, layout);
380908682cd3f4809493847b6bdf7605e0a2fede0d56Michael Lentine    }
38105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
38115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
381208682cd3f4809493847b6bdf7605e0a2fede0d56Michael Lentinetemplate <class OBJECT, class LAYOUT>
381308682cd3f4809493847b6bdf7605e0a2fede0d56Michael Lentinevoid SetLayout(OBJECT *pObject, VkImage image, VkImageSubresource range, const LAYOUT &layout) {
38145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    ImageSubresourcePair imgpair = {image, true, range};
381508682cd3f4809493847b6bdf7605e0a2fede0d56Michael Lentine    SetLayout(pObject, imgpair, layout, VK_IMAGE_ASPECT_COLOR_BIT);
381608682cd3f4809493847b6bdf7605e0a2fede0d56Michael Lentine    SetLayout(pObject, imgpair, layout, VK_IMAGE_ASPECT_DEPTH_BIT);
381708682cd3f4809493847b6bdf7605e0a2fede0d56Michael Lentine    SetLayout(pObject, imgpair, layout, VK_IMAGE_ASPECT_STENCIL_BIT);
381808682cd3f4809493847b6bdf7605e0a2fede0d56Michael Lentine    SetLayout(pObject, imgpair, layout, VK_IMAGE_ASPECT_METADATA_BIT);
38195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
38205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
382108682cd3f4809493847b6bdf7605e0a2fede0d56Michael Lentinetemplate <class OBJECT, class LAYOUT> void SetLayout(OBJECT *pObject, VkImage image, const LAYOUT &layout) {
38225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    ImageSubresourcePair imgpair = {image, false, VkImageSubresource()};
382308682cd3f4809493847b6bdf7605e0a2fede0d56Michael Lentine    SetLayout(pObject, image, imgpair, layout);
38245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
38255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
38265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisvoid SetLayout(const layer_data *dev_data, GLOBAL_CB_NODE *pCB, VkImageView imageView, const VkImageLayout &layout) {
382779fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis    auto view_state = getImageViewState(dev_data, imageView);
382879fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis    assert(view_state);
382912d5600c2f9e32343016fd944432ba95df370797Tobin Ehlis    auto image = view_state->create_info.image;
383079fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis    const VkImageSubresourceRange &subRange = view_state->create_info.subresourceRange;
38315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TODO: Do not iterate over every possibility - consolidate where possible
38325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t j = 0; j < subRange.levelCount; j++) {
38335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        uint32_t level = subRange.baseMipLevel + j;
38345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t k = 0; k < subRange.layerCount; k++) {
38355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            uint32_t layer = subRange.baseArrayLayer + k;
38365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            VkImageSubresource sub = {subRange.aspectMask, level, layer};
3837915963fbb05941d3d457f62d6ef61d066b7d73a9Mark Lobodzinski            // TODO: If ImageView was created with depth or stencil, transition both layouts as
3838915963fbb05941d3d457f62d6ef61d066b7d73a9Mark Lobodzinski            // the aspectMask is ignored and both are used. Verify that the extra implicit layout
3839915963fbb05941d3d457f62d6ef61d066b7d73a9Mark Lobodzinski            // is OK for descriptor set layout validation
3840038f931c1696f3e96aeec0e3786b5a47acf908e1Mark Lobodzinski            if (subRange.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
384179fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                if (vk_format_is_depth_and_stencil(view_state->create_info.format)) {
3842038f931c1696f3e96aeec0e3786b5a47acf908e1Mark Lobodzinski                    sub.aspectMask |= (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
3843038f931c1696f3e96aeec0e3786b5a47acf908e1Mark Lobodzinski                }
3844038f931c1696f3e96aeec0e3786b5a47acf908e1Mark Lobodzinski            }
38455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            SetLayout(pCB, image, sub, layout);
38465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
38475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
38485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
38495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
38505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate that given set is valid and that it's not being used by an in-flight CmdBuffer
38515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// func_str is the name of the calling function
3852e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves// Return false if no errors occur
3853e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves// Return true if validation error occurs and callback returns true (to skip upcoming API call down the chain)
38540dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlisstatic bool validateIdleDescriptorSet(const layer_data *dev_data, VkDescriptorSet set, std::string func_str) {
38550dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis    if (dev_data->instance_state->disabled.idle_descriptor_set)
38560dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis        return false;
3857e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool skip_call = false;
38580dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis    auto set_node = dev_data->setMap.find(set);
38590dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis    if (set_node == dev_data->setMap.end()) {
38600dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis        skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
38615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                             (uint64_t)(set), __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS",
3862414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                             "Cannot call %s() on descriptor set 0x%" PRIxLEAST64 " that has not been allocated.", func_str.c_str(),
38635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                             (uint64_t)(set));
38645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
38651c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis        // TODO : This covers various error cases so should pass error enum into this function and use passed in enum here
38665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (set_node->second->in_use.load()) {
38671c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis            skip_call |=
38680dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
38691c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis                        (uint64_t)(set), __LINE__, VALIDATION_ERROR_00919, "DS",
38701c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis                        "Cannot call %s() on descriptor set 0x%" PRIxLEAST64 " that is in use by a command buffer. %s",
38711c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis                        func_str.c_str(), (uint64_t)(set), validation_error_map[VALIDATION_ERROR_00919]);
38725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
38735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
38745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return skip_call;
38755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
3876f80bf38f4fb3f177b3e1be11b7b1c5edcdbf7d9bChris Forbes
3877e6651096ed8f07840447783c66827cc16d659a49Tobin Ehlis// Remove set from setMap and delete the set
38789dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlisstatic void freeDescriptorSet(layer_data *dev_data, cvdescriptorset::DescriptorSet *descriptor_set) {
38799dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlis    dev_data->setMap.erase(descriptor_set->GetSet());
38809dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlis    delete descriptor_set;
38819dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlis}
38825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Free all DS Pools including their Sets & related sub-structs
38835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// NOTE : Calls to this function should be wrapped in mutex
38845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic void deletePools(layer_data *my_data) {
38855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (my_data->descriptorPoolMap.size() <= 0)
38865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return;
38875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (auto ii = my_data->descriptorPoolMap.begin(); ii != my_data->descriptorPoolMap.end(); ++ii) {
3888c5f47f0a54e14c47d402aeabc6498d981ecda9ccTobin Ehlis        // Remove this pools' sets from setMap and delete them
3889cb9ce9e05b8e939d3da35c64997c70049877f4feTobin Ehlis        for (auto ds : (*ii).second->sets) {
38909dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlis            freeDescriptorSet(my_data, ds);
38915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
3892f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis        (*ii).second->sets.clear();
38935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
38945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    my_data->descriptorPoolMap.clear();
38955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
38965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
38975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic void clearDescriptorPool(layer_data *my_data, const VkDevice device, const VkDescriptorPool pool,
38985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                VkDescriptorPoolResetFlags flags) {
38995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    DESCRIPTOR_POOL_NODE *pPool = getPoolNode(my_data, pool);
3900de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis    // TODO: validate flags
3901de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis    // For every set off of this pool, clear it, remove from setMap, and free cvdescriptorset::DescriptorSet
3902de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis    for (auto ds : pPool->sets) {
3903de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis        freeDescriptorSet(my_data, ds);
3904de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis    }
3905de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis    pPool->sets.clear();
3906de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis    // Reset available count for each type and available sets for this pool
3907de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis    for (uint32_t i = 0; i < pPool->availableDescriptorTypeCount.size(); ++i) {
3908de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis        pPool->availableDescriptorTypeCount[i] = pPool->maxDescriptorTypeCount[i];
39095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
3910de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis    pPool->availableSets = pPool->maxSets;
39115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
39125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
39135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// For given CB object, fetch associated CB Node from map
39145121a8dcacb23766ba4455b4eea429f0a3d62099Chris Forbesstatic GLOBAL_CB_NODE *getCBNode(layer_data const *my_data, const VkCommandBuffer cb) {
39155121a8dcacb23766ba4455b4eea429f0a3d62099Chris Forbes    auto it = my_data->commandBufferMap.find(cb);
39165121a8dcacb23766ba4455b4eea429f0a3d62099Chris Forbes    if (it == my_data->commandBufferMap.end()) {
391772d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis        log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
391872d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                reinterpret_cast<const uint64_t &>(cb), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
3919414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                "Attempt to use CommandBuffer 0x%" PRIxLEAST64 " that doesn't exist!", (uint64_t)(cb));
39205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return NULL;
39215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
39225121a8dcacb23766ba4455b4eea429f0a3d62099Chris Forbes    return it->second;
39235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
39245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Free all CB Nodes
39255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// NOTE : Calls to this function should be wrapped in mutex
39265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic void deleteCommandBuffers(layer_data *my_data) {
3927400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis    if (my_data->commandBufferMap.empty()) {
39285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return;
39295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
39305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (auto ii = my_data->commandBufferMap.begin(); ii != my_data->commandBufferMap.end(); ++ii) {
39315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        delete (*ii).second;
39325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
39335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    my_data->commandBufferMap.clear();
39345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
39355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3936e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool report_error_no_cb_begin(const layer_data *dev_data, const VkCommandBuffer cb, const char *caller_name) {
39375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
39385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                   (uint64_t)cb, __LINE__, DRAWSTATE_NO_BEGIN_COMMAND_BUFFER, "DS",
39395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                   "You must call vkBeginCommandBuffer() before this call to %s", caller_name);
39405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
39415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3942e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesbool validateCmdsInCmdBuffer(const layer_data *dev_data, const GLOBAL_CB_NODE *pCB, const CMD_TYPE cmd_type) {
39435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (!pCB->activeRenderPass)
3944e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        return false;
3945e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool skip_call = false;
3946d0d8e333806eaac08bdc87ddeff886dc2b0f09e7Tobin Ehlis    if (pCB->activeSubpassContents == VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS &&
3947d0d8e333806eaac08bdc87ddeff886dc2b0f09e7Tobin Ehlis        (cmd_type != CMD_EXECUTECOMMANDS && cmd_type != CMD_NEXTSUBPASS && cmd_type != CMD_ENDRENDERPASS)) {
39485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
39495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                             DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
39505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                             "Commands cannot be called in a subpass using secondary command buffers.");
39515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else if (pCB->activeSubpassContents == VK_SUBPASS_CONTENTS_INLINE && cmd_type == CMD_EXECUTECOMMANDS) {
39525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
39535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                             DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
39545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                             "vkCmdExecuteCommands() cannot be called in a subpass using inline commands.");
39555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
39565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return skip_call;
39575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
39585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
39595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic bool checkGraphicsBit(const layer_data *my_data, VkQueueFlags flags, const char *name) {
39605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (!(flags & VK_QUEUE_GRAPHICS_BIT))
39615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
39625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                       DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
39635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                       "Cannot call %s on a command buffer allocated from a pool without graphics capabilities.", name);
39645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return false;
39655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
39665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
39675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic bool checkComputeBit(const layer_data *my_data, VkQueueFlags flags, const char *name) {
39685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (!(flags & VK_QUEUE_COMPUTE_BIT))
39695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
39705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                       DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
39715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                       "Cannot call %s on a command buffer allocated from a pool without compute capabilities.", name);
39725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return false;
39735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
39745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
39755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic bool checkGraphicsOrComputeBit(const layer_data *my_data, VkQueueFlags flags, const char *name) {
39765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (!((flags & VK_QUEUE_GRAPHICS_BIT) || (flags & VK_QUEUE_COMPUTE_BIT)))
39775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
39785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                       DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
39795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                       "Cannot call %s on a command buffer allocated from a pool without graphics capabilities.", name);
39805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return false;
39815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
39825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
39835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Add specified CMD to the CmdBuffer in given pCB, flagging errors if CB is not
39845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//  in the recording state or if there's an issue with the Cmd ordering
3985a01b5eb150981aad061238e64b173d0da8c11140Chris Forbesstatic bool addCmd(layer_data *my_data, GLOBAL_CB_NODE *pCB, const CMD_TYPE cmd, const char *caller_name) {
398683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
3987a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes    auto pPool = getCommandPoolNode(my_data, pCB->createInfo.commandPool);
3988a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes    if (pPool) {
3989a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes        VkQueueFlags flags = my_data->phys_dev_properties.queue_family_properties[pPool->queueFamilyIndex].queueFlags;
39905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        switch (cmd) {
39915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_BINDPIPELINE:
39925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_BINDPIPELINEDELTA:
39935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_BINDDESCRIPTORSETS:
39945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_FILLBUFFER:
39955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_CLEARCOLORIMAGE:
39965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_SETEVENT:
39975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_RESETEVENT:
39985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_WAITEVENTS:
39995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_BEGINQUERY:
40005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_ENDQUERY:
40015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_RESETQUERYPOOL:
40025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_COPYQUERYPOOLRESULTS:
40035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_WRITETIMESTAMP:
400483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= checkGraphicsOrComputeBit(my_data, flags, cmdTypeToString(cmd).c_str());
40055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            break;
40065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_SETVIEWPORTSTATE:
40075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_SETSCISSORSTATE:
40085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_SETLINEWIDTHSTATE:
40095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_SETDEPTHBIASSTATE:
40105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_SETBLENDSTATE:
40115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_SETDEPTHBOUNDSSTATE:
40125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_SETSTENCILREADMASKSTATE:
40135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_SETSTENCILWRITEMASKSTATE:
40145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_SETSTENCILREFERENCESTATE:
40155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_BINDINDEXBUFFER:
40165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_BINDVERTEXBUFFER:
40175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_DRAW:
40185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_DRAWINDEXED:
40195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_DRAWINDIRECT:
40205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_DRAWINDEXEDINDIRECT:
40215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_BLITIMAGE:
40225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_CLEARATTACHMENTS:
40235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_CLEARDEPTHSTENCILIMAGE:
40245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_RESOLVEIMAGE:
40255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_BEGINRENDERPASS:
40265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_NEXTSUBPASS:
40275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_ENDRENDERPASS:
402883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= checkGraphicsBit(my_data, flags, cmdTypeToString(cmd).c_str());
40295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            break;
40305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_DISPATCH:
40315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_DISPATCHINDIRECT:
403283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= checkComputeBit(my_data, flags, cmdTypeToString(cmd).c_str());
40335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            break;
40345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_COPYBUFFER:
40355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_COPYIMAGE:
40365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_COPYBUFFERTOIMAGE:
40375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_COPYIMAGETOBUFFER:
40385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_CLONEIMAGEDATA:
40395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_UPDATEBUFFER:
40405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_PIPELINEBARRIER:
40415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case CMD_EXECUTECOMMANDS:
40427651c2eb9fe152ba62921ed60454afd882357e2aTobin Ehlis        case CMD_END:
40435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            break;
40445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        default:
40455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            break;
40465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
40475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
40485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB->state != CB_RECORDING) {
404983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= report_error_no_cb_begin(my_data, pCB->commandBuffer, caller_name);
40507651c2eb9fe152ba62921ed60454afd882357e2aTobin Ehlis    } else {
405183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= validateCmdsInCmdBuffer(my_data, pCB, cmd);
40525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        CMD_NODE cmdNode = {};
40535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // init cmd node and append to end of cmd LL
40545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        cmdNode.cmdNumber = ++pCB->numCmds;
40555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        cmdNode.type = cmd;
40565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->cmds.push_back(cmdNode);
40575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
405883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    return skip_call;
40595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
40607e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// For given object struct return a ptr of BASE_NODE type for its wrapping struct
40617e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin EhlisBASE_NODE *GetStateStructPtrFromObject(layer_data *dev_data, VK_OBJECT object_struct) {
40627e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    BASE_NODE *base_ptr = nullptr;
40637e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    switch (object_struct.type) {
40647e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT: {
40657e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        base_ptr = getSetNode(dev_data, reinterpret_cast<VkDescriptorSet &>(object_struct.handle));
40667e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        break;
40677e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    }
40687e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT: {
40697e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        base_ptr = getSamplerNode(dev_data, reinterpret_cast<VkSampler &>(object_struct.handle));
40707e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        break;
40717e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    }
40727e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT: {
40737e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        base_ptr = getQueryPoolNode(dev_data, reinterpret_cast<VkQueryPool &>(object_struct.handle));
40747e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        break;
40757e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    }
40767e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT: {
40777e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        base_ptr = getPipeline(dev_data, reinterpret_cast<VkPipeline &>(object_struct.handle));
4078bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis        break;
4079bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis    }
4080bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT: {
40817e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        base_ptr = getBufferNode(dev_data, reinterpret_cast<VkBuffer &>(object_struct.handle));
40827e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        break;
40837e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    }
40847e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT: {
40857e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        base_ptr = getBufferViewState(dev_data, reinterpret_cast<VkBufferView &>(object_struct.handle));
40867e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        break;
40877e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    }
40887e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: {
40897e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        base_ptr = getImageNode(dev_data, reinterpret_cast<VkImage &>(object_struct.handle));
40907e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        break;
40917e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    }
40927e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT: {
40937e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        base_ptr = getImageViewState(dev_data, reinterpret_cast<VkImageView &>(object_struct.handle));
4094bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis        break;
4095bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis    }
40969822fe9cda4c97bfa374f680fa90419e0f82580eTobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT: {
40977e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        base_ptr = getEventNode(dev_data, reinterpret_cast<VkEvent &>(object_struct.handle));
40989822fe9cda4c97bfa374f680fa90419e0f82580eTobin Ehlis        break;
40999822fe9cda4c97bfa374f680fa90419e0f82580eTobin Ehlis    }
41007e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT: {
41017e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        base_ptr = getPoolNode(dev_data, reinterpret_cast<VkDescriptorPool &>(object_struct.handle));
4102ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis        break;
4103ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis    }
41047e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT: {
41057e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        base_ptr = getCommandPoolNode(dev_data, reinterpret_cast<VkCommandPool &>(object_struct.handle));
4106a86b57cf1145ee63d5997547ac0f9847933fc3b6Tobin Ehlis        break;
4107a86b57cf1145ee63d5997547ac0f9847933fc3b6Tobin Ehlis    }
41087e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT: {
41097e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        base_ptr = getFramebuffer(dev_data, reinterpret_cast<VkFramebuffer &>(object_struct.handle));
4110a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis        break;
4111a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis    }
41127e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT: {
41137e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        base_ptr = getRenderPass(dev_data, reinterpret_cast<VkRenderPass &>(object_struct.handle));
41147e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        break;
41157e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    }
41167e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    case VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT: {
41177e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        base_ptr = getMemObjInfo(dev_data, reinterpret_cast<VkDeviceMemory &>(object_struct.handle));
411856f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis        break;
411956f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis    }
4120bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis    default:
41217e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        // TODO : Any other objects to be handled here?
41227e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        assert(0);
41237e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        break;
4124bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis    }
41257e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    return base_ptr;
41267e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis}
41277e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis
41287e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// Tie the VK_OBJECT to the cmd buffer which includes:
41297e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis//  Add object_binding to cmd buffer
41307e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis//  Add cb_binding to object
41317e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlisstatic void addCommandBufferBinding(std::unordered_set<GLOBAL_CB_NODE *> *cb_bindings, VK_OBJECT obj, GLOBAL_CB_NODE *cb_node) {
41327e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    cb_bindings->insert(cb_node);
41337e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    cb_node->object_bindings.insert(obj);
41347e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis}
41357e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// For a given object, if cb_node is in that objects cb_bindings, remove cb_node
41367e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlisstatic void removeCommandBufferBinding(layer_data *dev_data, VK_OBJECT const *object, GLOBAL_CB_NODE *cb_node) {
41377e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    BASE_NODE *base_obj = GetStateStructPtrFromObject(dev_data, *object);
41387e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    if (base_obj)
41397e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        base_obj->cb_bindings.erase(cb_node);
4140bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis}
41415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Reset the command buffer state
41425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//  Maintain the createInfo and set state to CB_NEW, but clear all other state
4143400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlisstatic void resetCB(layer_data *dev_data, const VkCommandBuffer cb) {
4144400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis    GLOBAL_CB_NODE *pCB = dev_data->commandBufferMap[cb];
41455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
4146b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine        pCB->in_use.store(0);
41475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->cmds.clear();
41485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Reset CB state (note that createInfo is not cleared)
41495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->commandBuffer = cb;
41505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        memset(&pCB->beginInfo, 0, sizeof(VkCommandBufferBeginInfo));
41515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        memset(&pCB->inheritanceInfo, 0, sizeof(VkCommandBufferInheritanceInfo));
41525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->numCmds = 0;
41535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        memset(pCB->drawCount, 0, NUM_DRAW_TYPES * sizeof(uint64_t));
41545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->state = CB_NEW;
41555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->submitCount = 0;
41565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->status = 0;
4157b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes        pCB->viewportMask = 0;
4158b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes        pCB->scissorMask = 0;
415993c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski
416072d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis        for (uint32_t i = 0; i < VK_PIPELINE_BIND_POINT_RANGE_SIZE; ++i) {
416172d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis            pCB->lastBound[i].reset();
416272d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis        }
416393c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski
41645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        memset(&pCB->activeRenderPassBeginInfo, 0, sizeof(pCB->activeRenderPassBeginInfo));
4165ee691f5c5fa87aac3750454d2bca2cb582e4e817Chris Forbes        pCB->activeRenderPass = nullptr;
41665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->activeSubpassContents = VK_SUBPASS_CONTENTS_INLINE;
41675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->activeSubpass = 0;
4168e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis        pCB->broken_bindings.clear();
41695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->waitedEvents.clear();
41705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->events.clear();
4171c7e6bc41aa9c6e5a677b138b9459b252cd3bedf2Mark Lobodzinski        pCB->writeEventsBeforeWait.clear();
41725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->waitedEventsBeforeQueryReset.clear();
41735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->queryToStateMap.clear();
41745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->activeQueries.clear();
41755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->startedQueries.clear();
4176abfafae4ec5d76e520916b03d196e474e972c949Michael Lentine        pCB->imageSubresourceMap.clear();
41775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->imageLayoutMap.clear();
41785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->eventToStageMap.clear();
41795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->drawData.clear();
41805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->currentDrawData.buffers.clear();
41815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->primaryCommandBuffer = VK_NULL_HANDLE;
4182bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis        // Make sure any secondaryCommandBuffers are removed from globalInFlight
4183bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis        for (auto secondary_cb : pCB->secondaryCommandBuffers) {
4184bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis            dev_data->globalInFlightCmdBuffers.erase(secondary_cb);
4185bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis        }
41865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->secondaryCommandBuffers.clear();
41877a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis        pCB->updateImages.clear();
41887a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis        pCB->updateBuffers.clear();
4189400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis        clear_cmd_buf_and_mem_references(dev_data, pCB);
4190b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        pCB->eventUpdates.clear();
4191d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine        pCB->queryUpdates.clear();
419293c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski
4193bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis        // Remove object bindings
4194bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis        for (auto obj : pCB->object_bindings) {
4195bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis            removeCommandBufferBinding(dev_data, &obj, pCB);
4196bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis        }
4197a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis        pCB->object_bindings.clear();
419893c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski        // Remove this cmdBuffer's reference from each FrameBuffer's CB ref list
419993c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski        for (auto framebuffer : pCB->framebuffers) {
4200d9369e5a41f95b7bd1670240d441dbed58bc36fbTobin Ehlis            auto fb_node = getFramebuffer(dev_data, framebuffer);
4201d9369e5a41f95b7bd1670240d441dbed58bc36fbTobin Ehlis            if (fb_node)
4202b6fe8da9537ef985960fd1d32b83c952b422f00bTobin Ehlis                fb_node->cb_bindings.erase(pCB);
420393c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski        }
420493c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski        pCB->framebuffers.clear();
42057003b38da5cc27a063af3c45080f3a35438283eeTobin Ehlis        pCB->activeFramebuffer = VK_NULL_HANDLE;
42065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
42075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
42085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
42095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Set PSO-related status bits for CB, including dynamic state set via PSO
42105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic void set_cb_pso_status(GLOBAL_CB_NODE *pCB, const PIPELINE_NODE *pPipe) {
42115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Account for any dynamic state not set via this PSO
4212ca546210846c65808717f8875deae39bd227c240Tobin Ehlis    if (!pPipe->graphicsPipelineCI.pDynamicState ||
4213ca546210846c65808717f8875deae39bd227c240Tobin Ehlis        !pPipe->graphicsPipelineCI.pDynamicState->dynamicStateCount) { // All state is static
42141afd60fa23eaee2000e232efd5d05a64224a91dcTony Barbour        pCB->status |= CBSTATUS_ALL;
42155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
42165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // First consider all state on
42175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Then unset any state that's noted as dynamic in PSO
42185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Finally OR that into CB statemask
42195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        CBStatusFlags psoDynStateMask = CBSTATUS_ALL;
4220ca546210846c65808717f8875deae39bd227c240Tobin Ehlis        for (uint32_t i = 0; i < pPipe->graphicsPipelineCI.pDynamicState->dynamicStateCount; i++) {
4221ca546210846c65808717f8875deae39bd227c240Tobin Ehlis            switch (pPipe->graphicsPipelineCI.pDynamicState->pDynamicStates[i]) {
42225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            case VK_DYNAMIC_STATE_LINE_WIDTH:
42235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                psoDynStateMask &= ~CBSTATUS_LINE_WIDTH_SET;
42245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                break;
42255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            case VK_DYNAMIC_STATE_DEPTH_BIAS:
42265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                psoDynStateMask &= ~CBSTATUS_DEPTH_BIAS_SET;
42275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                break;
42285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            case VK_DYNAMIC_STATE_BLEND_CONSTANTS:
42293d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                psoDynStateMask &= ~CBSTATUS_BLEND_CONSTANTS_SET;
42305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                break;
42315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            case VK_DYNAMIC_STATE_DEPTH_BOUNDS:
42325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                psoDynStateMask &= ~CBSTATUS_DEPTH_BOUNDS_SET;
42335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                break;
42345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK:
42355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                psoDynStateMask &= ~CBSTATUS_STENCIL_READ_MASK_SET;
42365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                break;
42375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK:
42385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                psoDynStateMask &= ~CBSTATUS_STENCIL_WRITE_MASK_SET;
42395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                break;
42405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            case VK_DYNAMIC_STATE_STENCIL_REFERENCE:
42415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                psoDynStateMask &= ~CBSTATUS_STENCIL_REFERENCE_SET;
42425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                break;
42435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            default:
42445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                // TODO : Flag error here
42455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                break;
42465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
42475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
42485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->status |= psoDynStateMask;
42495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
42505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
42515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
42525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Print the last bound Gfx Pipeline
4253e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool printPipeline(layer_data *my_data, const VkCommandBuffer cb) {
425483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
42555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(my_data, cb);
42565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
42575c288f35b2eab0dab95d18768235fef6ffd69b30Tobin Ehlis        PIPELINE_NODE *pPipeTrav = pCB->lastBound[VK_PIPELINE_BIND_POINT_GRAPHICS].pipeline_node;
42585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (!pPipeTrav) {
42595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // nothing to print
42605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
426183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
426283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 __LINE__, DRAWSTATE_NONE, "DS", "%s",
426383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 vk_print_vkgraphicspipelinecreateinfo(
426483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                     reinterpret_cast<const VkGraphicsPipelineCreateInfo *>(&pPipeTrav->graphicsPipelineCI), "{DS}")
426583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                     .c_str());
42665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
42675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
426883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    return skip_call;
42695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
42705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
42715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic void printCB(layer_data *my_data, const VkCommandBuffer cb) {
42725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(my_data, cb);
42735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB && pCB->cmds.size() > 0) {
42745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        log_msg(my_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
4275414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                DRAWSTATE_NONE, "DS", "Cmds in CB 0x%p", (void *)cb);
42765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        vector<CMD_NODE> cmds = pCB->cmds;
42775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (auto ii = cmds.begin(); ii != cmds.end(); ++ii) {
42785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // TODO : Need to pass cb as srcObj here
42795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            log_msg(my_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
4280414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                    __LINE__, DRAWSTATE_NONE, "DS", "  CMD 0x%" PRIx64 ": %s", (*ii).cmdNumber, cmdTypeToString((*ii).type).c_str());
42815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
42825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
42835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Nothing to print
42845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
42855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
42865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4287e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool synchAndPrintDSConfig(layer_data *my_data, const VkCommandBuffer cb) {
428883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
42895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (!(my_data->report_data->active_flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT)) {
429083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        return skip_call;
42915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
429283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    skip_call |= printPipeline(my_data, cb);
429383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    return skip_call;
42945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
42955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
42965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Flags validation error if the associated call is made inside a render pass. The apiName
42975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// routine should ONLY be called outside a render pass.
4298e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool insideRenderPass(const layer_data *my_data, GLOBAL_CB_NODE *pCB, const char *apiName) {
4299e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool inside = false;
43005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB->activeRenderPass) {
43015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        inside = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
43025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                         (uint64_t)pCB->commandBuffer, __LINE__, DRAWSTATE_INVALID_RENDERPASS_CMD, "DS",
4303414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                         "%s: It is invalid to issue this call inside an active render pass (0x%" PRIxLEAST64 ")", apiName,
4304ee691f5c5fa87aac3750454d2bca2cb582e4e817Chris Forbes                         (uint64_t)pCB->activeRenderPass->renderPass);
43055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
43065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return inside;
43075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
43085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
43095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Flags validation error if the associated call is made outside a render pass. The apiName
43105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// routine should ONLY be called inside a render pass.
4311e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool outsideRenderPass(const layer_data *my_data, GLOBAL_CB_NODE *pCB, const char *apiName) {
4312e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool outside = false;
43135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (((pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) && (!pCB->activeRenderPass)) ||
43145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        ((pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) && (!pCB->activeRenderPass) &&
43155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis         !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT))) {
43165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        outside = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
43175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                          (uint64_t)pCB->commandBuffer, __LINE__, DRAWSTATE_NO_ACTIVE_RENDERPASS, "DS",
43185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                          "%s: This call must be issued inside an active render pass.", apiName);
43195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
43205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return outside;
43215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
43225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4323f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesstatic void init_core_validation(instance_layer_data *instance_data, const VkAllocationCallbacks *pAllocator) {
4324d11c4ee2bd2a5672093d76630d895e824ee1a571Mark Lobodzinski
4325b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis    layer_debug_actions(instance_data->report_data, instance_data->logging_callback, pAllocator, "lunarg_core_validation");
43265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
43275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
43285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4329747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbesstatic void checkInstanceRegisterExtensions(const VkInstanceCreateInfo *pCreateInfo, instance_layer_data *instance_data) {
4330747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
4331747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SURFACE_EXTENSION_NAME))
4332747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes            instance_data->surfaceExtensionEnabled = true;
4333747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_DISPLAY_EXTENSION_NAME))
4334747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes            instance_data->displayExtensionEnabled = true;
4335747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_ANDROID_KHR
4336747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_ANDROID_SURFACE_EXTENSION_NAME))
4337747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes            instance_data->androidSurfaceExtensionEnabled = true;
4338747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif
4339747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_MIR_KHR
4340747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_MIR_SURFACE_EXTENSION_NAME))
4341747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes            instance_data->mirSurfaceExtensionEnabled = true;
4342747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif
4343747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WAYLAND_KHR
4344747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME))
4345747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes            instance_data->waylandSurfaceExtensionEnabled = true;
4346747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif
4347747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WIN32_KHR
4348747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WIN32_SURFACE_EXTENSION_NAME))
4349747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes            instance_data->win32SurfaceExtensionEnabled = true;
4350747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif
4351747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XCB_KHR
4352747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XCB_SURFACE_EXTENSION_NAME))
4353747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes            instance_data->xcbSurfaceExtensionEnabled = true;
4354747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif
4355747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XLIB_KHR
4356747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XLIB_SURFACE_EXTENSION_NAME))
4357747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes            instance_data->xlibSurfaceExtensionEnabled = true;
4358747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif
4359747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    }
4360747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
4361747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
436289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL
436389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
43645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
43655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
43665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    assert(chain_info->u.pLayerInfo);
43675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
43685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
43695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (fpCreateInstance == NULL)
43705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return VK_ERROR_INITIALIZATION_FAILED;
43715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
43725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Advance the link info for the next element on the chain
43735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
43745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
43755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
43765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (result != VK_SUCCESS)
43775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return result;
43785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4379f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes    instance_layer_data *instance_data = get_my_data_ptr(get_dispatch_key(*pInstance), instance_layer_data_map);
438056a5ba3e60a723781945959ffc10e2e215350de5Chia-I Wu    instance_data->instance = *pInstance;
43819172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    layer_init_instance_dispatch_table(*pInstance, &instance_data->dispatch_table, fpGetInstanceProcAddr);
43825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
43839172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    instance_data->report_data = debug_report_create_instance(
43849172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes        &instance_data->dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
4385747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    checkInstanceRegisterExtensions(pCreateInfo, instance_data);
4386b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis    init_core_validation(instance_data, pAllocator);
4387825ac70f99460ccb9494d34f93d8ee7ec303e5deMark Lobodzinski
4388b51f48f9e79665e20830097dd9c6434bac68de34Mark Lobodzinski    instance_data->instance_state = unique_ptr<INSTANCE_STATE>(new INSTANCE_STATE());
43895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    ValidateLayerOrdering(*pCreateInfo);
43905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
43915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
43925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
43935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
43945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis/* hook DestroyInstance to remove tableInstanceMap entry */
439589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
43965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TODOSC : Shouldn't need any customization here
43975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    dispatch_key key = get_dispatch_key(instance);
43985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TBD: Need any locking this early, in case this function is called at the
43995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // same time by more than one thread?
44009172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    instance_layer_data *instance_data = get_my_data_ptr(key, instance_layer_data_map);
44019172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    instance_data->dispatch_table.DestroyInstance(instance, pAllocator);
44025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4403b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::lock_guard<std::mutex> lock(global_lock);
44045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Clean up logging callback, if any
44059172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    while (instance_data->logging_callback.size() > 0) {
44069172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes        VkDebugReportCallbackEXT callback = instance_data->logging_callback.back();
44079172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes        layer_destroy_msg_callback(instance_data->report_data, callback, pAllocator);
44089172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes        instance_data->logging_callback.pop_back();
44095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
44105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
44119172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    layer_debug_report_destroy_instance(instance_data->report_data);
44125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data_map.erase(key);
44135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
44145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4415373469f006399d6b5204ee05db3b56beb168b36fMark Youngstatic void checkDeviceRegisterExtensions(const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
44165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t i;
44175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TBD: Need any locking, in case this function is called at the same time
44185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // by more than one thread?
44195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
44205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    dev_data->device_extensions.wsi_enabled = false;
4421c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young    dev_data->device_extensions.wsi_display_swapchain_enabled = false;
44225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
44235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
44245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0)
44255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            dev_data->device_extensions.wsi_enabled = true;
4426c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young        if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME) == 0)
4427c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young            dev_data->device_extensions.wsi_display_swapchain_enabled = true;
44285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
44295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
44305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4431838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski// Verify that queue family has been properly requested
4432f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesbool ValidateRequestedQueueFamilyProperties(instance_layer_data *instance_data, VkPhysicalDevice gpu, const VkDeviceCreateInfo *create_info) {
4433838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski    bool skip_call = false;
44344b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes    auto physical_device_state = getPhysicalDeviceState(instance_data, gpu);
4435838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski    // First check is app has actually requested queueFamilyProperties
44364b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes    if (!physical_device_state) {
44374b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes        skip_call |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
4438838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski                             0, __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL",
4439838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski                             "Invalid call to vkCreateDevice() w/o first calling vkEnumeratePhysicalDevices().");
44404b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes    } else if (QUERY_DETAILS != physical_device_state->vkGetPhysicalDeviceQueueFamilyPropertiesState) {
4441838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski        // TODO: This is not called out as an invalid use in the spec so make more informative recommendation.
44424b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes        skip_call |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
4443838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski                             VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_INVALID_QUEUE_CREATE_REQUEST,
4444838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski                             "DL", "Call to vkCreateDevice() w/o first calling vkGetPhysicalDeviceQueueFamilyProperties().");
4445838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski    } else {
4446838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski        // Check that the requested queue properties are valid
4447838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski        for (uint32_t i = 0; i < create_info->queueCreateInfoCount; i++) {
4448838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski            uint32_t requestedIndex = create_info->pQueueCreateInfos[i].queueFamilyIndex;
44497d8b6ab1b68c397da50bad43deb1fba389ebace7Chris Forbes            if (requestedIndex >= physical_device_state->queue_family_properties.size()) {
4450838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski                skip_call |= log_msg(
44514b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes                    instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0,
4452838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski                    __LINE__, DEVLIMITS_INVALID_QUEUE_CREATE_REQUEST, "DL",
4453838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski                    "Invalid queue create request in vkCreateDevice(). Invalid queueFamilyIndex %u requested.", requestedIndex);
4454838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski            } else if (create_info->pQueueCreateInfos[i].queueCount >
44557d8b6ab1b68c397da50bad43deb1fba389ebace7Chris Forbes                       physical_device_state->queue_family_properties[requestedIndex].queueCount) {
4456838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski                skip_call |=
44574b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes                    log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
4458838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski                            0, __LINE__, DEVLIMITS_INVALID_QUEUE_CREATE_REQUEST, "DL",
4459838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski                            "Invalid queue create request in vkCreateDevice(). QueueFamilyIndex %u only has %u queues, but "
4460838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski                            "requested queueCount is %u.",
44617d8b6ab1b68c397da50bad43deb1fba389ebace7Chris Forbes                            requestedIndex, physical_device_state->queue_family_properties[requestedIndex].queueCount,
4462838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski                            create_info->pQueueCreateInfos[i].queueCount);
4463838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski            }
4464838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski        }
4465838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski    }
4466838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski    return skip_call;
4467838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski}
4468838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski
4469f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski// Verify that features have been queried and that they are available
4470f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesstatic bool ValidateRequestedFeatures(instance_layer_data *dev_data, VkPhysicalDevice phys, const VkPhysicalDeviceFeatures *requested_features) {
4471f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    bool skip_call = false;
4472f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski
44733bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes    auto phys_device_state = getPhysicalDeviceState(dev_data, phys);
44743bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes    const VkBool32 *actual = reinterpret_cast<VkBool32 *>(&phys_device_state->features);
4475825ac70f99460ccb9494d34f93d8ee7ec303e5deMark Lobodzinski    const VkBool32 *requested = reinterpret_cast<const VkBool32 *>(requested_features);
4476f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    // TODO : This is a nice, compact way to loop through struct, but a bad way to report issues
4477f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    //  Need to provide the struct member name with the issue. To do that seems like we'll
4478f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    //  have to loop through each struct member which should be done w/ codegen to keep in synch.
4479f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    uint32_t errors = 0;
4480f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    uint32_t total_bools = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);
4481f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    for (uint32_t i = 0; i < total_bools; i++) {
4482f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski        if (requested[i] > actual[i]) {
4483f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski            // TODO: Add index to struct member name helper to be able to include a feature name
4484838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4485f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski                VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_INVALID_FEATURE_REQUESTED,
4486f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski                "DL", "While calling vkCreateDevice(), requesting feature #%u in VkPhysicalDeviceFeatures struct, "
4487f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski                "which is not available on this device.",
4488f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski                i);
4489f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski            errors++;
4490f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski        }
4491f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    }
44923bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes    if (errors && (UNCALLED == phys_device_state->vkGetPhysicalDeviceFeaturesState)) {
4493f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski        // If user didn't request features, notify them that they should
4494f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski        // TODO: Verify this against the spec. I believe this is an invalid use of the API and should return an error
4495838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski        skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4496cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski                             VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_INVALID_FEATURE_REQUESTED,
4497cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski                             "DL", "You requested features that are unavailable on this device. You should first query feature "
4498cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski                                   "availability by calling vkGetPhysicalDeviceFeatures().");
4499f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    }
4500f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    return skip_call;
4501f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski}
4502f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski
450389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
450489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                            const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
4505f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes    instance_layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(gpu), instance_layer_data_map);
4506f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    bool skip_call = false;
4507f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski
4508f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    // Check that any requested features are available
4509f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    if (pCreateInfo->pEnabledFeatures) {
45103bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes        skip_call |= ValidateRequestedFeatures(my_instance_data, gpu, pCreateInfo->pEnabledFeatures);
4511f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    }
45124b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes    skip_call |= ValidateRequestedQueueFamilyProperties(my_instance_data, gpu, pCreateInfo);
4513f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski
45141d659b4113b77a95325df10d602a03f1e7abf8b7Mark Mueller    if (skip_call) {
45151d659b4113b77a95325df10d602a03f1e7abf8b7Mark Mueller        return VK_ERROR_VALIDATION_FAILED_EXT;
45161d659b4113b77a95325df10d602a03f1e7abf8b7Mark Mueller    }
45171d659b4113b77a95325df10d602a03f1e7abf8b7Mark Mueller
45185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
45195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
45205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    assert(chain_info->u.pLayerInfo);
45215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
45225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
452356a5ba3e60a723781945959ffc10e2e215350de5Chia-I Wu    PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(my_instance_data->instance, "vkCreateDevice");
45245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (fpCreateDevice == NULL) {
45255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return VK_ERROR_INITIALIZATION_FAILED;
45265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
45275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
45285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Advance the link info for the next element on the chain
45295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
45305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
45315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
45325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (result != VK_SUCCESS) {
45335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return result;
45345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
45355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4536b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
45375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
45385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4539c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis    // Copy instance state into this device's layer_data struct
4540c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis    my_device_data->instance_state = unique_ptr<INSTANCE_STATE>(new INSTANCE_STATE(*(my_instance_data->instance_state)));
454107a464bd7fec9583f346b8c4b8d43c88d2e9ffa4Chris Forbes    my_device_data->instance_data = my_instance_data;
45425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Setup device dispatch table
45434a0754042cf090e131e9e769d8a3633c228625beChris Forbes    layer_init_device_dispatch_table(*pDevice, &my_device_data->dispatch_table, fpGetDeviceProcAddr);
45446c94fb996af5f7f79a2bff04cc8cf425086de111Chris Forbes    my_device_data->device = *pDevice;
45455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
45465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
4547373469f006399d6b5204ee05db3b56beb168b36fMark Young    checkDeviceRegisterExtensions(pCreateInfo, *pDevice);
45485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Get physical device limits for this device
45499172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    my_instance_data->dispatch_table.GetPhysicalDeviceProperties(gpu, &(my_device_data->phys_dev_properties.properties));
45505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t count;
45519172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    my_instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties(gpu, &count, nullptr);
4552b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis    my_device_data->phys_dev_properties.queue_family_properties.resize(count);
45539172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    my_instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties(
4554b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis        gpu, &count, &my_device_data->phys_dev_properties.queue_family_properties[0]);
45555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TODO: device limits should make sure these are compatible
45565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCreateInfo->pEnabledFeatures) {
4557f71dd305f197826a61f398bff725267a20ea1d90Chris Forbes        my_device_data->enabled_features = *pCreateInfo->pEnabledFeatures;
45585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
4559f71dd305f197826a61f398bff725267a20ea1d90Chris Forbes        memset(&my_device_data->enabled_features, 0, sizeof(VkPhysicalDeviceFeatures));
45605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
4561b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis    // Store physical device mem limits into device layer_data struct
45629172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    my_instance_data->dispatch_table.GetPhysicalDeviceMemoryProperties(gpu, &my_device_data->phys_dev_mem_props);
4563b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
45645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
45655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    ValidateLayerOrdering(*pCreateInfo);
45665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
45675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
45685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
45695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
45705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// prototype
457189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
45725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TODOSC : Shouldn't need any customization here
45735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    dispatch_key key = get_dispatch_key(device);
45745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(key, layer_data_map);
45755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Free all the memory
4576b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
45775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    deletePipelines(dev_data);
4578fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes    dev_data->renderPassMap.clear();
45795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    deleteCommandBuffers(dev_data);
4580f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis    // This will also delete all sets in the pool & remove them from setMap
45815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    deletePools(dev_data);
4582f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis    // All sets should be removed
4583f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis    assert(dev_data->setMap.empty());
4584a1e5173c89eb7f03e0434ad45ccd1471e722fa71Tobin Ehlis    for (auto del_layout : dev_data->descriptorSetLayoutMap) {
4585a1e5173c89eb7f03e0434ad45ccd1471e722fa71Tobin Ehlis        delete del_layout.second;
4586a1e5173c89eb7f03e0434ad45ccd1471e722fa71Tobin Ehlis    }
4587fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis    dev_data->descriptorSetLayoutMap.clear();
45885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    dev_data->imageViewMap.clear();
45895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    dev_data->imageMap.clear();
45905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    dev_data->imageSubresourceMap.clear();
45915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    dev_data->imageLayoutMap.clear();
45925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    dev_data->bufferViewMap.clear();
45935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    dev_data->bufferMap.clear();
45941344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis    // Queues persist until device is destroyed
45951344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis    dev_data->queueMap.clear();
4596b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
459703b71511c9e94f2e6101a3214858cee3742ec277Mark Lobodzinski#if MTMERGESOURCE
459883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
4599b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.lock();
46005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
46015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            (uint64_t)device, __LINE__, MEMTRACK_NONE, "MEM", "Printing List details prior to vkDestroyDevice()");
46025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
46035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            (uint64_t)device, __LINE__, MEMTRACK_NONE, "MEM", "================================================");
46040a1ce3dfd81c9f4efbe46f5ba5ddaea70bc4aa61Chris Forbes    print_mem_list(dev_data);
46050a1ce3dfd81c9f4efbe46f5ba5ddaea70bc4aa61Chris Forbes    printCBList(dev_data);
46065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Report any memory leaks
460758070a671b39e2058a799c7b9c932f3f03f2e66dTobin Ehlis    DEVICE_MEM_INFO *pInfo = NULL;
4608400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis    if (!dev_data->memObjMap.empty()) {
46095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (auto ii = dev_data->memObjMap.begin(); ii != dev_data->memObjMap.end(); ++ii) {
461057fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis            pInfo = (*ii).second.get();
4611de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis            if (pInfo->alloc_info.allocationSize != 0) {
46125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                // Valid Usage: All child objects created on device must have been destroyed prior to destroying device
461383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                skip_call |=
461483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
461583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            (uint64_t)pInfo->mem, __LINE__, MEMTRACK_MEMORY_LEAK, "MEM",
461683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            "Mem Object 0x%" PRIx64 " has not been freed. You should clean up this memory by calling "
461783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            "vkFreeMemory(0x%" PRIx64 ") prior to vkDestroyDevice().",
46185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            (uint64_t)(pInfo->mem), (uint64_t)(pInfo->mem));
46195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
46205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
46215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
46225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_debug_report_destroy_device(device);
4623b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
46245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
46255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#if DISPATCH_MAP_DEBUG
4626414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller    fprintf(stderr, "Device: 0x%p, key: 0x%p\n", device, key);
46275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#endif
462883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call) {
46294a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyDevice(device, pAllocator);
46305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
46315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#else
46324a0754042cf090e131e9e769d8a3633c228625beChris Forbes    dev_data->dispatch_table.DestroyDevice(device, pAllocator);
46335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#endif
46345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data_map.erase(key);
46355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
46365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
46375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
46385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
46395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// This validates that the initial layout specified in the command buffer for
46405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// the IMAGE is the same
46415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// as the global IMAGE layout
4642971020aec6166f20a12a833ebd003e0193f4160aChris Forbesstatic bool ValidateCmdBufImageLayouts(layer_data *dev_data, GLOBAL_CB_NODE *pCB) {
4643e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool skip_call = false;
46445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (auto cb_image_data : pCB->imageLayoutMap) {
46455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        VkImageLayout imageLayout;
46465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (!FindLayout(dev_data, cb_image_data.first, imageLayout)) {
46475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            skip_call |=
46485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
4649414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", "Cannot submit cmd buffer using deleted image 0x%" PRIx64 ".",
46505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        reinterpret_cast<const uint64_t &>(cb_image_data.first));
46515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
46525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (cb_image_data.second.initialLayout == VK_IMAGE_LAYOUT_UNDEFINED) {
46535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                // TODO: Set memory invalid which is in mem_tracker currently
46545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            } else if (imageLayout != cb_image_data.second.initialLayout) {
4655856ecb404bc959ddb877c150c9caa0649055b9cbMark Young                if (cb_image_data.first.hasSubresource) {
4656856ecb404bc959ddb877c150c9caa0649055b9cbMark Young                    skip_call |= log_msg(
4657856ecb404bc959ddb877c150c9caa0649055b9cbMark Young                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
4658971020aec6166f20a12a833ebd003e0193f4160aChris Forbes                        reinterpret_cast<uint64_t &>(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
4659414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        "Cannot submit cmd buffer using image (0x%" PRIx64 ") [sub-resource: aspectMask 0x%X array layer %u, mip level %u], "
4660856ecb404bc959ddb877c150c9caa0649055b9cbMark Young                        "with layout %s when first use is %s.",
4661414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        reinterpret_cast<const uint64_t &>(cb_image_data.first.image), cb_image_data.first.subresource.aspectMask,
4662414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                cb_image_data.first.subresource.arrayLayer,
4663414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                cb_image_data.first.subresource.mipLevel, string_VkImageLayout(imageLayout),
4664856ecb404bc959ddb877c150c9caa0649055b9cbMark Young                        string_VkImageLayout(cb_image_data.second.initialLayout));
4665856ecb404bc959ddb877c150c9caa0649055b9cbMark Young                } else {
4666856ecb404bc959ddb877c150c9caa0649055b9cbMark Young                    skip_call |= log_msg(
4667856ecb404bc959ddb877c150c9caa0649055b9cbMark Young                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
4668971020aec6166f20a12a833ebd003e0193f4160aChris Forbes                        reinterpret_cast<uint64_t &>(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
4669414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        "Cannot submit cmd buffer using image (0x%" PRIx64 ") with layout %s when "
4670856ecb404bc959ddb877c150c9caa0649055b9cbMark Young                        "first use is %s.",
4671856ecb404bc959ddb877c150c9caa0649055b9cbMark Young                        reinterpret_cast<const uint64_t &>(cb_image_data.first.image), string_VkImageLayout(imageLayout),
4672856ecb404bc959ddb877c150c9caa0649055b9cbMark Young                        string_VkImageLayout(cb_image_data.second.initialLayout));
4673856ecb404bc959ddb877c150c9caa0649055b9cbMark Young                }
46745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
46755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            SetLayout(dev_data, cb_image_data.first, cb_image_data.second.layout);
46765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
46775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
46785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return skip_call;
46795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
468039d153555b5101b1b093d80100e329368c66b79dMark Lobodzinski
4681a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis// Loop through bound objects and increment their in_use counts
4682a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis//  For any unknown objects, flag an error
46832f8cbf3b166e175174877a59929902e005953d6dTobin Ehlisstatic bool ValidateAndIncrementBoundObjects(layer_data *dev_data, GLOBAL_CB_NODE const *cb_node) {
4684162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis    bool skip = false;
4685162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis    DRAW_STATE_ERROR error_code = DRAWSTATE_NONE;
4686162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis    BASE_NODE *base_obj = nullptr;
4687a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis    for (auto obj : cb_node->object_bindings) {
4688a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis        switch (obj.type) {
4689a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis        case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT: {
4690162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis            base_obj = getSetNode(dev_data, reinterpret_cast<VkDescriptorSet &>(obj.handle));
4691162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis            error_code = DRAWSTATE_INVALID_DESCRIPTOR_SET;
4692a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis            break;
4693a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis        }
469456f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis        case VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT: {
4695162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis            base_obj = getSamplerNode(dev_data, reinterpret_cast<VkSampler &>(obj.handle));
4696162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis            error_code = DRAWSTATE_INVALID_SAMPLER;
469756f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis            break;
469856f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis        }
46992f8cbf3b166e175174877a59929902e005953d6dTobin Ehlis        case VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT: {
4700162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis            base_obj = getQueryPoolNode(dev_data, reinterpret_cast<VkQueryPool &>(obj.handle));
4701162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis            error_code = DRAWSTATE_INVALID_QUERY_POOL;
47022f8cbf3b166e175174877a59929902e005953d6dTobin Ehlis            break;
47032f8cbf3b166e175174877a59929902e005953d6dTobin Ehlis        }
47042f8cbf3b166e175174877a59929902e005953d6dTobin Ehlis        case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT: {
4705162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis            base_obj = getPipeline(dev_data, reinterpret_cast<VkPipeline &>(obj.handle));
4706162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis            error_code = DRAWSTATE_INVALID_PIPELINE;
47072f8cbf3b166e175174877a59929902e005953d6dTobin Ehlis            break;
47082f8cbf3b166e175174877a59929902e005953d6dTobin Ehlis        }
47092f8cbf3b166e175174877a59929902e005953d6dTobin Ehlis        case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT: {
4710162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis            base_obj = getBufferNode(dev_data, reinterpret_cast<VkBuffer &>(obj.handle));
4711162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis            error_code = DRAWSTATE_INVALID_BUFFER;
47122f8cbf3b166e175174877a59929902e005953d6dTobin Ehlis            break;
47132f8cbf3b166e175174877a59929902e005953d6dTobin Ehlis        }
47147e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT: {
47157e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis            base_obj = getBufferViewState(dev_data, reinterpret_cast<VkBufferView &>(obj.handle));
47167e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis            error_code = DRAWSTATE_INVALID_BUFFER_VIEW;
47177e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis            break;
47187e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        }
47192f8cbf3b166e175174877a59929902e005953d6dTobin Ehlis        case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: {
4720162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis            base_obj = getImageNode(dev_data, reinterpret_cast<VkImage &>(obj.handle));
4721162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis            error_code = DRAWSTATE_INVALID_IMAGE;
47222f8cbf3b166e175174877a59929902e005953d6dTobin Ehlis            break;
47232f8cbf3b166e175174877a59929902e005953d6dTobin Ehlis        }
47247e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT: {
47257e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis            base_obj = getImageViewState(dev_data, reinterpret_cast<VkImageView &>(obj.handle));
47267e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis            error_code = DRAWSTATE_INVALID_IMAGE_VIEW;
47277e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis            break;
47287e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        }
47292f8cbf3b166e175174877a59929902e005953d6dTobin Ehlis        case VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT: {
4730162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis            base_obj = getEventNode(dev_data, reinterpret_cast<VkEvent &>(obj.handle));
4731162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis            error_code = DRAWSTATE_INVALID_EVENT;
47322f8cbf3b166e175174877a59929902e005953d6dTobin Ehlis            break;
47332f8cbf3b166e175174877a59929902e005953d6dTobin Ehlis        }
47347e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT: {
47357e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis            base_obj = getPoolNode(dev_data, reinterpret_cast<VkDescriptorPool &>(obj.handle));
47367e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis            error_code = DRAWSTATE_INVALID_DESCRIPTOR_POOL;
47377e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis            break;
47387e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        }
47397e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT: {
47407e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis            base_obj = getCommandPoolNode(dev_data, reinterpret_cast<VkCommandPool &>(obj.handle));
47417e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis            error_code = DRAWSTATE_INVALID_COMMAND_POOL;
47427e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis            break;
47437e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        }
47447e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        case VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT: {
47457e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis            base_obj = getFramebuffer(dev_data, reinterpret_cast<VkFramebuffer &>(obj.handle));
47467e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis            error_code = DRAWSTATE_INVALID_FRAMEBUFFER;
47477e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis            break;
47487e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        }
47497e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        case VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT: {
47507e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis            base_obj = getRenderPass(dev_data, reinterpret_cast<VkRenderPass &>(obj.handle));
47517e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis            error_code = DRAWSTATE_INVALID_RENDERPASS;
47527e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis            break;
47537e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        }
47547e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        case VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT: {
47557e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis            base_obj = getMemObjInfo(dev_data, reinterpret_cast<VkDeviceMemory &>(obj.handle));
47567e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis            error_code = DRAWSTATE_INVALID_DEVICE_MEMORY;
47577e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis            break;
47587e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        }
4759a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis        default:
4760a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis            // TODO : Merge handling of other objects types into this code
4761a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis            break;
4762a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis        }
4763162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis        if (!base_obj) {
4764162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis            skip |=
4765162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, obj.type, obj.handle, __LINE__, error_code, "DS",
4766162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis                        "Cannot submit cmd buffer using deleted %s 0x%" PRIx64 ".", object_type_to_string(obj.type), obj.handle);
4767162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis        } else {
4768162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis            base_obj->in_use.fetch_add(1);
4769162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis        }
4770a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis    }
4771162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis    return skip;
4772a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis}
4773a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis
47745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Track which resources are in-flight by atomically incrementing their "in_use" count
47759a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlisstatic bool validateAndIncrementResources(layer_data *dev_data, GLOBAL_CB_NODE *cb_node) {
4776e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool skip_call = false;
4777a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes
47789a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis    cb_node->in_use.fetch_add(1);
47799a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis    dev_data->globalInFlightCmdBuffers.insert(cb_node->commandBuffer);
4780a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes
4781a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis    // First Increment for all "generic" objects bound to cmd buffer, followed by special-case objects below
47829a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis    skip_call |= ValidateAndIncrementBoundObjects(dev_data, cb_node);
4783a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis    // TODO : We should be able to remove the NULL look-up checks from the code below as long as
4784a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis    //  all the corresponding cases are verified to cause CB_INVALID state and the CB_INVALID state
4785a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis    //  should then be flagged prior to calling this function
47869a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis    for (auto drawDataElement : cb_node->drawData) {
47875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (auto buffer : drawDataElement.buffers) {
47889a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis            auto buffer_node = getBufferNode(dev_data, buffer);
47898718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis            if (!buffer_node) {
47909a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis                skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT,
47915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                     (uint64_t)(buffer), __LINE__, DRAWSTATE_INVALID_BUFFER, "DS",
4792414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                     "Cannot submit cmd buffer using deleted buffer 0x%" PRIx64 ".", (uint64_t)(buffer));
47935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            } else {
47948718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis                buffer_node->in_use.fetch_add(1);
47955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
47965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
47975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
47989a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis    for (auto event : cb_node->writeEventsBeforeWait) {
47999a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis        auto event_node = getEventNode(dev_data, event);
48009556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis        if (event_node)
48019556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis            event_node->write_in_use++;
4802c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine    }
48035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return skip_call;
48045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
48055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4806b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine// Note: This function assumes that the global lock is held by the calling
4807b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine// thread.
48087d33205c3aa4aba751a2c07f956634aac616f916Chris Forbes// TODO: untangle this.
4809b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentinestatic bool cleanInFlightCmdBuffer(layer_data *my_data, VkCommandBuffer cmdBuffer) {
4810b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine    bool skip_call = false;
4811b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine    GLOBAL_CB_NODE *pCB = getCBNode(my_data, cmdBuffer);
4812b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine    if (pCB) {
4813b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine        for (auto queryEventsPair : pCB->waitedEventsBeforeQueryReset) {
4814b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine            for (auto event : queryEventsPair.second) {
4815b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine                if (my_data->eventMap[event].needsSignaled) {
4816b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine                    skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4817b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine                                         VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, 0, DRAWSTATE_INVALID_QUERY, "DS",
4818414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                         "Cannot get query results on queryPool 0x%" PRIx64
4819414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                         " with index %d which was guarded by unsignaled event 0x%" PRIx64 ".",
4820b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine                                         (uint64_t)(queryEventsPair.first.pool), queryEventsPair.first.index, (uint64_t)(event));
4821b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine                }
4822b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine            }
4823b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine        }
4824b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine    }
4825b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine    return skip_call;
4826b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine}
48277d33205c3aa4aba751a2c07f956634aac616f916Chris Forbes
48287d33205c3aa4aba751a2c07f956634aac616f916Chris Forbes// TODO: nuke this completely.
4829b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine// Decrement cmd_buffer in_use and if it goes to 0 remove cmd_buffer from globalInFlightCmdBuffers
4830b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentinestatic inline void removeInFlightCmdBuffer(layer_data *dev_data, VkCommandBuffer cmd_buffer) {
4831b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine    // Pull it off of global list initially, but if we find it in any other queue list, add it back in
4832b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, cmd_buffer);
4833b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine    pCB->in_use.fetch_sub(1);
4834b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine    if (!pCB->in_use.load()) {
4835b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine        dev_data->globalInFlightCmdBuffers.erase(cmd_buffer);
4836b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine    }
4837b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine}
4838b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine
4839a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis// Decrement in-use count for objects bound to command buffer
48402f8cbf3b166e175174877a59929902e005953d6dTobin Ehlisstatic void DecrementBoundResources(layer_data *dev_data, GLOBAL_CB_NODE const *cb_node) {
484100e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis    BASE_NODE *base_obj = nullptr;
4842a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis    for (auto obj : cb_node->object_bindings) {
48437e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        base_obj = GetStateStructPtrFromObject(dev_data, obj);
484400e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis        if (base_obj) {
484500e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis            base_obj->in_use.fetch_sub(1);
484600e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis        }
4847a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis    }
4848a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis}
4849da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes
48509867daedbf52debc77d6568162ee21e071699b80Chris Forbesstatic bool RetireWorkOnQueue(layer_data *dev_data, QUEUE_NODE *pQueue, uint64_t seq)
48519867daedbf52debc77d6568162ee21e071699b80Chris Forbes{
48529867daedbf52debc77d6568162ee21e071699b80Chris Forbes    bool skip_call = false; // TODO: extract everything that might fail to precheck
48539867daedbf52debc77d6568162ee21e071699b80Chris Forbes    std::unordered_map<VkQueue, uint64_t> otherQueueSeqs;
48549867daedbf52debc77d6568162ee21e071699b80Chris Forbes
48559867daedbf52debc77d6568162ee21e071699b80Chris Forbes    // Roll this queue forward, one submission at a time.
48569867daedbf52debc77d6568162ee21e071699b80Chris Forbes    while (pQueue->seq < seq) {
48579867daedbf52debc77d6568162ee21e071699b80Chris Forbes        auto & submission = pQueue->submissions.front();
48589867daedbf52debc77d6568162ee21e071699b80Chris Forbes
48599867daedbf52debc77d6568162ee21e071699b80Chris Forbes        for (auto & wait : submission.waitSemaphores) {
48609867daedbf52debc77d6568162ee21e071699b80Chris Forbes            auto pSemaphore = getSemaphoreNode(dev_data, wait.semaphore);
4861da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes            pSemaphore->in_use.fetch_sub(1);
48629867daedbf52debc77d6568162ee21e071699b80Chris Forbes            auto & lastSeq = otherQueueSeqs[wait.queue];
48639867daedbf52debc77d6568162ee21e071699b80Chris Forbes            lastSeq = std::max(lastSeq, wait.seq);
4864da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes        }
4865cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes
48669867daedbf52debc77d6568162ee21e071699b80Chris Forbes        for (auto & semaphore : submission.signalSemaphores) {
48679867daedbf52debc77d6568162ee21e071699b80Chris Forbes            auto pSemaphore = getSemaphoreNode(dev_data, semaphore);
48689867daedbf52debc77d6568162ee21e071699b80Chris Forbes            pSemaphore->in_use.fetch_sub(1);
48699867daedbf52debc77d6568162ee21e071699b80Chris Forbes        }
4870cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes
48719867daedbf52debc77d6568162ee21e071699b80Chris Forbes        for (auto cb : submission.cbs) {
48729a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis            auto cb_node = getCBNode(dev_data, cb);
4873a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis            // First perform decrement on general case bound objects
48749a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis            DecrementBoundResources(dev_data, cb_node);
48759a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis            for (auto drawDataElement : cb_node->drawData) {
48769867daedbf52debc77d6568162ee21e071699b80Chris Forbes                for (auto buffer : drawDataElement.buffers) {
48779867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    auto buffer_node = getBufferNode(dev_data, buffer);
48789867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    if (buffer_node) {
48799867daedbf52debc77d6568162ee21e071699b80Chris Forbes                        buffer_node->in_use.fetch_sub(1);
48809867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    }
48819867daedbf52debc77d6568162ee21e071699b80Chris Forbes                }
4882da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes            }
48839a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis            for (auto event : cb_node->writeEventsBeforeWait) {
48849867daedbf52debc77d6568162ee21e071699b80Chris Forbes                auto eventNode = dev_data->eventMap.find(event);
48859867daedbf52debc77d6568162ee21e071699b80Chris Forbes                if (eventNode != dev_data->eventMap.end()) {
48869867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    eventNode->second.write_in_use--;
48879867daedbf52debc77d6568162ee21e071699b80Chris Forbes                }
48889867daedbf52debc77d6568162ee21e071699b80Chris Forbes            }
48899a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis            for (auto queryStatePair : cb_node->queryToStateMap) {
48909867daedbf52debc77d6568162ee21e071699b80Chris Forbes                dev_data->queryToStateMap[queryStatePair.first] = queryStatePair.second;
48919867daedbf52debc77d6568162ee21e071699b80Chris Forbes            }
48929a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis            for (auto eventStagePair : cb_node->eventToStageMap) {
48939867daedbf52debc77d6568162ee21e071699b80Chris Forbes                dev_data->eventMap[eventStagePair.first].stageMask = eventStagePair.second;
4894da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes            }
48950a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine
48969867daedbf52debc77d6568162ee21e071699b80Chris Forbes            skip_call |= cleanInFlightCmdBuffer(dev_data, cb);
48979867daedbf52debc77d6568162ee21e071699b80Chris Forbes            removeInFlightCmdBuffer(dev_data, cb);
48980a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine        }
48999867daedbf52debc77d6568162ee21e071699b80Chris Forbes
49009867daedbf52debc77d6568162ee21e071699b80Chris Forbes        auto pFence = getFenceNode(dev_data, submission.fence);
49019867daedbf52debc77d6568162ee21e071699b80Chris Forbes        if (pFence) {
49029867daedbf52debc77d6568162ee21e071699b80Chris Forbes            pFence->state = FENCE_RETIRED;
49030a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine        }
49049867daedbf52debc77d6568162ee21e071699b80Chris Forbes
49059867daedbf52debc77d6568162ee21e071699b80Chris Forbes        pQueue->submissions.pop_front();
49069867daedbf52debc77d6568162ee21e071699b80Chris Forbes        pQueue->seq++;
4907b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    }
49089867daedbf52debc77d6568162ee21e071699b80Chris Forbes
49099867daedbf52debc77d6568162ee21e071699b80Chris Forbes    // Roll other queues forward to the highest seq we saw a wait for
49109867daedbf52debc77d6568162ee21e071699b80Chris Forbes    for (auto qs : otherQueueSeqs) {
49119867daedbf52debc77d6568162ee21e071699b80Chris Forbes        skip_call |= RetireWorkOnQueue(dev_data, getQueueNode(dev_data, qs.first), qs.second);
4912d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    }
49135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
49149867daedbf52debc77d6568162ee21e071699b80Chris Forbes    return skip_call;
49159867daedbf52debc77d6568162ee21e071699b80Chris Forbes}
4916651d92815dfff917308137bb67aacccc4f60df86Chris Forbes
4917651d92815dfff917308137bb67aacccc4f60df86Chris Forbes
4918651d92815dfff917308137bb67aacccc4f60df86Chris Forbes// Submit a fence to a queue, delimiting previous fences and previous untracked
4919651d92815dfff917308137bb67aacccc4f60df86Chris Forbes// work by it.
4920651d92815dfff917308137bb67aacccc4f60df86Chris Forbesstatic void
49219867daedbf52debc77d6568162ee21e071699b80Chris ForbesSubmitFence(QUEUE_NODE *pQueue, FENCE_NODE *pFence, uint64_t submitCount)
4922651d92815dfff917308137bb67aacccc4f60df86Chris Forbes{
4923cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes    pFence->state = FENCE_INFLIGHT;
49249867daedbf52debc77d6568162ee21e071699b80Chris Forbes    pFence->signaler.first = pQueue->queue;
49259867daedbf52debc77d6568162ee21e071699b80Chris Forbes    pFence->signaler.second = pQueue->seq + pQueue->submissions.size() + submitCount;
4926b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine}
4927b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine
4928e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool validateCommandBufferSimultaneousUse(layer_data *dev_data, GLOBAL_CB_NODE *pCB) {
49295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    bool skip_call = false;
49305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (dev_data->globalInFlightCmdBuffers.count(pCB->commandBuffer) &&
49315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) {
49325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        skip_call |=
49335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
493427c3e0dda9e30d1d334728bbd373e8d7011257d4Chris Forbes                    __LINE__, DRAWSTATE_INVALID_CB_SIMULTANEOUS_USE, "DS",
4935414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                    "Command Buffer 0x%" PRIx64 " is already in use and is not marked for simultaneous use.",
49365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    reinterpret_cast<uint64_t>(pCB->commandBuffer));
49375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
49385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return skip_call;
49395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
49405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
494175b0d6603382dcb3e3de24c11ea6e4aa2ef8b4d2Tobin Ehlisstatic bool validateCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *pCB, const char *call_source) {
4942c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis    bool skip = false;
4943c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis    if (dev_data->instance_state->disabled.command_buffer_state)
4944c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis        return skip;
49450a59acde4b40fde3bbfea5811d2abf2c85ca62f4Tobin Ehlis    // Validate ONE_TIME_SUBMIT_BIT CB is not being submitted more than once
49460a59acde4b40fde3bbfea5811d2abf2c85ca62f4Tobin Ehlis    if ((pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) && (pCB->submitCount > 1)) {
4947c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
4948c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis                        __LINE__, DRAWSTATE_COMMAND_BUFFER_SINGLE_SUBMIT_VIOLATION, "DS",
4949c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis                        "CB 0x%" PRIxLEAST64 " was begun w/ VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT "
4950c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis                        "set, but has been submitted 0x%" PRIxLEAST64 " times.",
4951c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis                        (uint64_t)(pCB->commandBuffer), pCB->submitCount);
49520a59acde4b40fde3bbfea5811d2abf2c85ca62f4Tobin Ehlis    }
49535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Validate that cmd buffers have been updated
49545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (CB_RECORDED != pCB->state) {
49555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (CB_INVALID == pCB->state) {
49565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // Inform app of reason CB invalid
4957e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis            for (auto obj : pCB->broken_bindings) {
4958e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis                const char *type_str = object_type_to_string(obj.type);
4959e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis                // Descriptor sets are a special case that can be either destroyed or updated to invalidated a CB
4960e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis                const char *cause_str =
4961e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis                    (obj.type == VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT) ? "destroyed or updated" : "destroyed";
49625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4963c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis                skip |=
49645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
49655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            reinterpret_cast<uint64_t &>(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
4966e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis                            "You are submitting command buffer 0x%" PRIxLEAST64 " that is invalid because bound %s 0x%" PRIxLEAST64
4967e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis                            " was %s.",
4968e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis                            reinterpret_cast<uint64_t &>(pCB->commandBuffer), type_str, obj.handle, cause_str);
49695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
49705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else { // Flag error for using CB w/o vkEndCommandBuffer() called
4971c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
4972c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis                            (uint64_t)(pCB->commandBuffer), __LINE__, DRAWSTATE_NO_END_COMMAND_BUFFER, "DS",
4973c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis                            "You must call vkEndCommandBuffer() on CB 0x%" PRIxLEAST64 " before this call to %s!",
4974c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis                            reinterpret_cast<uint64_t &>(pCB->commandBuffer), call_source);
49755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
49765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
4977c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis    return skip;
49785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
49795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
49807bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski// Validate that queueFamilyIndices of primary command buffers match this queue
49817bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski// Secondary command buffers were previously validated in vkCmdExecuteCommands().
49827bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinskistatic bool validateQueueFamilyIndices(layer_data *dev_data, GLOBAL_CB_NODE *pCB, VkQueue queue) {
49837bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski    bool skip_call = false;
49847bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski    auto pPool = getCommandPoolNode(dev_data, pCB->createInfo.commandPool);
49857bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski    auto queue_node = getQueueNode(dev_data, queue);
49867bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski
49877bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski    if (pPool && queue_node && (pPool->queueFamilyIndex != queue_node->queueFamilyIndex)) {
49887bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski        skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
49897bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski            reinterpret_cast<uint64_t>(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_QUEUE_FAMILY, "DS",
49907bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski            "vkQueueSubmit: Primary command buffer 0x%" PRIxLEAST64
49917bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski            " created in queue family %d is being submitted on queue 0x%" PRIxLEAST64 " from queue family %d.",
49927bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski            reinterpret_cast<uint64_t>(pCB->commandBuffer), pPool->queueFamilyIndex,
49937bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski            reinterpret_cast<uint64_t>(queue), queue_node->queueFamilyIndex);
49947bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski    }
49957bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski
49967bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski    return skip_call;
49977bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski}
49987bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski
4999da8f07baf262972eb3e719fa07b073c180dff157Chris Forbesstatic bool validatePrimaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *pCB) {
50005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Track in-use for resources off of primary and any secondary CBs
500183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
5002a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes
5003a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes    // If USAGE_SIMULTANEOUS_USE_BIT not set then CB cannot already be executing
5004a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes    // on device
500583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    skip_call |= validateCommandBufferSimultaneousUse(dev_data, pCB);
5006a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes
500783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    skip_call |= validateAndIncrementResources(dev_data, pCB);
5008a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes
50095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (!pCB->secondaryCommandBuffers.empty()) {
50105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (auto secondaryCmdBuffer : pCB->secondaryCommandBuffers) {
50115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            GLOBAL_CB_NODE *pSubCB = getCBNode(dev_data, secondaryCmdBuffer);
501283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= validateAndIncrementResources(dev_data, pSubCB);
50134c665b29a9d2906a378417546c7fc6436731d07fTobin Ehlis            if ((pSubCB->primaryCommandBuffer != pCB->commandBuffer) &&
50144c665b29a9d2906a378417546c7fc6436731d07fTobin Ehlis                !(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) {
50155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
50165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        __LINE__, DRAWSTATE_COMMAND_BUFFER_SINGLE_SUBMIT_VIOLATION, "DS",
5017414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        "CB 0x%" PRIxLEAST64 " was submitted with secondary buffer 0x%" PRIxLEAST64
50185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        " but that buffer has subsequently been bound to "
5019414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        "primary cmd buffer 0x%" PRIxLEAST64
50204c665b29a9d2906a378417546c7fc6436731d07fTobin Ehlis                        " and it does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set.",
50215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        reinterpret_cast<uint64_t>(pCB->commandBuffer), reinterpret_cast<uint64_t>(secondaryCmdBuffer),
50225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        reinterpret_cast<uint64_t>(pSubCB->primaryCommandBuffer));
50235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
50245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
50255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5026a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes
502775b0d6603382dcb3e3de24c11ea6e4aa2ef8b4d2Tobin Ehlis    skip_call |= validateCommandBufferState(dev_data, pCB, "vkQueueSubmit()");
5028a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes
502983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    return skip_call;
50305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
50315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
503281c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbesstatic bool
5033651d92815dfff917308137bb67aacccc4f60df86Chris ForbesValidateFenceForSubmit(layer_data *dev_data, FENCE_NODE *pFence)
503481c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes{
503583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
503681c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes
5037651d92815dfff917308137bb67aacccc4f60df86Chris Forbes    if (pFence) {
5038cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes        if (pFence->state == FENCE_INFLIGHT) {
503983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT,
504083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 (uint64_t)(pFence->fence), __LINE__, DRAWSTATE_INVALID_FENCE, "DS",
504183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 "Fence 0x%" PRIx64 " is already in use by another submission.", (uint64_t)(pFence->fence));
5042a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis        }
504381c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes
5044cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes        else if (pFence->state == FENCE_RETIRED) {
504583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |=
504683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT,
504783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                        reinterpret_cast<uint64_t &>(pFence->fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM",
504883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                        "Fence 0x%" PRIxLEAST64 " submitted in SIGNALED state.  Fences must be reset before being submitted",
504983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                        reinterpret_cast<uint64_t &>(pFence->fence));
5050a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis        }
50515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
505281c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes
505383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    return skip_call;
505481c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes}
505581c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes
5056651d92815dfff917308137bb67aacccc4f60df86Chris Forbes
505781c4a32a622486043c15e427fb0e85cc1cf7dd47Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL
505881c4a32a622486043c15e427fb0e85cc1cf7dd47Chris ForbesQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) {
505983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
506081c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
506181c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
506281c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes    std::unique_lock<std::mutex> lock(global_lock);
506381c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes
5064651d92815dfff917308137bb67aacccc4f60df86Chris Forbes    auto pQueue = getQueueNode(dev_data, queue);
5065651d92815dfff917308137bb67aacccc4f60df86Chris Forbes    auto pFence = getFenceNode(dev_data, fence);
506683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    skip_call |= ValidateFenceForSubmit(dev_data, pFence);
506781c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes
506883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (skip_call) {
5069d7d60cccc862fee2d0b3ad410c5fdcc40ddc83aeChris Forbes        return VK_ERROR_VALIDATION_FAILED_EXT;
5070d7d60cccc862fee2d0b3ad410c5fdcc40ddc83aeChris Forbes    }
5071d7d60cccc862fee2d0b3ad410c5fdcc40ddc83aeChris Forbes
50721344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis    // TODO : Review these old print functions and clean up as appropriate
50731344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis    print_mem_list(dev_data);
50741344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis    printCBList(dev_data);
5075651d92815dfff917308137bb67aacccc4f60df86Chris Forbes
5076651d92815dfff917308137bb67aacccc4f60df86Chris Forbes    // Mark the fence in-use.
5077651d92815dfff917308137bb67aacccc4f60df86Chris Forbes    if (pFence) {
50789867daedbf52debc77d6568162ee21e071699b80Chris Forbes        SubmitFence(pQueue, pFence, std::max(1u, submitCount));
5079651d92815dfff917308137bb67aacccc4f60df86Chris Forbes    }
5080651d92815dfff917308137bb67aacccc4f60df86Chris Forbes
50815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Now verify each individual submit
50825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
50835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        const VkSubmitInfo *submit = &pSubmits[submit_idx];
50849867daedbf52debc77d6568162ee21e071699b80Chris Forbes        vector<SEMAPHORE_WAIT> semaphore_waits;
50859867daedbf52debc77d6568162ee21e071699b80Chris Forbes        vector<VkSemaphore> semaphore_signals;
50865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t i = 0; i < submit->waitSemaphoreCount; ++i) {
508701a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes            VkSemaphore semaphore = submit->pWaitSemaphores[i];
508801a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes            auto pSemaphore = getSemaphoreNode(dev_data, semaphore);
508901a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes            if (pSemaphore) {
509001a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes                if (pSemaphore->signaled) {
50919867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    if (pSemaphore->signaler.first != VK_NULL_HANDLE) {
50929867daedbf52debc77d6568162ee21e071699b80Chris Forbes                        semaphore_waits.push_back({semaphore, pSemaphore->signaler.first, pSemaphore->signaler.second});
50939867daedbf52debc77d6568162ee21e071699b80Chris Forbes                        pSemaphore->in_use.fetch_add(1);
50949867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    }
50959867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    pSemaphore->signaler.first = VK_NULL_HANDLE;
509601a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes                    pSemaphore->signaled = false;
50971344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                } else {
509883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                    skip_call |=
50991344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                        log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT,
51001344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                                reinterpret_cast<const uint64_t &>(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS",
5101414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                "Queue 0x%" PRIx64 " is waiting on semaphore 0x%" PRIx64 " that has no way to be signaled.",
51021344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                                reinterpret_cast<uint64_t &>(queue), reinterpret_cast<const uint64_t &>(semaphore));
51031344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                }
51045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
51055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
51065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t i = 0; i < submit->signalSemaphoreCount; ++i) {
510701a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes            VkSemaphore semaphore = submit->pSignalSemaphores[i];
510801a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes            auto pSemaphore = getSemaphoreNode(dev_data, semaphore);
510901a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes            if (pSemaphore) {
511001a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes                if (pSemaphore->signaled) {
511183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                    skip_call |=
51121344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                        log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT,
51131344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                                reinterpret_cast<const uint64_t &>(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS",
5114414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                "Queue 0x%" PRIx64 " is signaling semaphore 0x%" PRIx64
5115414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                " that has already been signaled but not waited on by queue 0x%" PRIx64 ".",
51161344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                                reinterpret_cast<uint64_t &>(queue), reinterpret_cast<const uint64_t &>(semaphore),
51179867daedbf52debc77d6568162ee21e071699b80Chris Forbes                                reinterpret_cast<uint64_t &>(pSemaphore->signaler.first));
51181344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                } else {
51199867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    pSemaphore->signaler.first = queue;
51209867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    pSemaphore->signaler.second = pQueue->seq + pQueue->submissions.size() + 1;
512101a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes                    pSemaphore->signaled = true;
5122da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes                    pSemaphore->in_use.fetch_add(1);
51239867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    semaphore_signals.push_back(semaphore);
51241344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                }
51250a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine            }
51265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
5127651d92815dfff917308137bb67aacccc4f60df86Chris Forbes
5128da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes        std::vector<VkCommandBuffer> cbs;
5129da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes
51305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
5131971020aec6166f20a12a833ebd003e0193f4160aChris Forbes            auto pCBNode = getCBNode(dev_data, submit->pCommandBuffers[i]);
513283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= ValidateCmdBufImageLayouts(dev_data, pCBNode);
51331344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis            if (pCBNode) {
5134da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes                cbs.push_back(submit->pCommandBuffers[i]);
5135651d92815dfff917308137bb67aacccc4f60df86Chris Forbes                for (auto secondaryCmdBuffer : pCBNode->secondaryCommandBuffers) {
5136da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes                    cbs.push_back(secondaryCmdBuffer);
5137651d92815dfff917308137bb67aacccc4f60df86Chris Forbes                }
5138651d92815dfff917308137bb67aacccc4f60df86Chris Forbes
51391344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                pCBNode->submitCount++; // increment submit count
514083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                skip_call |= validatePrimaryCommandBufferState(dev_data, pCBNode);
51417bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski                skip_call |= validateQueueFamilyIndices(dev_data, pCBNode, queue);
5142ea371fa7c8c57edb4d1436e4570cf54f3fc0463fTobin Ehlis                // Potential early exit here as bad object state may crash in delayed function calls
5143ea371fa7c8c57edb4d1436e4570cf54f3fc0463fTobin Ehlis                if (skip_call)
5144ea371fa7c8c57edb4d1436e4570cf54f3fc0463fTobin Ehlis                    return result;
51451344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                // Call submit-time functions to validate/update state
51461344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                for (auto &function : pCBNode->validate_functions) {
514783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                    skip_call |= function();
51481344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                }
51491344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                for (auto &function : pCBNode->eventUpdates) {
515083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                    skip_call |= function(queue);
51511344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                }
5152d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine                for (auto &function : pCBNode->queryUpdates) {
515383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                    skip_call |= function(queue);
5154d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine                }
51551344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis            }
51565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
5157da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes
51589867daedbf52debc77d6568162ee21e071699b80Chris Forbes        pQueue->submissions.emplace_back(cbs, semaphore_waits, semaphore_signals,
51599867daedbf52debc77d6568162ee21e071699b80Chris Forbes                                         submit_idx == submitCount - 1 ? fence : VK_NULL_HANDLE);
51609867daedbf52debc77d6568162ee21e071699b80Chris Forbes    }
51619867daedbf52debc77d6568162ee21e071699b80Chris Forbes
51629867daedbf52debc77d6568162ee21e071699b80Chris Forbes    if (pFence && !submitCount) {
51639867daedbf52debc77d6568162ee21e071699b80Chris Forbes        // If no submissions, but just dropping a fence on the end of the queue,
51649867daedbf52debc77d6568162ee21e071699b80Chris Forbes        // record an empty submission with just the fence, so we can determine
51659867daedbf52debc77d6568162ee21e071699b80Chris Forbes        // its completion.
51669867daedbf52debc77d6568162ee21e071699b80Chris Forbes        pQueue->submissions.emplace_back(std::vector<VkCommandBuffer>(),
51679867daedbf52debc77d6568162ee21e071699b80Chris Forbes                                         std::vector<SEMAPHORE_WAIT>(),
51689867daedbf52debc77d6568162ee21e071699b80Chris Forbes                                         std::vector<VkSemaphore>(),
51699867daedbf52debc77d6568162ee21e071699b80Chris Forbes                                         fence);
51705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
51719867daedbf52debc77d6568162ee21e071699b80Chris Forbes
5172b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
517383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
51744a0754042cf090e131e9e769d8a3633c228625beChris Forbes        result = dev_data->dispatch_table.QueueSubmit(queue, submitCount, pSubmits, fence);
51755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
51765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
51775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
51785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
517989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL AllocateMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo,
518089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                              const VkAllocationCallbacks *pAllocator, VkDeviceMemory *pMemory) {
51815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
51824a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = my_data->dispatch_table.AllocateMemory(device, pAllocateInfo, pAllocator, pMemory);
51835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TODO : Track allocations and overall size here
5184b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::lock_guard<std::mutex> lock(global_lock);
51855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    add_mem_obj_info(my_data, device, *pMemory, pAllocateInfo);
51860a1ce3dfd81c9f4efbe46f5ba5ddaea70bc4aa61Chris Forbes    print_mem_list(my_data);
51875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
51885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
51895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
519089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
519189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuFreeMemory(VkDevice device, VkDeviceMemory mem, const VkAllocationCallbacks *pAllocator) {
51925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
51935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
51945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // From spec : A memory object is freed by calling vkFreeMemory() when it is no longer needed.
51955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Before freeing a memory object, an application must ensure the memory object is no longer
51965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // in use by the device—for example by command buffers queued for execution. The memory need
51975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // not yet be unbound from all images and buffers, but any further use of those images or
51985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // buffers (on host or device) for anything other than destroying those objects will result in
51995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // undefined behavior.
52005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5201b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
520274243a735fe102b370237ddf80d3e6f7ec5246dbMark Mueller    bool skip_call = freeMemObjInfo(my_data, device, mem, false);
52030a1ce3dfd81c9f4efbe46f5ba5ddaea70bc4aa61Chris Forbes    print_mem_list(my_data);
52040a1ce3dfd81c9f4efbe46f5ba5ddaea70bc4aa61Chris Forbes    printCBList(my_data);
5205b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
520674243a735fe102b370237ddf80d3e6f7ec5246dbMark Mueller    if (!skip_call) {
52074a0754042cf090e131e9e769d8a3633c228625beChris Forbes        my_data->dispatch_table.FreeMemory(device, mem, pAllocator);
520874243a735fe102b370237ddf80d3e6f7ec5246dbMark Mueller    }
52095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
52105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5211f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis// Validate that given Map memory range is valid. This means that the memory should not already be mapped,
5212f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis//  and that the size of the map range should be:
5213f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis//  1. Not zero
5214f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis//  2. Within the size of the memory allocation
5215f57fc64ac43691ad98e1713886b345465573070aTobin Ehlisstatic bool ValidateMapMemRange(layer_data *my_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size) {
521683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
52175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
52185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (size == 0) {
521983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
522083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, "MEM",
522183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            "VkMapMemory: Attempting to map memory range of size zero");
52225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
52235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
52245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    auto mem_element = my_data->memObjMap.find(mem);
52255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (mem_element != my_data->memObjMap.end()) {
522657fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis        auto mem_info = mem_element->second.get();
52275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // It is an application error to call VkMapMemory on an object that is already mapped
5228de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        if (mem_info->mem_range.size != 0) {
522983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
523083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, "MEM",
523183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                "VkMapMemory: Attempting to map memory on an already-mapped object 0x%" PRIxLEAST64, (uint64_t)mem);
52325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
52335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
52345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Validate that offset + size is within object's allocationSize
52355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (size == VK_WHOLE_SIZE) {
5236de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis            if (offset >= mem_info->alloc_info.allocationSize) {
523783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                skip_call = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
523883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                    VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP,
523983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                    "MEM", "Mapping Memory from 0x%" PRIx64 " to 0x%" PRIx64
524083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                           " with size of VK_WHOLE_SIZE oversteps total array size 0x%" PRIx64,
5241de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis                                    offset, mem_info->alloc_info.allocationSize, mem_info->alloc_info.allocationSize);
52425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
52435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
5244de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis            if ((offset + size) > mem_info->alloc_info.allocationSize) {
524583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                skip_call =
524657fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis                    log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
524757fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis                            (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, "MEM",
524857fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis                            "Mapping Memory from 0x%" PRIx64 " to 0x%" PRIx64 " oversteps total array size 0x%" PRIx64, offset,
5249de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis                            size + offset, mem_info->alloc_info.allocationSize);
52505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
52515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
52525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
525383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    return skip_call;
52545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
52555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5256e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic void storeMemRanges(layer_data *my_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size) {
525757fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis    auto mem_info = getMemObjInfo(my_data, mem);
525857fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis    if (mem_info) {
5259de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        mem_info->mem_range.offset = offset;
5260de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        mem_info->mem_range.size = size;
52615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
52625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
52635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5264e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool deleteMemRanges(layer_data *my_data, VkDeviceMemory mem) {
526583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
526657fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis    auto mem_info = getMemObjInfo(my_data, mem);
526757fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis    if (mem_info) {
5268de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        if (!mem_info->mem_range.size) {
52695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // Valid Usage: memory must currently be mapped
527083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
527183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, "MEM",
527283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                "Unmapping Memory without memory being mapped: mem obj 0x%" PRIxLEAST64, (uint64_t)mem);
52735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
5274de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        mem_info->mem_range.size = 0;
52755f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski        if (mem_info->shadow_copy) {
52765f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            free(mem_info->shadow_copy_base);
52775f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            mem_info->shadow_copy_base = 0;
52785f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            mem_info->shadow_copy = 0;
52795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
52805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
528183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    return skip_call;
52825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
52835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
52845f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski// Guard value for pad data
52855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic char NoncoherentMemoryFillValue = 0xb;
52865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
52875f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinskistatic void initializeAndTrackMemory(layer_data *dev_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size,
52885f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                                     void **ppData) {
528957fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis    auto mem_info = getMemObjInfo(dev_data, mem);
529057fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis    if (mem_info) {
5291de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        mem_info->p_driver_data = *ppData;
5292de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        uint32_t index = mem_info->alloc_info.memoryTypeIndex;
5293b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis        if (dev_data->phys_dev_mem_props.memoryTypes[index].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) {
52945f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            mem_info->shadow_copy = 0;
52955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
52965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (size == VK_WHOLE_SIZE) {
52975f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                size = mem_info->alloc_info.allocationSize - offset;
52985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
52995f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            mem_info->shadow_pad_size = dev_data->phys_dev_properties.properties.limits.minMemoryMapAlignment;
53005f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            assert(vk_safe_modulo(mem_info->shadow_pad_size,
53015f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                                  dev_data->phys_dev_properties.properties.limits.minMemoryMapAlignment) == 0);
53025f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            // Ensure start of mapped region reflects hardware alignment constraints
53035f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            uint64_t map_alignment = dev_data->phys_dev_properties.properties.limits.minMemoryMapAlignment;
53045f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski
53055f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            // From spec: (ppData - offset) must be aligned to at least limits::minMemoryMapAlignment.
53065f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            uint64_t start_offset = offset % map_alignment;
53075f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            // Data passed to driver will be wrapped by a guardband of data to detect over- or under-writes.
53086e17c244b21ce43ac57404a00a0d844039eed363Mark Lobodzinski            mem_info->shadow_copy_base = malloc(static_cast<size_t>(2 * mem_info->shadow_pad_size + size + map_alignment + start_offset));
53095f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski
53105f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            mem_info->shadow_copy =
53115f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                reinterpret_cast<char *>((reinterpret_cast<uintptr_t>(mem_info->shadow_copy_base) + map_alignment) &
53125f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                                         ~(map_alignment - 1)) + start_offset;
53135f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            assert(vk_safe_modulo(reinterpret_cast<uintptr_t>(mem_info->shadow_copy) + mem_info->shadow_pad_size - start_offset,
53145f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                                  map_alignment) == 0);
53155f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski
53166e17c244b21ce43ac57404a00a0d844039eed363Mark Lobodzinski            memset(mem_info->shadow_copy, NoncoherentMemoryFillValue, static_cast<size_t>(2 * mem_info->shadow_pad_size + size));
53175f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            *ppData = static_cast<char *>(mem_info->shadow_copy) + mem_info->shadow_pad_size;
53185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
53195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
53205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
53215f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski
5322a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis// Verify that state for fence being waited on is appropriate. That is,
53239867daedbf52debc77d6568162ee21e071699b80Chris Forbes//  a fence being waited on should not already be signaled and
5324a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis//  it should have been submitted on a queue or during acquire next image
532549f6132af865afd5b7f413c91125971ac97c135aChris Forbesstatic inline bool verifyWaitFenceState(layer_data *dev_data, VkFence fence, const char *apiCall) {
532683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
53279b48b44dd917f95b5f34dd629ec4076fc87eb3a2Chris Forbes
532849f6132af865afd5b7f413c91125971ac97c135aChris Forbes    auto pFence = getFenceNode(dev_data, fence);
53299b48b44dd917f95b5f34dd629ec4076fc87eb3a2Chris Forbes    if (pFence) {
5330cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes        if (pFence->state == FENCE_UNSIGNALED) {
533183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT,
533283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 reinterpret_cast<uint64_t &>(fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM",
533383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 "%s called for fence 0x%" PRIxLEAST64 " which has not been submitted on a Queue or during "
533483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 "acquire next image.",
533583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 apiCall, reinterpret_cast<uint64_t &>(fence));
53365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
53375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
533883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    return skip_call;
53395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
5340a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis
5341b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbesstatic bool RetireFence(layer_data *dev_data, VkFence fence) {
5342b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes    auto pFence = getFenceNode(dev_data, fence);
5343b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes    if (pFence->signaler.first != VK_NULL_HANDLE) {
5344b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes        /* Fence signaller is a queue -- use this as proof that prior operations
5345b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes         * on that queue have completed.
5346b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes         */
5347b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes        return RetireWorkOnQueue(dev_data,
5348b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes                                 getQueueNode(dev_data, pFence->signaler.first),
5349b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes                                 pFence->signaler.second);
5350b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes    }
5351d4513979120463171eb479cdded9336eb9944da1Chris Forbes    else {
5352d4513979120463171eb479cdded9336eb9944da1Chris Forbes        /* Fence signaller is the WSI. We're not tracking what the WSI op
5353d4513979120463171eb479cdded9336eb9944da1Chris Forbes         * actually /was/ in CV yet, but we need to mark the fence as retired.
5354d4513979120463171eb479cdded9336eb9944da1Chris Forbes         */
5355d4513979120463171eb479cdded9336eb9944da1Chris Forbes        pFence->state = FENCE_RETIRED;
5356d4513979120463171eb479cdded9336eb9944da1Chris Forbes        return false;
5357d4513979120463171eb479cdded9336eb9944da1Chris Forbes    }
5358b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes}
5359b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes
536089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL
536189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuWaitForFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences, VkBool32 waitAll, uint64_t timeout) {
53625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
5363e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool skip_call = false;
53645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Verify fence status of submitted fences
5365b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
53665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < fenceCount; i++) {
536749f6132af865afd5b7f413c91125971ac97c135aChris Forbes        skip_call |= verifyWaitFenceState(dev_data, pFences[i], "vkWaitForFences");
53685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5369b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
53705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (skip_call)
53715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return VK_ERROR_VALIDATION_FAILED_EXT;
5372a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis
53734a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.WaitForFences(device, fenceCount, pFences, waitAll, timeout);
5374414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller
53755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (result == VK_SUCCESS) {
5376b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.lock();
53775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // When we know that all fences are complete we can clean/remove their CBs
53785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (waitAll || fenceCount == 1) {
53799867daedbf52debc77d6568162ee21e071699b80Chris Forbes            for (uint32_t i = 0; i < fenceCount; i++) {
5380b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes                skip_call |= RetireFence(dev_data, pFences[i]);
53819867daedbf52debc77d6568162ee21e071699b80Chris Forbes            }
53825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
53835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // NOTE : Alternate case not handled here is when some fences have completed. In
53845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        //  this case for app to guarantee which fences completed it will have to call
53855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        //  vkGetFenceStatus() at which point we'll clean/remove their CBs if complete.
5386b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
53875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5388e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    if (skip_call)
53895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return VK_ERROR_VALIDATION_FAILED_EXT;
53905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
53915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
53925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
539389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL GetFenceStatus(VkDevice device, VkFence fence) {
53945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
539583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
5396b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
539783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    skip_call = verifyWaitFenceState(dev_data, fence, "vkGetFenceStatus");
5398b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
5399a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis
540083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (skip_call)
540183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        return VK_ERROR_VALIDATION_FAILED_EXT;
5402a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis
54034a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.GetFenceStatus(device, fence);
5404b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.lock();
54055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (result == VK_SUCCESS) {
5406d4513979120463171eb479cdded9336eb9944da1Chris Forbes        skip_call |= RetireFence(dev_data, fence);
54075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5408b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
5409e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    if (skip_call)
54105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return VK_ERROR_VALIDATION_FAILED_EXT;
54115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
54125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
54135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
541489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex,
5415b376edacad6f7ab3fcc0a914e9b1673a9fcd5143Mark Lobodzinski                                                            VkQueue *pQueue) {
54165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
54174a0754042cf090e131e9e769d8a3633c228625beChris Forbes    dev_data->dispatch_table.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
5418b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::lock_guard<std::mutex> lock(global_lock);
5419b376edacad6f7ab3fcc0a914e9b1673a9fcd5143Mark Lobodzinski
5420b376edacad6f7ab3fcc0a914e9b1673a9fcd5143Mark Lobodzinski    // Add queue to tracking set only if it is new
5421b376edacad6f7ab3fcc0a914e9b1673a9fcd5143Mark Lobodzinski    auto result = dev_data->queues.emplace(*pQueue);
5422b376edacad6f7ab3fcc0a914e9b1673a9fcd5143Mark Lobodzinski    if (result.second == true) {
5423b376edacad6f7ab3fcc0a914e9b1673a9fcd5143Mark Lobodzinski        QUEUE_NODE *pQNode = &dev_data->queueMap[*pQueue];
54248988ad37ea5a054ff2ae3cbe4b767ae6c13cf48bChris Forbes        pQNode->queue = *pQueue;
54257bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski        pQNode->queueFamilyIndex = queueFamilyIndex;
54269867daedbf52debc77d6568162ee21e071699b80Chris Forbes        pQNode->seq = 0;
5427b376edacad6f7ab3fcc0a914e9b1673a9fcd5143Mark Lobodzinski    }
54285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
54295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
543089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL QueueWaitIdle(VkQueue queue) {
54315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
5432e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool skip_call = false;
54339867daedbf52debc77d6568162ee21e071699b80Chris Forbes    std::unique_lock<std::mutex> lock(global_lock);
54349867daedbf52debc77d6568162ee21e071699b80Chris Forbes    auto pQueue = getQueueNode(dev_data, queue);
54359867daedbf52debc77d6568162ee21e071699b80Chris Forbes    skip_call |= RetireWorkOnQueue(dev_data, pQueue, pQueue->seq + pQueue->submissions.size());
54369867daedbf52debc77d6568162ee21e071699b80Chris Forbes    lock.unlock();
5437e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    if (skip_call)
54385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return VK_ERROR_VALIDATION_FAILED_EXT;
54394a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.QueueWaitIdle(queue);
54405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
54415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
54425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
544389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL DeviceWaitIdle(VkDevice device) {
5444e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool skip_call = false;
54455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
5446b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
54479867daedbf52debc77d6568162ee21e071699b80Chris Forbes    for (auto & queue : dev_data->queueMap) {
54489867daedbf52debc77d6568162ee21e071699b80Chris Forbes        skip_call |= RetireWorkOnQueue(dev_data, &queue.second, queue.second.seq + queue.second.submissions.size());
54495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5450b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
5451e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    if (skip_call)
54525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return VK_ERROR_VALIDATION_FAILED_EXT;
54534a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.DeviceWaitIdle(device);
54545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
54555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
54565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
545789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyFence(VkDevice device, VkFence fence, const VkAllocationCallbacks *pAllocator) {
54585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
545983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
5460b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
54611344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis    auto fence_pair = dev_data->fenceMap.find(fence);
54621344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis    if (fence_pair != dev_data->fenceMap.end()) {
5463cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes        if (fence_pair->second.state == FENCE_INFLIGHT) {
546483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT,
546583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 (uint64_t)(fence), __LINE__, DRAWSTATE_INVALID_FENCE, "DS", "Fence 0x%" PRIx64 " is in use.",
546683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 (uint64_t)(fence));
54671344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis        }
54681344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis        dev_data->fenceMap.erase(fence_pair);
54695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5470b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
54711344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis
547283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
54734a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyFence(device, fence, pAllocator);
54745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
54755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5476eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis// For given obj node, if it is use, flag a validation error and return callback result, else return false
5477eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlisbool ValidateObjectNotInUse(const layer_data *dev_data, BASE_NODE *obj_node, VK_OBJECT obj_struct) {
54787626815e3c23be98681f3fcf733ee938022af612Tobin Ehlis    if (dev_data->instance_state->disabled.object_in_use)
54797626815e3c23be98681f3fcf733ee938022af612Tobin Ehlis        return false;
5480eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis    bool skip = false;
5481eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis    if (obj_node->in_use.load()) {
5482eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, obj_struct.type, obj_struct.handle, __LINE__,
5483f4cc4424ca6a7819cd8e9ed646d337b4a74ed7f3Tobin Ehlis                        DRAWSTATE_OBJECT_INUSE, "DS", "Cannot delete %s 0x%" PRIx64 " that is currently in use by a command buffer.",
5484eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis                        object_type_to_string(obj_struct.type), obj_struct.handle);
5485eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis    }
5486eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis    return skip;
5487eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis}
5488eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis
548989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
549089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuDestroySemaphore(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks *pAllocator) {
54915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
5492eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis    bool skip = false;
5493e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis    std::unique_lock<std::mutex> lock(global_lock);
5494eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis    auto sema_node = getSemaphoreNode(dev_data, semaphore);
5495eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis    if (sema_node) {
5496eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis        skip |= ValidateObjectNotInUse(dev_data, sema_node,
5497eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis                                       {reinterpret_cast<uint64_t &>(semaphore), VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT});
54985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5499eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis    if (!skip) {
5500eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis        dev_data->semaphoreMap.erase(semaphore);
5501eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis        lock.unlock();
55024a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroySemaphore(device, semaphore, pAllocator);
550399d938c90c2f000ee73fb13513dacf84ffa5651fMark Mueller    }
55045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
55055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
550689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyEvent(VkDevice device, VkEvent event, const VkAllocationCallbacks *pAllocator) {
55075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
5508eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis    bool skip = false;
5509b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
55109556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis    auto event_node = getEventNode(dev_data, event);
55119556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis    if (event_node) {
5512eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis        VK_OBJECT obj_struct = {reinterpret_cast<uint64_t &>(event), VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT};
5513eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis        skip |= ValidateObjectNotInUse(dev_data, event_node, obj_struct);
55149556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis        // Any bound cmd buffers are now invalid
5515eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis        invalidateCommandBuffers(event_node->cb_bindings, obj_struct);
55169556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis    }
5517f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis    if (!skip) {
5518f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis        dev_data->eventMap.erase(event);
5519f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis        lock.unlock();
55204a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyEvent(device, event, pAllocator);
5521f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis    }
55225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
55235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
552489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
552589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuDestroyQueryPool(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks *pAllocator) {
5526ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
5527eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis    bool skip = false;
5528ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis    std::unique_lock<std::mutex> lock(global_lock);
5529ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis    auto qp_node = getQueryPoolNode(dev_data, queryPool);
5530ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis    if (qp_node) {
5531eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis        VK_OBJECT obj_struct = {reinterpret_cast<uint64_t &>(queryPool), VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT};
5532eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis        skip |= ValidateObjectNotInUse(dev_data, qp_node, obj_struct);
5533ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis        // Any bound cmd buffers are now invalid
5534eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis        invalidateCommandBuffers(qp_node->cb_bindings, obj_struct);
5535ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis    }
5536f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis    if (!skip) {
5537f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis        dev_data->queryPoolMap.erase(queryPool);
5538f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis        lock.unlock();
55394a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyQueryPool(device, queryPool, pAllocator);
5540f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis    }
55415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
55425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
554389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL GetQueryPoolResults(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery,
554489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                   uint32_t queryCount, size_t dataSize, void *pData, VkDeviceSize stride,
554589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                   VkQueryResultFlags flags) {
55465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
55475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<QueryObject, vector<VkCommandBuffer>> queriesInFlight;
5548b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
55495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (auto cmdBuffer : dev_data->globalInFlightCmdBuffers) {
5550971020aec6166f20a12a833ebd003e0193f4160aChris Forbes        auto pCB = getCBNode(dev_data, cmdBuffer);
55515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (auto queryStatePair : pCB->queryToStateMap) {
55525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            queriesInFlight[queryStatePair.first].push_back(cmdBuffer);
55535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
55545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5555e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool skip_call = false;
55565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < queryCount; ++i) {
55575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        QueryObject query = {queryPool, firstQuery + i};
55585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto queryElement = queriesInFlight.find(query);
55595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto queryToStateElement = dev_data->queryToStateMap.find(query);
55605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (queryToStateElement != dev_data->queryToStateMap.end()) {
5561ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski            // Available and in flight
5562ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski            if (queryElement != queriesInFlight.end() && queryToStateElement != dev_data->queryToStateMap.end() &&
5563ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                queryToStateElement->second) {
5564ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                for (auto cmdBuffer : queryElement->second) {
5565971020aec6166f20a12a833ebd003e0193f4160aChris Forbes                    auto pCB = getCBNode(dev_data, cmdBuffer);
5566ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                    auto queryEventElement = pCB->waitedEventsBeforeQueryReset.find(query);
5567ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                    if (queryEventElement == pCB->waitedEventsBeforeQueryReset.end()) {
5568ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                        skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
5569ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                                             VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, __LINE__, DRAWSTATE_INVALID_QUERY, "DS",
5570414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                             "Cannot get query results on queryPool 0x%" PRIx64 " with index %d which is in flight.",
5571ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                                             (uint64_t)(queryPool), firstQuery + i);
5572ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                    } else {
5573ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                        for (auto event : queryEventElement->second) {
5574ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                            dev_data->eventMap[event].needsSignaled = true;
5575ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                        }
5576ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                    }
5577ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                }
5578ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                // Unavailable and in flight
5579ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski            } else if (queryElement != queriesInFlight.end() && queryToStateElement != dev_data->queryToStateMap.end() &&
5580ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                       !queryToStateElement->second) {
5581ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                // TODO : Can there be the same query in use by multiple command buffers in flight?
5582ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                bool make_available = false;
5583ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                for (auto cmdBuffer : queryElement->second) {
5584971020aec6166f20a12a833ebd003e0193f4160aChris Forbes                    auto pCB = getCBNode(dev_data, cmdBuffer);
5585ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                    make_available |= pCB->queryToStateMap[query];
5586ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                }
5587ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                if (!(((flags & VK_QUERY_RESULT_PARTIAL_BIT) || (flags & VK_QUERY_RESULT_WAIT_BIT)) && make_available)) {
55885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
55895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                         VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, __LINE__, DRAWSTATE_INVALID_QUERY, "DS",
5590414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                         "Cannot get query results on queryPool 0x%" PRIx64 " with index %d which is unavailable.",
55915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                         (uint64_t)(queryPool), firstQuery + i);
55925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
5593ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                // Unavailable
5594ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski            } else if (queryToStateElement != dev_data->queryToStateMap.end() && !queryToStateElement->second) {
55955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
55965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                     VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, __LINE__, DRAWSTATE_INVALID_QUERY, "DS",
5597414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                     "Cannot get query results on queryPool 0x%" PRIx64 " with index %d which is unavailable.",
55985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                     (uint64_t)(queryPool), firstQuery + i);
5599ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                // Unitialized
5600ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski            } else if (queryToStateElement == dev_data->queryToStateMap.end()) {
5601ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
5602ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                                     VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, __LINE__, DRAWSTATE_INVALID_QUERY, "DS",
5603414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                     "Cannot get query results on queryPool 0x%" PRIx64
5604ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                                     " with index %d as data has not been collected for this index.",
5605ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                                     (uint64_t)(queryPool), firstQuery + i);
56065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
56075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
56085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5609b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
56105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (skip_call)
56115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return VK_ERROR_VALIDATION_FAILED_EXT;
56124a0754042cf090e131e9e769d8a3633c228625beChris Forbes    return dev_data->dispatch_table.GetQueryPoolResults(device, queryPool, firstQuery, queryCount, dataSize, pData, stride, flags);
56135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
56145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5615e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool validateIdleBuffer(const layer_data *my_data, VkBuffer buffer) {
5616e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool skip_call = false;
56178718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis    auto buffer_node = getBufferNode(my_data, buffer);
56188718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis    if (!buffer_node) {
56195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT,
56205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                             (uint64_t)(buffer), __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS",
5621414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                             "Cannot free buffer 0x%" PRIxLEAST64 " that has not been allocated.", (uint64_t)(buffer));
56225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
56238718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis        if (buffer_node->in_use.load()) {
56245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT,
56255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                 (uint64_t)(buffer), __LINE__, DRAWSTATE_OBJECT_INUSE, "DS",
5626414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                 "Cannot free buffer 0x%" PRIxLEAST64 " that is in use by a command buffer.", (uint64_t)(buffer));
56275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
56285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
56295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return skip_call;
56305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
56315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5632825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Return true if given ranges intersect, else false
5633825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Prereq : For both ranges, range->end - range->start > 0. This case should have already resulted
5634825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis//  in an error so not checking that here
5635825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// pad_ranges bool indicates a linear and non-linear comparison which requires padding
5636825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// In the case where padding is required, if an alias is encountered then a validation error is reported and skip_call
5637825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis//  may be set by the callback function so caller should merge in skip_call value if padding case is possible.
56387dc3fbb89e2dcf3df8fc2e6639a867a959fef3f3Tobin Ehlisstatic bool rangesIntersect(layer_data const *dev_data, MEMORY_RANGE const *range1, MEMORY_RANGE const *range2, bool *skip_call) {
56397dc3fbb89e2dcf3df8fc2e6639a867a959fef3f3Tobin Ehlis    *skip_call = false;
5640825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    auto r1_start = range1->start;
5641825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    auto r1_end = range1->end;
5642825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    auto r2_start = range2->start;
5643825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    auto r2_end = range2->end;
5644825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    VkDeviceSize pad_align = 1;
5645825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    if (range1->linear != range2->linear) {
5646825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        pad_align = dev_data->phys_dev_properties.properties.limits.bufferImageGranularity;
5647825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    }
5648825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    if ((r1_end & ~(pad_align - 1)) < (r2_start & ~(pad_align - 1)))
5649825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        return false;
5650825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    if ((r1_start & ~(pad_align - 1)) > (r2_end & ~(pad_align - 1)))
5651825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        return false;
565247aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski
5653825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    if (range1->linear != range2->linear) {
5654825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        // In linear vs. non-linear case, it's an error to alias
5655825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        const char *r1_linear_str = range1->linear ? "Linear" : "Non-linear";
5656825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        const char *r1_type_str = range1->image ? "image" : "buffer";
5657825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        const char *r2_linear_str = range2->linear ? "linear" : "non-linear";
5658825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        const char *r2_type_str = range2->image ? "image" : "buffer";
5659825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        auto obj_type = range1->image ? VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT : VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT;
56607dc3fbb89e2dcf3df8fc2e6639a867a959fef3f3Tobin Ehlis        *skip_call |=
5661825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis            log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, obj_type, range1->handle, 0, MEMTRACK_INVALID_ALIASING,
5662825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis                    "MEM", "%s %s 0x%" PRIx64 " is aliased with %s %s 0x%" PRIx64
5663825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis                           " which is in violation of the Buffer-Image Granularity section of the Vulkan specification.",
5664825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis                    r1_linear_str, r1_type_str, range1->handle, r2_linear_str, r2_type_str, range2->handle);
566547aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski    }
5666825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    // Ranges intersect
5667825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    return true;
566847aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski}
5669623548a271287ae55415e45e3c654ee66d4e79ffTobin Ehlis// Simplified rangesIntersect that calls above function to check range1 for intersection with offset & end addresses
5670cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlisstatic bool rangesIntersect(layer_data const *dev_data, MEMORY_RANGE const *range1, VkDeviceSize offset, VkDeviceSize end) {
5671825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    // Create a local MEMORY_RANGE struct to wrap offset/size
5672825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    MEMORY_RANGE range_wrap;
5673825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    // Synch linear with range1 to avoid padding and potential validation error case
5674825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    range_wrap.linear = range1->linear;
5675825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    range_wrap.start = offset;
5676cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    range_wrap.end = end;
5677825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    bool tmp_bool;
56787dc3fbb89e2dcf3df8fc2e6639a867a959fef3f3Tobin Ehlis    return rangesIntersect(dev_data, range1, &range_wrap, &tmp_bool);
5679825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis}
5680cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis// For given mem_info, set all ranges valid that intersect [offset-end] range
5681cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis// TODO : For ranges where there is no alias, we may want to create new buffer ranges that are valid
5682cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlisstatic void SetMemRangesValid(layer_data const *dev_data, DEVICE_MEM_INFO *mem_info, VkDeviceSize offset, VkDeviceSize end) {
5683cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    bool tmp_bool = false;
5684cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    MEMORY_RANGE map_range;
5685cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    map_range.linear = true;
5686cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    map_range.start = offset;
5687cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    map_range.end = end;
5688cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    for (auto &handle_range_pair : mem_info->bound_ranges) {
56897dc3fbb89e2dcf3df8fc2e6639a867a959fef3f3Tobin Ehlis        if (rangesIntersect(dev_data, &handle_range_pair.second, &map_range, &tmp_bool)) {
5690cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis            // TODO : WARN here if tmp_bool true?
5691cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis            handle_range_pair.second.valid = true;
5692cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis        }
5693cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    }
5694cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis}
5695825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Object with given handle is being bound to memory w/ given mem_info struct.
5696825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis//  Track the newly bound memory range with given memoryOffset
5697825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis//  Also scan any previous ranges, track aliased ranges with new range, and flag an error if a linear
5698825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis//  and non-linear range incorrectly overlap.
5699825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Return true if an error is flagged and the user callback returns "true", otherwise false
5700825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// is_image indicates an image object, otherwise handle is for a buffer
5701825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// is_linear indicates a buffer or linear image
5702825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlisstatic bool InsertMemoryRange(layer_data const *dev_data, uint64_t handle, DEVICE_MEM_INFO *mem_info, VkDeviceSize memoryOffset,
5703825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis                              VkMemoryRequirements memRequirements, bool is_image, bool is_linear) {
5704825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    bool skip_call = false;
57055360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    MEMORY_RANGE range;
5706825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis
5707825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    range.image = is_image;
570847aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski    range.handle = handle;
5709825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    range.linear = is_linear;
5710f541bf53dee6daf82a4c8304354eac599a884d29Tobin Ehlis    range.valid = mem_info->global_valid;
5711825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    range.memory = mem_info->mem;
571247aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski    range.start = memoryOffset;
5713825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    range.size = memRequirements.size;
571447aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski    range.end = memoryOffset + memRequirements.size - 1;
57155360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    range.aliases.clear();
57165360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    // Update Memory aliasing
57175360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    // Save aliase ranges so we can copy into final map entry below. Can't do it in loop b/c we don't yet have final ptr. If we
57185360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    // inserted into map before loop to get the final ptr, then we may enter loop when not needed & we check range against itself
57195360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    std::unordered_set<MEMORY_RANGE *> tmp_alias_ranges;
5720825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    for (auto &obj_range_pair : mem_info->bound_ranges) {
5721825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        auto check_range = &obj_range_pair.second;
57225360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis        bool intersection_error = false;
57237dc3fbb89e2dcf3df8fc2e6639a867a959fef3f3Tobin Ehlis        if (rangesIntersect(dev_data, &range, check_range, &intersection_error)) {
5724825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis            skip_call |= intersection_error;
5725825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis            range.aliases.insert(check_range);
57265360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis            tmp_alias_ranges.insert(check_range);
5727825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        }
5728825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    }
57295360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    mem_info->bound_ranges[handle] = std::move(range);
57305360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    for (auto tmp_range : tmp_alias_ranges) {
57315360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis        tmp_range->aliases.insert(&mem_info->bound_ranges[handle]);
57325360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    }
5733825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    if (is_image)
5734825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        mem_info->bound_images.insert(handle);
5735825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    else
5736825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        mem_info->bound_buffers.insert(handle);
5737825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis
5738825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    return skip_call;
573947aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski}
574047aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski
57419f12a235bb9c014878a98ce385b68587add2538aTobin Ehlisstatic bool InsertImageMemoryRange(layer_data const *dev_data, VkImage image, DEVICE_MEM_INFO *mem_info, VkDeviceSize mem_offset,
5742825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis                                   VkMemoryRequirements mem_reqs, bool is_linear) {
57439f12a235bb9c014878a98ce385b68587add2538aTobin Ehlis    return InsertMemoryRange(dev_data, reinterpret_cast<uint64_t &>(image), mem_info, mem_offset, mem_reqs, true, is_linear);
5744825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis}
5745825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis
57469f12a235bb9c014878a98ce385b68587add2538aTobin Ehlisstatic bool InsertBufferMemoryRange(layer_data const *dev_data, VkBuffer buffer, DEVICE_MEM_INFO *mem_info, VkDeviceSize mem_offset,
5747825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis                                    VkMemoryRequirements mem_reqs) {
57489f12a235bb9c014878a98ce385b68587add2538aTobin Ehlis    return InsertMemoryRange(dev_data, reinterpret_cast<uint64_t &>(buffer), mem_info, mem_offset, mem_reqs, false, true);
5749825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis}
5750825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis
5751825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Remove MEMORY_RANGE struct for give handle from bound_ranges of mem_info
5752825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis//  is_image indicates if handle is for image or buffer
5753825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis//  This function will also remove the handle-to-index mapping from the appropriate
5754825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis//  map and clean up any aliases for range being removed.
5755825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlisstatic void RemoveMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info, bool is_image) {
5756825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    auto erase_range = &mem_info->bound_ranges[handle];
5757825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    for (auto alias_range : erase_range->aliases) {
5758825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        alias_range->aliases.erase(erase_range);
575947aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski    }
57605360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    erase_range->aliases.clear();
5761825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    mem_info->bound_ranges.erase(handle);
57621cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis    if (is_image) {
5763825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        mem_info->bound_images.erase(handle);
57641cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis    } else {
5765825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        mem_info->bound_buffers.erase(handle);
57661cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis    }
576747aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski}
576847aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski
5769825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlisstatic void RemoveBufferMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info) { RemoveMemoryRange(handle, mem_info, false); }
5770825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis
5771825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlisstatic void RemoveImageMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info) { RemoveMemoryRange(handle, mem_info, true); }
5772825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis
577389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyBuffer(VkDevice device, VkBuffer buffer,
577489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                         const VkAllocationCallbacks *pAllocator) {
57755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
5776b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
57775a758b24bbcdad37a5ccf41c3581c289acf11c2dTobin Ehlis    if (!validateIdleBuffer(dev_data, buffer)) {
5778e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis        // Clean up memory binding and range information for buffer
5779e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis        auto buff_node = getBufferNode(dev_data, buffer);
5780e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis        if (buff_node) {
5781e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis            // Any bound cmd buffers are now invalid
5782e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis            invalidateCommandBuffers(buff_node->cb_bindings,
5783e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis                                     {reinterpret_cast<uint64_t &>(buff_node->buffer), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT});
5784e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis            auto mem_info = getMemObjInfo(dev_data, buff_node->mem);
5785e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis            if (mem_info) {
5786825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis                RemoveBufferMemoryRange(reinterpret_cast<uint64_t &>(buffer), mem_info);
5787e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis            }
5788e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis            clear_object_binding(dev_data, reinterpret_cast<uint64_t &>(buffer), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT);
5789e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis            dev_data->bufferMap.erase(buff_node->buffer);
5790e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis        }
5791b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
57924a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyBuffer(device, buffer, pAllocator);
579347aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski    }
57945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
57955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
57968e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlisstatic bool PreCallValidateDestroyBufferView(layer_data *dev_data, VkBufferView buffer_view, BUFFER_VIEW_STATE **buffer_view_state,
57978e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis                                             VK_OBJECT *obj_struct) {
57987626815e3c23be98681f3fcf733ee938022af612Tobin Ehlis    if (dev_data->instance_state->disabled.destroy_buffer_view)
57997626815e3c23be98681f3fcf733ee938022af612Tobin Ehlis        return false;
58008e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis    bool skip = false;
58018e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis    *buffer_view_state = getBufferViewState(dev_data, buffer_view);
58028e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis    if (buffer_view_state) {
58038e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis        *obj_struct = {reinterpret_cast<uint64_t &>(buffer_view), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT};
58048e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis        skip |= ValidateObjectNotInUse(dev_data, *buffer_view_state, *obj_struct);
58058e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis    }
58068e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis    return skip;
58078e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis}
58088e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis
58098e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlisstatic void PostCallRecordDestroyBufferView(layer_data *dev_data, VkBufferView buffer_view, BUFFER_VIEW_STATE *buffer_view_state,
58108e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis                                            VK_OBJECT obj_struct) {
58118e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis    // Any bound cmd buffers are now invalid
58128e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis    invalidateCommandBuffers(buffer_view_state->cb_bindings, obj_struct);
5813c6f1a9ab8d9bee0a805a298c9d28f5e81f8877b5Tobin Ehlis    dev_data->bufferViewMap.erase(buffer_view);
58148e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis}
58158e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis
581689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
581789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuDestroyBufferView(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks *pAllocator) {
58185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
5819e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis    std::unique_lock<std::mutex> lock(global_lock);
58208e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis    // Common data objects use pre & post call
58218e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis    BUFFER_VIEW_STATE *buffer_view_state = nullptr;
58228e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis    VK_OBJECT obj_struct;
58238e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis    // Validate state before calling down chain, update common data if we'll be calling down chain
58248e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis    bool skip = PreCallValidateDestroyBufferView(dev_data, bufferView, &buffer_view_state, &obj_struct);
582538e26abbaa884eb48bfec4ddb4e0ae2c90634e06Tobin Ehlis    if (!skip) {
582638e26abbaa884eb48bfec4ddb4e0ae2c90634e06Tobin Ehlis        lock.unlock();
58274a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyBufferView(device, bufferView, pAllocator);
58288e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis        lock.lock();
58298e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis        // We made call so update state
58308e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis        PostCallRecordDestroyBufferView(dev_data, bufferView, buffer_view_state, obj_struct);
58315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
58325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
58335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
583489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks *pAllocator) {
58355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
5836f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis    bool skip = false;
5837e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis    std::unique_lock<std::mutex> lock(global_lock);
583899df1a43113407af9ddb0aa2322fb99d9f59e5c2Tobin Ehlis    auto img_node = getImageNode(dev_data, image);
583999df1a43113407af9ddb0aa2322fb99d9f59e5c2Tobin Ehlis    if (img_node) {
5840f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis        VK_OBJECT obj_struct = {reinterpret_cast<uint64_t &>(img_node->image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT};
584199df1a43113407af9ddb0aa2322fb99d9f59e5c2Tobin Ehlis        // Any bound cmd buffers are now invalid
5842f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis        invalidateCommandBuffers(img_node->cb_bindings, obj_struct);
5843f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis        skip |= ValidateObjectNotInUse(dev_data, img_node, obj_struct);
5844f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis    }
5845f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis    if (!skip) {
584647aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski        // Clean up memory mapping, bindings and range references for image
584799df1a43113407af9ddb0aa2322fb99d9f59e5c2Tobin Ehlis        auto mem_info = getMemObjInfo(dev_data, img_node->mem);
584857fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis        if (mem_info) {
5849825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis            RemoveImageMemoryRange(reinterpret_cast<uint64_t &>(image), mem_info);
585047aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski            clear_object_binding(dev_data, reinterpret_cast<uint64_t &>(image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT);
585147aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski        }
585258070a671b39e2058a799c7b9c932f3f03f2e66dTobin Ehlis        // Remove image from imageMap
585399df1a43113407af9ddb0aa2322fb99d9f59e5c2Tobin Ehlis        dev_data->imageMap.erase(img_node->image);
5854f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis
5855f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis        const auto &subEntry = dev_data->imageSubresourceMap.find(image);
5856f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis        if (subEntry != dev_data->imageSubresourceMap.end()) {
5857f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis            for (const auto &pair : subEntry->second) {
5858f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis                dev_data->imageLayoutMap.erase(pair);
5859f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis            }
5860f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis            dev_data->imageSubresourceMap.erase(subEntry);
58615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
5862f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis        lock.unlock();
58634a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyImage(device, image, pAllocator);
58645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
58655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
58665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
58674261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinskistatic bool ValidateMemoryTypes(const layer_data *dev_data, const DEVICE_MEM_INFO *mem_info, const uint32_t memory_type_bits,
58684261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski                                  const char *funcName) {
58694261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski    bool skip_call = false;
5870de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis    if (((1 << mem_info->alloc_info.memoryTypeIndex) & memory_type_bits) == 0) {
5871de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        skip_call = log_msg(
5872de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis            dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
5873de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis            reinterpret_cast<const uint64_t &>(mem_info->mem), __LINE__, MEMTRACK_INVALID_MEM_TYPE, "MT",
5874de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis            "%s(): MemoryRequirements->memoryTypeBits (0x%X) for this object type are not compatible with the memory "
5875de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis            "type (0x%X) of this memory object 0x%" PRIx64 ".",
5876de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis            funcName, memory_type_bits, mem_info->alloc_info.memoryTypeIndex, reinterpret_cast<const uint64_t &>(mem_info->mem));
58774261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski    }
58784261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski    return skip_call;
58794261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski}
58804261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski
588189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL
588289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuBindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memoryOffset) {
588358070a671b39e2058a799c7b9c932f3f03f2e66dTobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
58845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
5885b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
58865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Track objects tied to memory
58879f12a235bb9c014878a98ce385b68587add2538aTobin Ehlis    uint64_t buffer_handle = reinterpret_cast<uint64_t &>(buffer);
5888888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis    bool skip_call = SetMemBinding(dev_data, mem, buffer_handle, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, "vkBindBufferMemory");
58898718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis    auto buffer_node = getBufferNode(dev_data, buffer);
58908718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis    if (buffer_node) {
58915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        VkMemoryRequirements memRequirements;
58924a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.GetBufferMemoryRequirements(device, buffer, &memRequirements);
58934bf66272b011176416dd42e726decd70d5a02fa2Chris Forbes        buffer_node->mem = mem;
58944bf66272b011176416dd42e726decd70d5a02fa2Chris Forbes        buffer_node->memOffset = memoryOffset;
58954bf66272b011176416dd42e726decd70d5a02fa2Chris Forbes        buffer_node->memSize = memRequirements.size;
589647aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski
589747aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski        // Track and validate bound memory range information
589857fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis        auto mem_info = getMemObjInfo(dev_data, mem);
589957fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis        if (mem_info) {
59009f12a235bb9c014878a98ce385b68587add2538aTobin Ehlis            skip_call |= InsertBufferMemoryRange(dev_data, buffer, mem_info, memoryOffset, memRequirements);
590183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= ValidateMemoryTypes(dev_data, mem_info, memRequirements.memoryTypeBits, "BindBufferMemory");
590247aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski        }
590347aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski
59042c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves        // Validate memory requirements alignment
59052c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves        if (vk_safe_modulo(memoryOffset, memRequirements.alignment) != 0) {
590683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |=
59072c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0,
59082c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves                        __LINE__, DRAWSTATE_INVALID_BUFFER_MEMORY_OFFSET, "DS",
5909414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        "vkBindBufferMemory(): memoryOffset is 0x%" PRIxLEAST64 " but must be an integer multiple of the "
5910414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        "VkMemoryRequirements::alignment value 0x%" PRIxLEAST64
59112c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves                        ", returned from a call to vkGetBufferMemoryRequirements with buffer",
59122c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves                        memoryOffset, memRequirements.alignment);
59132c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves        }
5914ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller
59152c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves        // Validate device limits alignments
5916ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        static const VkBufferUsageFlagBits usage_list[3] = {
5917ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller            static_cast<VkBufferUsageFlagBits>(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT),
5918ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller            VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
5919ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller            VK_BUFFER_USAGE_STORAGE_BUFFER_BIT};
5920ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        static const char *memory_type[3] = {"texel",
5921ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller                                             "uniform",
5922ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller                                             "storage"};
5923ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        static const char *offset_name[3] = {
5924ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller            "minTexelBufferOffsetAlignment",
5925ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller            "minUniformBufferOffsetAlignment",
5926ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller            "minStorageBufferOffsetAlignment"
5927ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        };
5928ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller
5929ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        // Keep this one fresh!
5930ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        const VkDeviceSize offset_requirement[3] = {
5931ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller            dev_data->phys_dev_properties.properties.limits.minTexelBufferOffsetAlignment,
5932ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller            dev_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment,
5933ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller            dev_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment
5934ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        };
59358718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis        VkBufferUsageFlags usage = dev_data->bufferMap[buffer].get()->createInfo.usage;
5936ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller
5937ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        for (int i = 0; i < 3; i++) {
5938ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller            if (usage & usage_list[i]) {
5939ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller                if (vk_safe_modulo(memoryOffset, offset_requirement[i]) != 0) {
5940ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller                    skip_call |=
5941ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller                        log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
5942ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller                                0, __LINE__, DRAWSTATE_INVALID_TEXEL_BUFFER_OFFSET, "DS",
5943ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller                                "vkBindBufferMemory(): %s memoryOffset is 0x%" PRIxLEAST64 " but must be a multiple of "
5944ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller                                "device limit %s 0x%" PRIxLEAST64,
5945ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller                                memory_type[i], memoryOffset, offset_name[i], offset_requirement[i]);
5946ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller                }
59472c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves            }
59482c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves        }
59495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
59500a1ce3dfd81c9f4efbe46f5ba5ddaea70bc4aa61Chris Forbes    print_mem_list(dev_data);
5951b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
595283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call) {
59534a0754042cf090e131e9e769d8a3633c228625beChris Forbes        result = dev_data->dispatch_table.BindBufferMemory(device, buffer, mem, memoryOffset);
59545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
59555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
59565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
59575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
595889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
595989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuGetBufferMemoryRequirements(VkDevice device, VkBuffer buffer, VkMemoryRequirements *pMemoryRequirements) {
59605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
59615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TODO : What to track here?
59625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    //   Could potentially save returned mem requirements and validate values passed into BindBufferMemory
59634a0754042cf090e131e9e769d8a3633c228625beChris Forbes    my_data->dispatch_table.GetBufferMemoryRequirements(device, buffer, pMemoryRequirements);
59645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
59655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
596689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
596789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuGetImageMemoryRequirements(VkDevice device, VkImage image, VkMemoryRequirements *pMemoryRequirements) {
59685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
59695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TODO : What to track here?
59705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    //   Could potentially save returned mem requirements and validate values passed into BindImageMemory
59714a0754042cf090e131e9e769d8a3633c228625beChris Forbes    my_data->dispatch_table.GetImageMemoryRequirements(device, image, pMemoryRequirements);
59725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
5973593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
597489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
597589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuDestroyImageView(VkDevice device, VkImageView imageView, const VkAllocationCallbacks *pAllocator) {
5976d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
5977d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis    bool skip = false;
5978d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis    std::unique_lock<std::mutex> lock(global_lock);
5979d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis    auto view_state = getImageViewState(dev_data, imageView);
5980d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis    if (view_state) {
5981d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis        VK_OBJECT obj_struct = {reinterpret_cast<uint64_t &>(imageView), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT};
5982d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis        skip |= ValidateObjectNotInUse(dev_data, view_state, obj_struct);
5983d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis        // Any bound cmd buffers are now invalid
5984d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis        invalidateCommandBuffers(view_state->cb_bindings, obj_struct);
5985d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis    }
5986d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis    if (!skip) {
5987d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis        dev_data->imageViewMap.erase(imageView);
5988d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis        lock.unlock();
59894a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyImageView(device, imageView, pAllocator);
5990d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis    }
59915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
59925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
599389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
599489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuDestroyShaderModule(VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks *pAllocator) {
5995918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
5996918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes
5997b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
5998918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes    my_data->shaderModuleMap.erase(shaderModule);
5999b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
6000918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes
60014a0754042cf090e131e9e769d8a3633c228625beChris Forbes    my_data->dispatch_table.DestroyShaderModule(device, shaderModule, pAllocator);
60025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
60035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
600489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
600589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) {
6006a86b57cf1145ee63d5997547ac0f9847933fc3b6Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
6007eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis    bool skip = false;
6008e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis    std::unique_lock<std::mutex> lock(global_lock);
6009a86b57cf1145ee63d5997547ac0f9847933fc3b6Tobin Ehlis    auto pipe_node = getPipeline(dev_data, pipeline);
6010a86b57cf1145ee63d5997547ac0f9847933fc3b6Tobin Ehlis    if (pipe_node) {
6011eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis        VK_OBJECT obj_struct = {reinterpret_cast<uint64_t &>(pipeline), VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT};
6012eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis        skip |= ValidateObjectNotInUse(dev_data, pipe_node, obj_struct);
6013a86b57cf1145ee63d5997547ac0f9847933fc3b6Tobin Ehlis        // Any bound cmd buffers are now invalid
6014eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis        invalidateCommandBuffers(pipe_node->cb_bindings, obj_struct);
6015a86b57cf1145ee63d5997547ac0f9847933fc3b6Tobin Ehlis    }
6016f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis    if (!skip) {
6017f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis        dev_data->pipelineMap.erase(pipeline);
6018f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis        lock.unlock();
60194a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyPipeline(device, pipeline, pAllocator);
6020f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis    }
60215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
60225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
602389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
602489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuDestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks *pAllocator) {
60256792ea7cc0ce5fa64b7bd6c946460608cbda91c7Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
6026e28cddb35c63274c13873b9a7060ad43b255c6f1Tobin Ehlis    std::unique_lock<std::mutex> lock(global_lock);
60276792ea7cc0ce5fa64b7bd6c946460608cbda91c7Tobin Ehlis    dev_data->pipelineLayoutMap.erase(pipelineLayout);
6028e28cddb35c63274c13873b9a7060ad43b255c6f1Tobin Ehlis    lock.unlock();
6029e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis
60304a0754042cf090e131e9e769d8a3633c228625beChris Forbes    dev_data->dispatch_table.DestroyPipelineLayout(device, pipelineLayout, pAllocator);
60315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
60325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
603389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
603489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuDestroySampler(VkDevice device, VkSampler sampler, const VkAllocationCallbacks *pAllocator) {
603556f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
6036eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis    bool skip = false;
603756f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis    std::unique_lock<std::mutex> lock(global_lock);
603856f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis    auto sampler_node = getSamplerNode(dev_data, sampler);
603956f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis    if (sampler_node) {
6040eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis        VK_OBJECT obj_struct = {reinterpret_cast<uint64_t &>(sampler), VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT};
6041eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis        skip |= ValidateObjectNotInUse(dev_data, sampler_node, obj_struct);
604256f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis        // Any bound cmd buffers are now invalid
6043eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis        invalidateCommandBuffers(sampler_node->cb_bindings, obj_struct);
604456f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis    }
6045f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis    if (!skip) {
6046f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis        dev_data->samplerMap.erase(sampler);
6047f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis        lock.unlock();
60484a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroySampler(device, sampler, pAllocator);
6049f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis    }
60505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
60515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
605289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
605389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuDestroyDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks *pAllocator) {
6054e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis    // TODO : Clean up any internal data structures using this obj.
60555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    get_my_data_ptr(get_dispatch_key(device), layer_data_map)
60564a0754042cf090e131e9e769d8a3633c228625beChris Forbes        ->dispatch_table.DestroyDescriptorSetLayout(device, descriptorSetLayout, pAllocator);
60575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
60585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
605989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
606089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuDestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks *pAllocator) {
60611c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis    // TODO : Add checks for VALIDATION_ERROR_00901
6062e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis    // TODO : Clean up any internal data structures using this obj.
60635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    get_my_data_ptr(get_dispatch_key(device), layer_data_map)
60644a0754042cf090e131e9e769d8a3633c228625beChris Forbes        ->dispatch_table.DestroyDescriptorPool(device, descriptorPool, pAllocator);
60655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
6066bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// Verify cmdBuffer in given cb_node is not in global in-flight set, and return skip_call result
6067bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis//  If this is a secondary command buffer, then make sure its primary is also in-flight
6068bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis//  If primary is not in-flight, then remove secondary from global in-flight set
6069bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// This function is only valid at a point when cmdBuffer is being reset or freed
6070a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbesstatic bool checkCommandBufferInFlight(layer_data *dev_data, const GLOBAL_CB_NODE *cb_node, const char *action) {
6071bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis    bool skip_call = false;
6072bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis    if (dev_data->globalInFlightCmdBuffers.count(cb_node->commandBuffer)) {
6073bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis        // Primary CB or secondary where primary is also in-flight is an error
6074bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis        if ((cb_node->createInfo.level != VK_COMMAND_BUFFER_LEVEL_SECONDARY) ||
6075bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis            (dev_data->globalInFlightCmdBuffers.count(cb_node->primaryCommandBuffer))) {
6076bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis            skip_call |= log_msg(
6077bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis                dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
6078bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis                reinterpret_cast<const uint64_t &>(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER_RESET, "DS",
6079414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                "Attempt to %s command buffer (0x%" PRIxLEAST64 ") which is in use.", action,
6080bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis                reinterpret_cast<const uint64_t &>(cb_node->commandBuffer));
6081bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis        }
6082bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis    }
6083bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis    return skip_call;
6084bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis}
6085a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes
6086bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// Iterate over all cmdBuffers in given commandPool and verify that each is not in use
6087a01b5eb150981aad061238e64b173d0da8c11140Chris Forbesstatic bool checkCommandBuffersInFlight(layer_data *dev_data, COMMAND_POOL_NODE *pPool, const char *action) {
6088bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis    bool skip_call = false;
6089a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes    for (auto cmd_buffer : pPool->commandBuffers) {
6090a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes        if (dev_data->globalInFlightCmdBuffers.count(cmd_buffer)) {
6091a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes            skip_call |= checkCommandBufferInFlight(dev_data, getCBNode(dev_data, cmd_buffer), action);
6092bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis        }
6093bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis    }
6094bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis    return skip_call;
6095bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis}
60965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6097a01b5eb150981aad061238e64b173d0da8c11140Chris Forbesstatic void clearCommandBuffersInFlight(layer_data *dev_data, COMMAND_POOL_NODE *pPool) {
6098a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes    for (auto cmd_buffer : pPool->commandBuffers) {
6099a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes        dev_data->globalInFlightCmdBuffers.erase(cmd_buffer);
6100a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes    }
6101a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes}
6102a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes
610389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
610489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuFreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers) {
61055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
61065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    bool skip_call = false;
6107b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
6108c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes
61095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < commandBufferCount; i++) {
61109f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        auto cb_node = getCBNode(dev_data, pCommandBuffers[i]);
61115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Delete CB information structure, and remove from commandBufferMap
61129f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        if (cb_node) {
61139f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis            skip_call |= checkCommandBufferInFlight(dev_data, cb_node, "free");
6114c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes        }
6115c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes    }
6116c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes
6117c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes    if (skip_call)
6118c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes        return;
6119c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes
6120c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes    auto pPool = getCommandPoolNode(dev_data, commandPool);
6121c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes    for (uint32_t i = 0; i < commandBufferCount; i++) {
61229f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        auto cb_node = getCBNode(dev_data, pCommandBuffers[i]);
6123c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes        // Delete CB information structure, and remove from commandBufferMap
61249f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        if (cb_node) {
61259f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis            dev_data->globalInFlightCmdBuffers.erase(cb_node->commandBuffer);
61265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // reset prior to delete for data clean-up
61279f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis            resetCB(dev_data, cb_node->commandBuffer);
61289f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis            dev_data->commandBufferMap.erase(cb_node->commandBuffer);
61299f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis            delete cb_node;
61305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
61315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
61325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Remove commandBuffer reference from commandPoolMap
6133c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes        pPool->commandBuffers.remove(pCommandBuffers[i]);
61345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
61350a1ce3dfd81c9f4efbe46f5ba5ddaea70bc4aa61Chris Forbes    printCBList(dev_data);
6136b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
6137e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis
61384a0754042cf090e131e9e769d8a3633c228625beChris Forbes    dev_data->dispatch_table.FreeCommandBuffers(device, commandPool, commandBufferCount, pCommandBuffers);
61395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
61405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
614189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo,
614289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                 const VkAllocationCallbacks *pAllocator,
614389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                 VkCommandPool *pCommandPool) {
61445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
61455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
61464a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateCommandPool(device, pCreateInfo, pAllocator, pCommandPool);
61475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
61485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
6149b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        std::lock_guard<std::mutex> lock(global_lock);
61505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        dev_data->commandPoolMap[*pCommandPool].createFlags = pCreateInfo->flags;
61515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        dev_data->commandPoolMap[*pCommandPool].queueFamilyIndex = pCreateInfo->queueFamilyIndex;
61525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
61535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
61545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
61555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
615689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo *pCreateInfo,
615789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                               const VkAllocationCallbacks *pAllocator, VkQueryPool *pQueryPool) {
61585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
61595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
61604a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateQueryPool(device, pCreateInfo, pAllocator, pQueryPool);
61615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (result == VK_SUCCESS) {
6162b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        std::lock_guard<std::mutex> lock(global_lock);
6163eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis        QUERY_POOL_NODE *qp_node = &dev_data->queryPoolMap[*pQueryPool];
6164eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis        qp_node->createInfo = *pCreateInfo;
61655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
61665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
61675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
61685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
61695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Destroy commandPool along with all of the commandBuffers allocated from that pool
617089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
617189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuDestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks *pAllocator) {
61725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
617383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
6174b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
61755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Verify that command buffers in pool are complete (not in-flight)
6176a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes    auto pPool = getCommandPoolNode(dev_data, commandPool);
617783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    skip_call |= checkCommandBuffersInFlight(dev_data, pPool, "destroy command pool with");
61785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
617983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (skip_call)
61805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return;
61819f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis    // Must remove cmdpool from cmdpoolmap, after removing all cmdbuffers in its list from the commandBufferMap
6182a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes    clearCommandBuffersInFlight(dev_data, pPool);
6183a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes    for (auto cb : pPool->commandBuffers) {
6184a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes        clear_cmd_buf_and_mem_references(dev_data, cb);
61859f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        auto cb_node = getCBNode(dev_data, cb);
6186d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis        // Remove references to this cb_node prior to delete
6187d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis        // TODO : Need better solution here, resetCB?
61887165385f3a39f1f951f3a6a9a06ed2cce4642b6dMark Lobodzinski        for (auto obj : cb_node->object_bindings) {
61897165385f3a39f1f951f3a6a9a06ed2cce4642b6dMark Lobodzinski            removeCommandBufferBinding(dev_data, &obj, cb_node);
61907165385f3a39f1f951f3a6a9a06ed2cce4642b6dMark Lobodzinski        }
6191d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis        for (auto framebuffer : cb_node->framebuffers) {
6192d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis            auto fb_node = getFramebuffer(dev_data, framebuffer);
6193d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis            if (fb_node)
6194d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis                fb_node->cb_bindings.erase(cb_node);
6195d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis        }
61969f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        dev_data->commandBufferMap.erase(cb); // Remove this command buffer
61979f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        delete cb_node;                       // delete CB info structure
6198a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes    }
6199a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes    dev_data->commandPoolMap.erase(commandPool);
6200a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes    lock.unlock();
6201e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis
62024a0754042cf090e131e9e769d8a3633c228625beChris Forbes    dev_data->dispatch_table.DestroyCommandPool(device, commandPool, pAllocator);
62035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
62045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
620589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL
620689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuResetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags) {
62075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
620883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
6209400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis
62101ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes    std::unique_lock<std::mutex> lock(global_lock);
6211a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes    auto pPool = getCommandPoolNode(dev_data, commandPool);
621283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    skip_call |= checkCommandBuffersInFlight(dev_data, pPool, "reset command pool with");
62131ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes    lock.unlock();
6214a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes
621583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (skip_call)
62165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return VK_ERROR_VALIDATION_FAILED_EXT;
62175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
62184a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.ResetCommandPool(device, commandPool, flags);
62195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
62205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Reset all of the CBs allocated from this pool
62215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
62221ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes        lock.lock();
6223a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes        clearCommandBuffersInFlight(dev_data, pPool);
6224a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes        for (auto cmdBuffer : pPool->commandBuffers) {
6225a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes            resetCB(dev_data, cmdBuffer);
62265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
62271ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes        lock.unlock();
62285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
62295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
62305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
62315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
623289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL ResetFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences) {
62335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
623483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
6235b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
62365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < fenceCount; ++i) {
6237df1846b33487b02061c0ff42d768588a9abeb6c7Chris Forbes        auto pFence = getFenceNode(dev_data, pFences[i]);
6238090da73358f71ba026e2474a822fecf55267d166Chris Forbes        if (pFence && pFence->state == FENCE_INFLIGHT) {
623983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT,
624083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 reinterpret_cast<const uint64_t &>(pFences[i]), __LINE__, DRAWSTATE_INVALID_FENCE, "DS",
624183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 "Fence 0x%" PRIx64 " is in use.", reinterpret_cast<const uint64_t &>(pFences[i]));
62425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
62435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
6244b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
6245090da73358f71ba026e2474a822fecf55267d166Chris Forbes
624683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (skip_call)
6247090da73358f71ba026e2474a822fecf55267d166Chris Forbes        return VK_ERROR_VALIDATION_FAILED_EXT;
6248090da73358f71ba026e2474a822fecf55267d166Chris Forbes
62494a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.ResetFences(device, fenceCount, pFences);
6250090da73358f71ba026e2474a822fecf55267d166Chris Forbes
6251090da73358f71ba026e2474a822fecf55267d166Chris Forbes    if (result == VK_SUCCESS) {
6252090da73358f71ba026e2474a822fecf55267d166Chris Forbes        lock.lock();
6253090da73358f71ba026e2474a822fecf55267d166Chris Forbes        for (uint32_t i = 0; i < fenceCount; ++i) {
6254090da73358f71ba026e2474a822fecf55267d166Chris Forbes            auto pFence = getFenceNode(dev_data, pFences[i]);
6255090da73358f71ba026e2474a822fecf55267d166Chris Forbes            if (pFence) {
6256090da73358f71ba026e2474a822fecf55267d166Chris Forbes                pFence->state = FENCE_UNSIGNALED;
6257090da73358f71ba026e2474a822fecf55267d166Chris Forbes            }
6258090da73358f71ba026e2474a822fecf55267d166Chris Forbes        }
6259090da73358f71ba026e2474a822fecf55267d166Chris Forbes        lock.unlock();
6260090da73358f71ba026e2474a822fecf55267d166Chris Forbes    }
6261090da73358f71ba026e2474a822fecf55267d166Chris Forbes
62625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
62635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
62645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6265e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis// For given cb_nodes, invalidate them and track object causing invalidation
6266e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlisvoid invalidateCommandBuffers(std::unordered_set<GLOBAL_CB_NODE *> cb_nodes, VK_OBJECT obj) {
6267e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis    for (auto cb_node : cb_nodes) {
6268e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis        cb_node->state = CB_INVALID;
6269e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis        cb_node->broken_bindings.push_back(obj);
6270e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis    }
6271e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis}
6272e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis
627389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
627489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuDestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks *pAllocator) {
62755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
6276b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
6277d9369e5a41f95b7bd1670240d441dbed58bc36fbTobin Ehlis    auto fb_node = getFramebuffer(dev_data, framebuffer);
6278d9369e5a41f95b7bd1670240d441dbed58bc36fbTobin Ehlis    if (fb_node) {
6279e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis        invalidateCommandBuffers(fb_node->cb_bindings,
6280e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis                                 {reinterpret_cast<uint64_t &>(fb_node->framebuffer), VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT});
6281d9369e5a41f95b7bd1670240d441dbed58bc36fbTobin Ehlis        dev_data->frameBufferMap.erase(fb_node->framebuffer);
62825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
6283b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
62844a0754042cf090e131e9e769d8a3633c228625beChris Forbes    dev_data->dispatch_table.DestroyFramebuffer(device, framebuffer, pAllocator);
62855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
62865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
628789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
628889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuDestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks *pAllocator) {
62895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
6290a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis    bool skip = false;
6291e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis    std::unique_lock<std::mutex> lock(global_lock);
6292a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis    auto rp_state = getRenderPass(dev_data, renderPass);
6293a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis    if (rp_state) {
6294a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis        VK_OBJECT obj_struct = {reinterpret_cast<uint64_t &>(renderPass), VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT};
6295a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis        skip |= ValidateObjectNotInUse(dev_data, rp_state, obj_struct);
6296a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis        // Any bound cmd buffers are now invalid
6297a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis        invalidateCommandBuffers(rp_state->cb_bindings, obj_struct);
6298a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis    }
6299a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis    if (!skip) {
6300a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis        dev_data->renderPassMap.erase(renderPass);
6301a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis        lock.unlock();
63024a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyRenderPass(device, renderPass, pAllocator);
6303a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis    }
63045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
63055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
630689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo,
630789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                            const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) {
63085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
630947892024546c67e8db98b51b2ddb962c21088894Mark Lobodzinski
63104a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateBuffer(device, pCreateInfo, pAllocator, pBuffer);
63115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
63125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
6313b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        std::lock_guard<std::mutex> lock(global_lock);
63145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // TODO : This doesn't create deep copy of pQueueFamilyIndices so need to fix that if/when we want that data to be valid
6315b5e51047540e12567fbf674b23fe75ca86ca0371Tobin Ehlis        dev_data->bufferMap.insert(std::make_pair(*pBuffer, unique_ptr<BUFFER_NODE>(new BUFFER_NODE(*pBuffer, pCreateInfo))));
63165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
63175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
63185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
63195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
63208c07a094dc9cc4afb6b62181f341c12b9e969041Mark Youngstatic bool PreCallValidateCreateBufferView(layer_data *dev_data, const VkBufferViewCreateInfo *pCreateInfo) {
63218c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young    bool skip_call = false;
63228c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young    BUFFER_NODE *buf_node = getBufferNode(dev_data, pCreateInfo->buffer);
63238c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young    // If this isn't a sparse buffer, it needs to have memory backing it at CreateBufferView time
6324b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski    if (buf_node) {
6325b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, buf_node, "vkCreateBufferView()");
6326cf64d39a58d4903515232a17eea47ff3ed82faadTobin Ehlis        // In order to create a valid buffer view, the buffer must have been created with at least one of the
6327cf64d39a58d4903515232a17eea47ff3ed82faadTobin Ehlis        // following flags:  UNIFORM_TEXEL_BUFFER_BIT or STORAGE_TEXEL_BUFFER_BIT
632859b0561b0bd298885f90b9f524c0583cd8ee6f61Tobin Ehlis        skip_call |= ValidateBufferUsageFlags(dev_data, buf_node,
6329b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski                                              VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
6330b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski                                              false, "vkCreateBufferView()", "VK_BUFFER_USAGE_[STORAGE|UNIFORM]_TEXEL_BUFFER_BIT");
6331b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski    }
63328c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young    return skip_call;
63338c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young}
63348c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young
633589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateBufferView(VkDevice device, const VkBufferViewCreateInfo *pCreateInfo,
633689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                const VkAllocationCallbacks *pAllocator, VkBufferView *pView) {
63375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
63388c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young    std::unique_lock<std::mutex> lock(global_lock);
63398c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young    bool skip_call = PreCallValidateCreateBufferView(dev_data, pCreateInfo);
63408c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young    lock.unlock();
63418c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young    if (skip_call)
63428c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young        return VK_ERROR_VALIDATION_FAILED_EXT;
63434a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateBufferView(device, pCreateInfo, pAllocator, pView);
63445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
63458c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young        lock.lock();
634639267c0c27b8f032f05a6747eb02d4508247fdc1Tobin Ehlis        dev_data->bufferViewMap[*pView] = unique_ptr<BUFFER_VIEW_STATE>(new BUFFER_VIEW_STATE(*pView, pCreateInfo));
63478c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young        lock.unlock();
63485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
63495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
63505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
63515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
635289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,
635389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                           const VkAllocationCallbacks *pAllocator, VkImage *pImage) {
63545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
635547892024546c67e8db98b51b2ddb962c21088894Mark Lobodzinski
63564a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateImage(device, pCreateInfo, pAllocator, pImage);
63575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
63585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
6359b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        std::lock_guard<std::mutex> lock(global_lock);
63605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        IMAGE_LAYOUT_NODE image_node;
63615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        image_node.layout = pCreateInfo->initialLayout;
63625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        image_node.format = pCreateInfo->format;
636329e9a148072b1015633a102470f0cf706a9e2e55Tobin Ehlis        dev_data->imageMap.insert(std::make_pair(*pImage, unique_ptr<IMAGE_NODE>(new IMAGE_NODE(*pImage, pCreateInfo))));
63645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        ImageSubresourcePair subpair = {*pImage, false, VkImageSubresource()};
63655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        dev_data->imageSubresourceMap[*pImage].push_back(subpair);
63665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        dev_data->imageLayoutMap[subpair] = image_node;
63675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
63685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
63695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
63705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
63715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic void ResolveRemainingLevelsLayers(layer_data *dev_data, VkImageSubresourceRange *range, VkImage image) {
6372b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    /* expects global_lock to be held by caller */
63735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
63746d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis    auto image_node = getImageNode(dev_data, image);
63756d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis    if (image_node) {
63765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        /* If the caller used the special values VK_REMAINING_MIP_LEVELS and
63775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis         * VK_REMAINING_ARRAY_LAYERS, resolve them now in our internal state to
63785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis         * the actual values.
63795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis         */
63805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (range->levelCount == VK_REMAINING_MIP_LEVELS) {
63816d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            range->levelCount = image_node->createInfo.mipLevels - range->baseMipLevel;
63825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
63835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
63845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (range->layerCount == VK_REMAINING_ARRAY_LAYERS) {
63856d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            range->layerCount = image_node->createInfo.arrayLayers - range->baseArrayLayer;
63865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
63875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
63885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
63895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
63905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Return the correct layer/level counts if the caller used the special
63915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// values VK_REMAINING_MIP_LEVELS or VK_REMAINING_ARRAY_LAYERS.
63925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic void ResolveRemainingLevelsLayers(layer_data *dev_data, uint32_t *levels, uint32_t *layers, VkImageSubresourceRange range,
63935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                         VkImage image) {
6394b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    /* expects global_lock to be held by caller */
63955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
63965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    *levels = range.levelCount;
63975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    *layers = range.layerCount;
63986d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis    auto image_node = getImageNode(dev_data, image);
63996d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis    if (image_node) {
64005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (range.levelCount == VK_REMAINING_MIP_LEVELS) {
64016d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            *levels = image_node->createInfo.mipLevels - range.baseMipLevel;
64025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
64035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (range.layerCount == VK_REMAINING_ARRAY_LAYERS) {
64046d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            *layers = image_node->createInfo.arrayLayers - range.baseArrayLayer;
64055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
64065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
64075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
64085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
64098c07a094dc9cc4afb6b62181f341c12b9e969041Mark Youngstatic bool PreCallValidateCreateImageView(layer_data *dev_data, const VkImageViewCreateInfo *pCreateInfo) {
64108c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young    bool skip_call = false;
64118c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young    IMAGE_NODE *image_node = getImageNode(dev_data, pCreateInfo->image);
6412b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski    if (image_node) {
64135a8cba534d14ce341ba7a2100a542e93f0e3033cTony Barbour        skip_call |= ValidateImageUsageFlags(
64145a8cba534d14ce341ba7a2100a542e93f0e3033cTony Barbour            dev_data, image_node, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
64155a8cba534d14ce341ba7a2100a542e93f0e3033cTony Barbour                                      VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
64165a8cba534d14ce341ba7a2100a542e93f0e3033cTony Barbour            false, "vkCreateImageView()",
64175a8cba534d14ce341ba7a2100a542e93f0e3033cTony Barbour            "VK_IMAGE_USAGE_[SAMPLED|STORAGE|COLOR_ATTACHMENT|DEPTH_STENCIL_ATTACHMENT|INPUT_ATTACHMENT]_BIT");
6418b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        // If this isn't a sparse image, it needs to have memory backing it at CreateImageView time
6419b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= ValidateMemoryIsBoundToImage(dev_data, image_node, "vkCreateImageView()");
6420bb6624cb996175d8945190886a200e720b3871efChris Forbes    }
64218c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young    return skip_call;
64228c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young}
6423bb6624cb996175d8945190886a200e720b3871efChris Forbes
642479fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlisstatic inline void PostCallRecordCreateImageView(layer_data *dev_data, const VkImageViewCreateInfo *pCreateInfo, VkImageView view) {
642579fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis    dev_data->imageViewMap[view] = unique_ptr<IMAGE_VIEW_STATE>(new IMAGE_VIEW_STATE(view, pCreateInfo));
642679fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis    ResolveRemainingLevelsLayers(dev_data, &dev_data->imageViewMap[view].get()->create_info.subresourceRange, pCreateInfo->image);
64278c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young}
6428bb6624cb996175d8945190886a200e720b3871efChris Forbes
64298c07a094dc9cc4afb6b62181f341c12b9e969041Mark YoungVKAPI_ATTR VkResult VKAPI_CALL CreateImageView(VkDevice device, const VkImageViewCreateInfo *pCreateInfo,
64308c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young                                               const VkAllocationCallbacks *pAllocator, VkImageView *pView) {
64318c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
64328c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young    std::unique_lock<std::mutex> lock(global_lock);
64338c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young    bool skip_call = PreCallValidateCreateImageView(dev_data, pCreateInfo);
64348c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young    lock.unlock();
64358c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young    if (skip_call)
64368c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young        return VK_ERROR_VALIDATION_FAILED_EXT;
64374a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateImageView(device, pCreateInfo, pAllocator, pView);
64385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
64398c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young        lock.lock();
644079fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis        PostCallRecordCreateImageView(dev_data, pCreateInfo, *pView);
64418c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young        lock.unlock();
64425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
6443bb6624cb996175d8945190886a200e720b3871efChris Forbes
64445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
64455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
64465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
644789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL
644889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCreateFence(VkDevice device, const VkFenceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkFence *pFence) {
64495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
64504a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateFence(device, pCreateInfo, pAllocator, pFence);
64515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
6452b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        std::lock_guard<std::mutex> lock(global_lock);
6453a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis        auto &fence_node = dev_data->fenceMap[*pFence];
64548988ad37ea5a054ff2ae3cbe4b767ae6c13cf48bChris Forbes        fence_node.fence = *pFence;
6455a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis        fence_node.createInfo = *pCreateInfo;
6456cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes        fence_node.state = (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT) ? FENCE_RETIRED : FENCE_UNSIGNALED;
64575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
64585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
64595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
64605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
64615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// TODO handle pipeline caches
646289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreatePipelineCache(VkDevice device, const VkPipelineCacheCreateInfo *pCreateInfo,
646389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                   const VkAllocationCallbacks *pAllocator, VkPipelineCache *pPipelineCache) {
64645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
64654a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreatePipelineCache(device, pCreateInfo, pAllocator, pPipelineCache);
64665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
64675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
64685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
64695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin EhlisVKAPI_ATTR void VKAPI_CALL
647089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuDestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache, const VkAllocationCallbacks *pAllocator) {
64715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
64724a0754042cf090e131e9e769d8a3633c228625beChris Forbes    dev_data->dispatch_table.DestroyPipelineCache(device, pipelineCache, pAllocator);
64735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
64745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
64755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin EhlisVKAPI_ATTR VkResult VKAPI_CALL
647689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuGetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache, size_t *pDataSize, void *pData) {
64775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
64784a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.GetPipelineCacheData(device, pipelineCache, pDataSize, pData);
64795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
64805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
64815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
64825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin EhlisVKAPI_ATTR VkResult VKAPI_CALL
648389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuMergePipelineCaches(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, const VkPipelineCache *pSrcCaches) {
64845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
64854a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.MergePipelineCaches(device, dstCache, srcCacheCount, pSrcCaches);
64865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
64875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
64885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
64893d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis// utility function to set collective state for pipeline
64903d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlisvoid set_pipeline_state(PIPELINE_NODE *pPipe) {
64913d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    // If any attachment used by this pipeline has blendEnable, set top-level blendEnable
64923d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    if (pPipe->graphicsPipelineCI.pColorBlendState) {
64933d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        for (size_t i = 0; i < pPipe->attachments.size(); ++i) {
64943d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis            if (VK_TRUE == pPipe->attachments[i].blendEnable) {
64953d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                if (((pPipe->attachments[i].dstAlphaBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) &&
64963d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                     (pPipe->attachments[i].dstAlphaBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) ||
64973d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                    ((pPipe->attachments[i].dstColorBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) &&
64983d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                     (pPipe->attachments[i].dstColorBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) ||
64993d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                    ((pPipe->attachments[i].srcAlphaBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) &&
65003d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                     (pPipe->attachments[i].srcAlphaBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) ||
65013d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                    ((pPipe->attachments[i].srcColorBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) &&
65023d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                     (pPipe->attachments[i].srcColorBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA))) {
65033d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                    pPipe->blendConstantsEnabled = true;
65043d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                }
65053d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis            }
65063d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        }
65073d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    }
65083d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis}
65093d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis
651089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL
651189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
651289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                        const VkGraphicsPipelineCreateInfo *pCreateInfos, const VkAllocationCallbacks *pAllocator,
651389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                        VkPipeline *pPipelines) {
65145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkResult result = VK_SUCCESS;
65155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TODO What to do with pipelineCache?
65165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // The order of operations here is a little convoluted but gets the job done
65175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    //  1. Pipeline create state is first shadowed into PIPELINE_NODE struct
65185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    //  2. Create state is then validated (which uses flags setup during shadowing)
65195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    //  3. If everything looks good, we'll then create the pipeline and add NODE to pipelineMap
652083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
65215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TODO : Improve this data struct w/ unique_ptrs so cleanup below is automatic
65225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    vector<PIPELINE_NODE *> pPipeNode(count);
65235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
65245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
65255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t i = 0;
6526b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
65275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
65285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (i = 0; i < count; i++) {
6529ca546210846c65808717f8875deae39bd227c240Tobin Ehlis        pPipeNode[i] = new PIPELINE_NODE;
6530ca546210846c65808717f8875deae39bd227c240Tobin Ehlis        pPipeNode[i]->initGraphicsPipeline(&pCreateInfos[i]);
6531fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes        pPipeNode[i]->render_pass_ci.initialize(getRenderPass(dev_data, pCreateInfos[i].renderPass)->createInfo.ptr());
6532c8268861aaa8f9c47920065d6323e4609e5081b0Tobin Ehlis        pPipeNode[i]->pipeline_layout = *getPipelineLayout(dev_data, pCreateInfos[i].layout);
653367220c96300606b517394e25c7aa144dd4601bb6Chris Forbes
653483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= verifyPipelineCreateState(dev_data, device, pPipeNode, i);
65355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
65365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
653783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call) {
6538b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
65394a0754042cf090e131e9e769d8a3633c228625beChris Forbes        result =
65404a0754042cf090e131e9e769d8a3633c228625beChris Forbes            dev_data->dispatch_table.CreateGraphicsPipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines);
6541b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.lock();
65425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (i = 0; i < count; i++) {
65435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            pPipeNode[i]->pipeline = pPipelines[i];
65445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            dev_data->pipelineMap[pPipeNode[i]->pipeline] = pPipeNode[i];
65455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
6546b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
65475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
65485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (i = 0; i < count; i++) {
65495188e31f172f7dee49b6ae0a3d81d4cfd8c1b231Chris Forbes            delete pPipeNode[i];
65505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
6551b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
65525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return VK_ERROR_VALIDATION_FAILED_EXT;
65535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
65545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
65555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
65565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
655789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL
655889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
655989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                       const VkComputePipelineCreateInfo *pCreateInfos, const VkAllocationCallbacks *pAllocator,
656089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                       VkPipeline *pPipelines) {
65615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkResult result = VK_SUCCESS;
656283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
65635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
65645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TODO : Improve this data struct w/ unique_ptrs so cleanup below is automatic
65655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    vector<PIPELINE_NODE *> pPipeNode(count);
65665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
65675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
65685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t i = 0;
6569b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
65705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (i = 0; i < count; i++) {
65715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // TODO: Verify compute stage bits
65725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
65735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Create and initialize internal tracking data structure
65745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pPipeNode[i] = new PIPELINE_NODE;
6575ca546210846c65808717f8875deae39bd227c240Tobin Ehlis        pPipeNode[i]->initComputePipeline(&pCreateInfos[i]);
6576c8268861aaa8f9c47920065d6323e4609e5081b0Tobin Ehlis        pPipeNode[i]->pipeline_layout = *getPipelineLayout(dev_data, pCreateInfos[i].layout);
6577ca546210846c65808717f8875deae39bd227c240Tobin Ehlis        // memcpy(&pPipeNode[i]->computePipelineCI, (const void *)&pCreateInfos[i], sizeof(VkComputePipelineCreateInfo));
65785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
65795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // TODO: Add Compute Pipeline Verification
6580f71dd305f197826a61f398bff725267a20ea1d90Chris Forbes        skip_call |= !validate_compute_pipeline(dev_data->report_data, pPipeNode[i], &dev_data->enabled_features,
658183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                                dev_data->shaderModuleMap);
658283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        // skip_call |= verifyPipelineCreateState(dev_data, device, pPipeNode[i]);
65835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
65845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
658583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call) {
6586b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
65874a0754042cf090e131e9e769d8a3633c228625beChris Forbes        result =
65884a0754042cf090e131e9e769d8a3633c228625beChris Forbes            dev_data->dispatch_table.CreateComputePipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines);
6589b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.lock();
65905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (i = 0; i < count; i++) {
65915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            pPipeNode[i]->pipeline = pPipelines[i];
65925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            dev_data->pipelineMap[pPipeNode[i]->pipeline] = pPipeNode[i];
65935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
6594b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
65955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
65965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (i = 0; i < count; i++) {
65975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // Clean up any locally allocated data structures
65985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            delete pPipeNode[i];
65995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
6600b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
66015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return VK_ERROR_VALIDATION_FAILED_EXT;
66025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
66035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
66045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
66055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
660689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo,
660789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                             const VkAllocationCallbacks *pAllocator, VkSampler *pSampler) {
66085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
66094a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateSampler(device, pCreateInfo, pAllocator, pSampler);
66105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
6611b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        std::lock_guard<std::mutex> lock(global_lock);
6612cb9ce9e05b8e939d3da35c64997c70049877f4feTobin Ehlis        dev_data->samplerMap[*pSampler] = unique_ptr<SAMPLER_NODE>(new SAMPLER_NODE(pSampler, pCreateInfo));
66135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
66145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
66155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
66165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
661789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL
661889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
661989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                          const VkAllocationCallbacks *pAllocator, VkDescriptorSetLayout *pSetLayout) {
66205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
66214a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateDescriptorSetLayout(device, pCreateInfo, pAllocator, pSetLayout);
66225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
66235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // TODOSC : Capture layout bindings set
6624b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        std::lock_guard<std::mutex> lock(global_lock);
6625cb9ce9e05b8e939d3da35c64997c70049877f4feTobin Ehlis        dev_data->descriptorSetLayoutMap[*pSetLayout] =
6626cb9ce9e05b8e939d3da35c64997c70049877f4feTobin Ehlis            new cvdescriptorset::DescriptorSetLayout(dev_data->report_data, pCreateInfo, *pSetLayout);
66275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
66285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
66295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
66305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
66319e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz// Used by CreatePipelineLayout and CmdPushConstants.
66329e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz// Note that the index argument is optional and only used by CreatePipelineLayout.
66339e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultzstatic bool validatePushConstantRange(const layer_data *dev_data, const uint32_t offset, const uint32_t size,
66349e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz                                      const char *caller_name, uint32_t index = 0) {
66350dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis    if (dev_data->instance_state->disabled.push_constant_range)
66360dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis        return false;
66379e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    uint32_t const maxPushConstantsSize = dev_data->phys_dev_properties.properties.limits.maxPushConstantsSize;
663883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
66399e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    // Check that offset + size don't exceed the max.
66409e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    // Prevent arithetic overflow here by avoiding addition and testing in this order.
66411c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis    // TODO : This check combines VALIDATION_ERROR_00877 & 880, need to break out separately
66429e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    if ((offset >= maxPushConstantsSize) || (size > maxPushConstantsSize - offset)) {
66439e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        // This is a pain just to adapt the log message to the caller, but better to sort it out only when there is a problem.
66449e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        if (0 == strcmp(caller_name, "vkCreatePipelineLayout()")) {
664583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |=
66469e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
66471c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis                        VALIDATION_ERROR_00877, "DS", "%s call has push constants index %u with offset %u and size %u that "
66481c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis                                                      "exceeds this device's maxPushConstantSize of %u. %s",
66491c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis                        caller_name, index, offset, size, maxPushConstantsSize, validation_error_map[VALIDATION_ERROR_00877]);
66509e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        } else if (0 == strcmp(caller_name, "vkCmdPushConstants()")) {
665183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
665283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 DRAWSTATE_PUSH_CONSTANTS_ERROR, "DS", "%s call has push constants with offset %u and size %u that "
665383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                                                       "exceeds this device's maxPushConstantSize of %u.",
665483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 caller_name, offset, size, maxPushConstantsSize);
66559e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        } else {
665683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
665783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 DRAWSTATE_INTERNAL_ERROR, "DS", "%s caller not supported.", caller_name);
66589e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        }
66599e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    }
66609e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    // size needs to be non-zero and a multiple of 4.
66611c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis    // TODO : This check combines VALIDATION_ERROR_00878 & 879, need to break out separately
66629e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    if ((size == 0) || ((size & 0x3) != 0)) {
66639e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        if (0 == strcmp(caller_name, "vkCreatePipelineLayout()")) {
66641c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
66651c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis                                 VALIDATION_ERROR_00878, "DS", "%s call has push constants index %u with "
66661c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis                                                               "size %u. Size must be greater than zero and a multiple of 4. %s",
66671c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis                                 caller_name, index, size, validation_error_map[VALIDATION_ERROR_00878]);
66689e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        } else if (0 == strcmp(caller_name, "vkCmdPushConstants()")) {
666983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |=
66709e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
66719e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz                        DRAWSTATE_PUSH_CONSTANTS_ERROR, "DS", "%s call has push constants with "
66729e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz                                                              "size %u. Size must be greater than zero and a multiple of 4.",
66739e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz                        caller_name, size);
66749e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        } else {
667583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
667683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 DRAWSTATE_INTERNAL_ERROR, "DS", "%s caller not supported.", caller_name);
66779e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        }
66789e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    }
66799e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    // offset needs to be a multiple of 4.
66809e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    if ((offset & 0x3) != 0) {
66819e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        if (0 == strcmp(caller_name, "vkCreatePipelineLayout()")) {
668283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
668383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 DRAWSTATE_PUSH_CONSTANTS_ERROR, "DS", "%s call has push constants index %u with "
668483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                                                       "offset %u. Offset must be a multiple of 4.",
668583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 caller_name, index, offset);
66869e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        } else if (0 == strcmp(caller_name, "vkCmdPushConstants()")) {
668783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
668883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 DRAWSTATE_PUSH_CONSTANTS_ERROR, "DS", "%s call has push constants with "
668983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                                                       "offset %u. Offset must be a multiple of 4.",
669083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 caller_name, offset);
66919e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        } else {
669283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
669383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 DRAWSTATE_INTERNAL_ERROR, "DS", "%s caller not supported.", caller_name);
66949e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        }
66955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
669683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    return skip_call;
66975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
66985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
669989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
670089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                    const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout) {
670183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
67025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
67031c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis    // TODO : Add checks for VALIDATION_ERRORS 865-871
67049e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    // Push Constant Range checks
670507a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz    uint32_t i, j;
67065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) {
670783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= validatePushConstantRange(dev_data, pCreateInfo->pPushConstantRanges[i].offset,
670883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                               pCreateInfo->pPushConstantRanges[i].size, "vkCreatePipelineLayout()", i);
67099e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        if (0 == pCreateInfo->pPushConstantRanges[i].stageFlags) {
671083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
671183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 DRAWSTATE_PUSH_CONSTANTS_ERROR, "DS", "vkCreatePipelineLayout() call has no stageFlags set.");
67129e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        }
67139e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    }
671407a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz    if (skip_call)
671507a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz        return VK_ERROR_VALIDATION_FAILED_EXT;
671607a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz
67179e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    // Each range has been validated.  Now check for overlap between ranges (if they are good).
671807a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz    // There's no explicit Valid Usage language against this, so issue a warning instead of an error.
671907a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz    for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) {
672007a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz        for (j = i + 1; j < pCreateInfo->pushConstantRangeCount; ++j) {
672107a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz            const uint32_t minA = pCreateInfo->pPushConstantRanges[i].offset;
672207a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz            const uint32_t maxA = minA + pCreateInfo->pPushConstantRanges[i].size;
672307a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz            const uint32_t minB = pCreateInfo->pPushConstantRanges[j].offset;
672407a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz            const uint32_t maxB = minB + pCreateInfo->pPushConstantRanges[j].size;
672507a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz            if ((minA <= minB && maxA > minB) || (minB <= minA && maxB > minA)) {
672607a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz                skip_call |=
672707a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
672807a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz                            DRAWSTATE_PUSH_CONSTANTS_ERROR, "DS", "vkCreatePipelineLayout() call has push constants with "
672907a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz                                                                  "overlapping ranges: %u:[%u, %u), %u:[%u, %u)",
673007a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz                            i, minA, maxA, j, minB, maxB);
67319e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz            }
67325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
67335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
6734f73b2046273413ea1338dd714d67c39f8e0fa09eChris Forbes
67354a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
67365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
6737b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        std::lock_guard<std::mutex> lock(global_lock);
67385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        PIPELINE_LAYOUT_NODE &plNode = dev_data->pipelineLayoutMap[*pPipelineLayout];
673969b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis        plNode.layout = *pPipelineLayout;
6740416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis        plNode.set_layouts.resize(pCreateInfo->setLayoutCount);
67415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (i = 0; i < pCreateInfo->setLayoutCount; ++i) {
6742416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis            plNode.set_layouts[i] = getDescriptorSetLayout(dev_data, pCreateInfo->pSetLayouts[i]);
67435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
6744416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis        plNode.push_constant_ranges.resize(pCreateInfo->pushConstantRangeCount);
67455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) {
6746416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis            plNode.push_constant_ranges[i] = pCreateInfo->pPushConstantRanges[i];
67475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
67485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
67495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
67505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
67515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
675289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL
675389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCreateDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
675489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                     VkDescriptorPool *pDescriptorPool) {
67555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
67564a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateDescriptorPool(device, pCreateInfo, pAllocator, pDescriptorPool);
67575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
67585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Insert this pool into Global Pool LL at head
67595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
6760414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                    (uint64_t)*pDescriptorPool, __LINE__, DRAWSTATE_OUT_OF_MEMORY, "DS", "Created Descriptor Pool 0x%" PRIxLEAST64,
67615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    (uint64_t)*pDescriptorPool))
67625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            return VK_ERROR_VALIDATION_FAILED_EXT;
67635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        DESCRIPTOR_POOL_NODE *pNewNode = new DESCRIPTOR_POOL_NODE(*pDescriptorPool, pCreateInfo);
67645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (NULL == pNewNode) {
67655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
67665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        (uint64_t)*pDescriptorPool, __LINE__, DRAWSTATE_OUT_OF_MEMORY, "DS",
67675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        "Out of memory while attempting to allocate DESCRIPTOR_POOL_NODE in vkCreateDescriptorPool()"))
67685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                return VK_ERROR_VALIDATION_FAILED_EXT;
67695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
6770b9e992386a44404152747d66817a733aa127e281Jeremy Hayes            std::lock_guard<std::mutex> lock(global_lock);
67715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            dev_data->descriptorPoolMap[*pDescriptorPool] = pNewNode;
67725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
67735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
67745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Need to do anything if pool create fails?
67755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
67765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
67775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
67785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
677989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL
678089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags) {
67815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
67824a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.ResetDescriptorPool(device, descriptorPool, flags);
67835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
6784b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        std::lock_guard<std::mutex> lock(global_lock);
67855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        clearDescriptorPool(dev_data, device, descriptorPool, flags);
67865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
67875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
67885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
67892c4e180a4442f968b44f3d5136f7ffda706f6428Chris Forbes// Ensure the pool contains enough descriptors and descriptor sets to satisfy
6790789832b514862c7a7b5b847eeb8e7cacb733b77bTobin Ehlis// an allocation request. Fills common_data with the total number of descriptors of each type required,
6791789832b514862c7a7b5b847eeb8e7cacb733b77bTobin Ehlis// as well as DescriptorSetLayout ptrs used for later update.
67927f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlisstatic bool PreCallValidateAllocateDescriptorSets(layer_data *dev_data, const VkDescriptorSetAllocateInfo *pAllocateInfo,
67937f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis                                                  cvdescriptorset::AllocateDescriptorSetsData *common_data) {
67940dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis    if (dev_data->instance_state->disabled.allocate_descriptor_sets)
67950dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis        return false;
67967e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis    // All state checks for AllocateDescriptorSets is done in single function
6797e3f7c45fd64a44a67ce96c89e2bbee426c6ecf24Tobin Ehlis    return cvdescriptorset::ValidateAllocateDescriptorSets(dev_data->report_data, pAllocateInfo, dev_data, common_data);
67987e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis}
67997e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis// Allocation state was good and call down chain was made so update state based on allocating descriptor sets
68007e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlisstatic void PostCallRecordAllocateDescriptorSets(layer_data *dev_data, const VkDescriptorSetAllocateInfo *pAllocateInfo,
68017f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis                                                 VkDescriptorSet *pDescriptorSets,
68027f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis                                                 const cvdescriptorset::AllocateDescriptorSetsData *common_data) {
68037e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis    // All the updates are contained in a single cvdescriptorset function
68042c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis    cvdescriptorset::PerformAllocateDescriptorSets(pAllocateInfo, pDescriptorSets, common_data, &dev_data->descriptorPoolMap,
6805b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis                                                   &dev_data->setMap, dev_data);
68062c4e180a4442f968b44f3d5136f7ffda706f6428Chris Forbes}
68072c4e180a4442f968b44f3d5136f7ffda706f6428Chris Forbes
680889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL
680989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo, VkDescriptorSet *pDescriptorSets) {
68105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
6811b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
68127f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis    cvdescriptorset::AllocateDescriptorSetsData common_data(pAllocateInfo->descriptorSetCount);
68137f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis    bool skip_call = PreCallValidateAllocateDescriptorSets(dev_data, pAllocateInfo, &common_data);
6814b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
6815d173e0daab123373ce75105f2a908f6ae7cef6abChris Forbes
68167e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis    if (skip_call)
68175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return VK_ERROR_VALIDATION_FAILED_EXT;
6818d173e0daab123373ce75105f2a908f6ae7cef6abChris Forbes
68194a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.AllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
68206511ce241f7f210211e0c0e882f3c14889071f4dChris Forbes
68215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
6822b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.lock();
68237f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis        PostCallRecordAllocateDescriptorSets(dev_data, pAllocateInfo, pDescriptorSets, &common_data);
6824b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
68255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
68265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
68275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
6828cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis// Verify state before freeing DescriptorSets
6829cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlisstatic bool PreCallValidateFreeDescriptorSets(const layer_data *dev_data, VkDescriptorPool pool, uint32_t count,
6830cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis                                              const VkDescriptorSet *descriptor_sets) {
68310dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis    if (dev_data->instance_state->disabled.free_descriptor_sets)
68320dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis        return false;
6833cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis    bool skip_call = false;
6834cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis    // First make sure sets being destroyed are not currently in-use
6835cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis    for (uint32_t i = 0; i < count; ++i)
6836cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis        skip_call |= validateIdleDescriptorSet(dev_data, descriptor_sets[i], "vkFreeDescriptorSets");
6837cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis
6838cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis    DESCRIPTOR_POOL_NODE *pool_node = getPoolNode(dev_data, pool);
6839cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis    if (pool_node && !(VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT & pool_node->createInfo.flags)) {
6840cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis        // Can't Free from a NON_FREE pool
6841cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis        skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
68421c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis                             reinterpret_cast<uint64_t &>(pool), __LINE__, VALIDATION_ERROR_00922, "DS",
6843cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis                             "It is invalid to call vkFreeDescriptorSets() with a pool created without setting "
68441c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis                             "VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT. %s",
68451c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis                             validation_error_map[VALIDATION_ERROR_00922]);
6846cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis    }
6847cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis    return skip_call;
6848cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis}
6849cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis// Sets have been removed from the pool so update underlying state
6850cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlisstatic void PostCallRecordFreeDescriptorSets(layer_data *dev_data, VkDescriptorPool pool, uint32_t count,
6851cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis                                             const VkDescriptorSet *descriptor_sets) {
6852cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis    DESCRIPTOR_POOL_NODE *pool_state = getPoolNode(dev_data, pool);
6853cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis    // Update available descriptor sets in pool
6854cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis    pool_state->availableSets += count;
6855cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis
6856cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis    // For each freed descriptor add its resources back into the pool as available and remove from pool and setMap
6857cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis    for (uint32_t i = 0; i < count; ++i) {
6858cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis        auto set_state = dev_data->setMap[descriptor_sets[i]];
6859cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis        uint32_t type_index = 0, descriptor_count = 0;
6860cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis        for (uint32_t j = 0; j < set_state->GetBindingCount(); ++j) {
6861cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis            type_index = static_cast<uint32_t>(set_state->GetTypeFromIndex(j));
6862cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis            descriptor_count = set_state->GetDescriptorCountFromIndex(j);
6863cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis            pool_state->availableDescriptorTypeCount[type_index] += descriptor_count;
6864cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis        }
6865cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis        freeDescriptorSet(dev_data, set_state);
6866cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis        pool_state->sets.erase(set_state);
6867cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis    }
6868cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis}
68695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
687089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL
687189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuFreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t count, const VkDescriptorSet *pDescriptorSets) {
68725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
68735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Make sure that no sets being destroyed are in-flight
6874b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
687583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = PreCallValidateFreeDescriptorSets(dev_data, descriptorPool, count, pDescriptorSets);
6876b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
6877e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis
687883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (skip_call)
68795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return VK_ERROR_VALIDATION_FAILED_EXT;
68804a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.FreeDescriptorSets(device, descriptorPool, count, pDescriptorSets);
68815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
6882b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.lock();
6883cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis        PostCallRecordFreeDescriptorSets(dev_data, descriptorPool, count, pDescriptorSets);
6884b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
68855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
68865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
68875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
68886b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// TODO : This is a Proof-of-concept for core validation architecture
68896b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis//  Really we'll want to break out these functions to separate files but
68906b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis//  keeping it all together here to prove out design
68916b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// PreCallValidate* handles validating all of the state prior to calling down chain to UpdateDescriptorSets()
68926b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlisstatic bool PreCallValidateUpdateDescriptorSets(layer_data *dev_data, uint32_t descriptorWriteCount,
68936b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis                                                const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount,
68946b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis                                                const VkCopyDescriptorSet *pDescriptorCopies) {
68956b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis    // First thing to do is perform map look-ups.
68966b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis    // NOTE : UpdateDescriptorSets is somewhat unique in that it's operating on a number of DescriptorSets
68976b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis    //  so we can't just do a single map look-up up-front, but do them individually in functions below
68986b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis
68996b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis    // Now make call(s) that validate state, but don't perform state updates in this function
69006b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis    // Note, here DescriptorSets is unique in that we don't yet have an instance. Using a helper function in the
69016b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis    //  namespace which will parse params and make calls into specific class instances
6902104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis    return cvdescriptorset::ValidateUpdateDescriptorSets(dev_data->report_data, dev_data, descriptorWriteCount, pDescriptorWrites,
6903104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis                                                         descriptorCopyCount, pDescriptorCopies);
69046b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis}
69056b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// PostCallRecord* handles recording state updates following call down chain to UpdateDescriptorSets()
69066b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlisstatic void PostCallRecordUpdateDescriptorSets(layer_data *dev_data, uint32_t descriptorWriteCount,
69076b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis                                               const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount,
69086b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis                                               const VkCopyDescriptorSet *pDescriptorCopies) {
6909104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis    cvdescriptorset::PerformUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount,
69106b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis                                                 pDescriptorCopies);
69116b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis}
69125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
691389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
691489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuUpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet *pDescriptorWrites,
691589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                     uint32_t descriptorCopyCount, const VkCopyDescriptorSet *pDescriptorCopies) {
69166b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis    // Only map look-up at top level is for device-level layer_data
69175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
6918b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
69196b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis    bool skip_call = PreCallValidateUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount,
69206b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis                                                         pDescriptorCopies);
6921b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
69226b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis    if (!skip_call) {
69234a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.UpdateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount,
69244a0754042cf090e131e9e769d8a3633c228625beChris Forbes                                                      pDescriptorCopies);
69256b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis        lock.lock();
69266b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis        // Since UpdateDescriptorSets() is void, nothing to check prior to updating state
69276b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis        PostCallRecordUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount,
69286b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis                                           pDescriptorCopies);
69295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
69305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
69315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
693289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL
693389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuAllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pCreateInfo, VkCommandBuffer *pCommandBuffer) {
69345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
69354a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.AllocateCommandBuffers(device, pCreateInfo, pCommandBuffer);
69365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
6937b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        std::unique_lock<std::mutex> lock(global_lock);
6938cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes        auto pPool = getCommandPoolNode(dev_data, pCreateInfo->commandPool);
6939cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes
6940cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes        if (pPool) {
694172d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis            for (uint32_t i = 0; i < pCreateInfo->commandBufferCount; i++) {
69425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                // Add command buffer to its commandPool map
6943cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes                pPool->commandBuffers.push_back(pCommandBuffer[i]);
69445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                GLOBAL_CB_NODE *pCB = new GLOBAL_CB_NODE;
69455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                // Add command buffer to map
69465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                dev_data->commandBufferMap[pCommandBuffer[i]] = pCB;
69475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                resetCB(dev_data, pCommandBuffer[i]);
69485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                pCB->createInfo = *pCreateInfo;
69495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                pCB->device = device;
69505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
69515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
69520a1ce3dfd81c9f4efbe46f5ba5ddaea70bc4aa61Chris Forbes        printCBList(dev_data);
6953b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
69545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
69555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
69565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
69575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6958883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis// Add bindings between the given cmd buffer & framebuffer and the framebuffer's children
6959883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlisstatic void AddFramebufferBinding(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, FRAMEBUFFER_NODE *fb_state) {
6960883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis    fb_state->cb_bindings.insert(cb_state);
6961883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis    for (auto attachment : fb_state->attachments) {
6962883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis        auto view_state = attachment.view_state;
6963883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis        if (view_state) {
696403ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis            AddCommandBufferBindingImageView(dev_data, cb_state, view_state);
6965883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis        }
6966883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis        auto rp_state = getRenderPass(dev_data, fb_state->createInfo.renderPass);
6967883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis        if (rp_state) {
6968883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis            addCommandBufferBinding(
6969883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis                &rp_state->cb_bindings,
6970883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis                {reinterpret_cast<uint64_t &>(rp_state->renderPass), VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT}, cb_state);
6971883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis        }
6972883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis    }
6973883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis}
6974883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis
697589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL
697689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuBeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo *pBeginInfo) {
697783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
69785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
6979b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
69805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Validate command buffer level
6981f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis    GLOBAL_CB_NODE *cb_node = getCBNode(dev_data, commandBuffer);
6982f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis    if (cb_node) {
69835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // This implicitly resets the Cmd Buffer so make sure any fence is done and then clear memory references
6984a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis        if (dev_data->globalInFlightCmdBuffers.count(commandBuffer)) {
698583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |=
6986a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
6987a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis                        (uint64_t)commandBuffer, __LINE__, MEMTRACK_RESET_CB_WHILE_IN_FLIGHT, "MEM",
6988414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        "Calling vkBeginCommandBuffer() on active CB 0x%p before it has completed. "
6989a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis                        "You must check CB fence before this call.",
6990a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis                        commandBuffer);
69915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
6992f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis        clear_cmd_buf_and_mem_references(dev_data, cb_node);
6993f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis        if (cb_node->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) {
69945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // Secondary Command Buffer
69955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            const VkCommandBufferInheritanceInfo *pInfo = pBeginInfo->pInheritanceInfo;
69965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (!pInfo) {
699783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                skip_call |=
69985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
69995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            reinterpret_cast<uint64_t>(commandBuffer), __LINE__, DRAWSTATE_BEGIN_CB_INVALID_STATE, "DS",
7000414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                            "vkBeginCommandBuffer(): Secondary Command Buffer (0x%p) must have inheritance info.",
70015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            reinterpret_cast<void *>(commandBuffer));
70025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            } else {
70035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if (pBeginInfo->flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT) {
7004400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis                    if (!pInfo->renderPass) { // renderpass should NOT be null for a Secondary CB
700583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                        skip_call |= log_msg(
70065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
70075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            reinterpret_cast<uint64_t>(commandBuffer), __LINE__, DRAWSTATE_BEGIN_CB_INVALID_STATE, "DS",
7008414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                            "vkBeginCommandBuffer(): Secondary Command Buffers (0x%p) must specify a valid renderpass parameter.",
70095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            reinterpret_cast<void *>(commandBuffer));
70105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
7011400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis                    if (!pInfo->framebuffer) { // framebuffer may be null for a Secondary CB, but this affects perf
701283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                        skip_call |= log_msg(
701383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
701483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            reinterpret_cast<uint64_t>(commandBuffer), __LINE__, DRAWSTATE_BEGIN_CB_INVALID_STATE, "DS",
701583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            "vkBeginCommandBuffer(): Secondary Command Buffers (0x%p) may perform better if a "
701683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            "valid framebuffer parameter is specified.",
701783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            reinterpret_cast<void *>(commandBuffer));
70185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    } else {
70195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        string errorString = "";
7020f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes                        auto framebuffer = getFramebuffer(dev_data, pInfo->framebuffer);
7021f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes                        if (framebuffer) {
7022a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                            if ((framebuffer->createInfo.renderPass != pInfo->renderPass) &&
7023a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                !verify_renderpass_compatibility(dev_data, framebuffer->renderPassCreateInfo.ptr(),
7024fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes                                                                 getRenderPass(dev_data, pInfo->renderPass)->createInfo.ptr(),
7025a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                                                 errorString)) {
7026400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis                                // renderPass that framebuffer was created with must be compatible with local renderPass
702783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                skip_call |= log_msg(
7028a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                    dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7029a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t>(commandBuffer),
7030a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                    __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS",
7031a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                    "vkBeginCommandBuffer(): Secondary Command "
7032a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                    "Buffer (0x%p) renderPass (0x%" PRIxLEAST64 ") is incompatible w/ framebuffer "
7033a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                    "(0x%" PRIxLEAST64 ") w/ render pass (0x%" PRIxLEAST64 ") due to: %s",
7034a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                    reinterpret_cast<void *>(commandBuffer), reinterpret_cast<const uint64_t &>(pInfo->renderPass),
7035a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                    reinterpret_cast<const uint64_t &>(pInfo->framebuffer),
7036a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                    reinterpret_cast<uint64_t &>(framebuffer->createInfo.renderPass), errorString.c_str());
70375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            }
7038883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis                            // Connect this framebuffer and its children to this cmdBuffer
7039883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis                            AddFramebufferBinding(dev_data, cb_node, framebuffer);
70405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        }
70415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
70425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
70435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if ((pInfo->occlusionQueryEnable == VK_FALSE ||
7044f71dd305f197826a61f398bff725267a20ea1d90Chris Forbes                     dev_data->enabled_features.occlusionQueryPrecise == VK_FALSE) &&
70455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    (pInfo->queryFlags & VK_QUERY_CONTROL_PRECISE_BIT)) {
704683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                    skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
704783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                         VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t>(commandBuffer),
704883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                         __LINE__, DRAWSTATE_BEGIN_CB_INVALID_STATE, "DS",
704983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                         "vkBeginCommandBuffer(): Secondary Command Buffer (0x%p) must not have "
705083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                         "VK_QUERY_CONTROL_PRECISE_BIT if occulusionQuery is disabled or the device does not "
705183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                         "support precise occlusion queries.",
705283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                         reinterpret_cast<void *>(commandBuffer));
70535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
70545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
70555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (pInfo && pInfo->renderPass != VK_NULL_HANDLE) {
705616387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                auto renderPass = getRenderPass(dev_data, pInfo->renderPass);
705716387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                if (renderPass) {
7058fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes                    if (pInfo->subpass >= renderPass->createInfo.subpassCount) {
705983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                        skip_call |= log_msg(
706083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
706183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            (uint64_t)commandBuffer, __LINE__, DRAWSTATE_BEGIN_CB_INVALID_STATE, "DS",
706283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            "vkBeginCommandBuffer(): Secondary Command Buffers (0x%p) must has a subpass index (%d) "
706383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            "that is less than the number of subpasses (%d).",
7064fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes                            (void *)commandBuffer, pInfo->subpass, renderPass->createInfo.subpassCount);
70655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
70665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
70675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
70685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
7069f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis        if (CB_RECORDING == cb_node->state) {
707083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |=
70715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
70725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        (uint64_t)commandBuffer, __LINE__, DRAWSTATE_BEGIN_CB_INVALID_STATE, "DS",
7073414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        "vkBeginCommandBuffer(): Cannot call Begin on CB (0x%" PRIxLEAST64
70745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        ") in the RECORDING state. Must first call vkEndCommandBuffer().",
70755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        (uint64_t)commandBuffer);
7076f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis        } else if (CB_RECORDED == cb_node->state || (CB_INVALID == cb_node->state && CMD_END == cb_node->cmds.back().type)) {
7077f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            VkCommandPool cmdPool = cb_node->createInfo.commandPool;
7078cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes            auto pPool = getCommandPoolNode(dev_data, cmdPool);
7079cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes            if (!(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT & pPool->createFlags)) {
708083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                skip_call |=
70815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
70825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            (uint64_t)commandBuffer, __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER_RESET, "DS",
7083414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                            "Call to vkBeginCommandBuffer() on command buffer (0x%" PRIxLEAST64
7084414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                            ") attempts to implicitly reset cmdBuffer created from command pool (0x%" PRIxLEAST64
70855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            ") that does NOT have the VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit set.",
70865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            (uint64_t)commandBuffer, (uint64_t)cmdPool);
70875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
70885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            resetCB(dev_data, commandBuffer);
70895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
70905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Set updated state here in case implicit reset occurs above
7091f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis        cb_node->state = CB_RECORDING;
7092f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis        cb_node->beginInfo = *pBeginInfo;
7093f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis        if (cb_node->beginInfo.pInheritanceInfo) {
7094f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            cb_node->inheritanceInfo = *(cb_node->beginInfo.pInheritanceInfo);
7095f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            cb_node->beginInfo.pInheritanceInfo = &cb_node->inheritanceInfo;
7096888e1d268098177fde4a2263e3d7b7cc415f1debMark Young            // If we are a secondary command-buffer and inheriting.  Update the items we should inherit.
7097f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            if ((cb_node->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) &&
7098f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis                (cb_node->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) {
7099f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis                cb_node->activeRenderPass = getRenderPass(dev_data, cb_node->beginInfo.pInheritanceInfo->renderPass);
7100f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis                cb_node->activeSubpass = cb_node->beginInfo.pInheritanceInfo->subpass;
7101f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis                cb_node->framebuffers.insert(cb_node->beginInfo.pInheritanceInfo->framebuffer);
7102888e1d268098177fde4a2263e3d7b7cc415f1debMark Young            }
71035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
71045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
710583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
710683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                             (uint64_t)commandBuffer, __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
710783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                             "In vkBeginCommandBuffer() and unable to find CommandBuffer Node for CB 0x%p!", (void *)commandBuffer);
71085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7109b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
711083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (skip_call) {
71115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return VK_ERROR_VALIDATION_FAILED_EXT;
71125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
71134a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.BeginCommandBuffer(commandBuffer, pBeginInfo);
7114400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis
71155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
71165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
71175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
711889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL EndCommandBuffer(VkCommandBuffer commandBuffer) {
711983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
71205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkResult result = VK_SUCCESS;
71215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7122b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
71235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
71245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
7125fd61966f8d41b5bce15620b70563b7864cbb28feCody Northrop        if ((VK_COMMAND_BUFFER_LEVEL_PRIMARY == pCB->createInfo.level) || !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) {
7126fd61966f8d41b5bce15620b70563b7864cbb28feCody Northrop            // This needs spec clarification to update valid usage, see comments in PR:
7127fd61966f8d41b5bce15620b70563b7864cbb28feCody Northrop            // https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/pull/516#discussion_r63013756
712883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= insideRenderPass(dev_data, pCB, "vkEndCommandBuffer");
7129fd61966f8d41b5bce15620b70563b7864cbb28feCody Northrop        }
713083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, pCB, CMD_END, "vkEndCommandBuffer()");
71315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (auto query : pCB->activeQueries) {
713283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
713383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 DRAWSTATE_INVALID_QUERY, "DS",
713483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 "Ending command buffer with in progress query: queryPool 0x%" PRIx64 ", index %d",
713583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 (uint64_t)(query.pool), query.index);
71365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
71375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
713883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call) {
7139b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
71404a0754042cf090e131e9e769d8a3633c228625beChris Forbes        result = dev_data->dispatch_table.EndCommandBuffer(commandBuffer);
7141b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.lock();
71425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (VK_SUCCESS == result) {
71435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            pCB->state = CB_RECORDED;
71445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // Reset CB status flags
71455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            pCB->status = 0;
71465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            printCB(dev_data, commandBuffer);
71475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
71485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
71495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        result = VK_ERROR_VALIDATION_FAILED_EXT;
71505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7151b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
71525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
71535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
71545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
715589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL
715689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuResetCommandBuffer(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags) {
7157bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis    bool skip_call = false;
71585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7159b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
71605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
71615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkCommandPool cmdPool = pCB->createInfo.commandPool;
7162cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes    auto pPool = getCommandPoolNode(dev_data, cmdPool);
7163cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes    if (!(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT & pPool->createFlags)) {
7164bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis        skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
7165bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis                             (uint64_t)commandBuffer, __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER_RESET, "DS",
7166414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                             "Attempt to reset command buffer (0x%" PRIxLEAST64 ") created from command pool (0x%" PRIxLEAST64
7167bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis                             ") that does NOT have the VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit set.",
7168bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis                             (uint64_t)commandBuffer, (uint64_t)cmdPool);
71695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7170a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes    skip_call |= checkCommandBufferInFlight(dev_data, pCB, "reset");
7171b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
7172bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis    if (skip_call)
71735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return VK_ERROR_VALIDATION_FAILED_EXT;
71744a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.ResetCommandBuffer(commandBuffer, flags);
71755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
7176b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.lock();
7177a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes        dev_data->globalInFlightCmdBuffers.erase(commandBuffer);
71785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        resetCB(dev_data, commandBuffer);
7179b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
71805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
71815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
71825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
718393c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski
718489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
718589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline) {
718683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
71875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7188b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
71895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
71905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
719183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, pCB, CMD_BINDPIPELINE, "vkCmdBindPipeline()");
71925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if ((VK_PIPELINE_BIND_POINT_COMPUTE == pipelineBindPoint) && (pCB->activeRenderPass)) {
719383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |=
71945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
71955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        (uint64_t)pipeline, __LINE__, DRAWSTATE_INVALID_RENDERPASS_CMD, "DS",
7196414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        "Incorrectly binding compute pipeline (0x%" PRIxLEAST64 ") during active RenderPass (0x%" PRIxLEAST64 ")",
7197ee691f5c5fa87aac3750454d2bca2cb582e4e817Chris Forbes                        (uint64_t)pipeline, (uint64_t)pCB->activeRenderPass->renderPass);
71985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
71995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
72005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        PIPELINE_NODE *pPN = getPipeline(dev_data, pipeline);
72015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (pPN) {
72025c288f35b2eab0dab95d18768235fef6ffd69b30Tobin Ehlis            pCB->lastBound[pipelineBindPoint].pipeline_node = pPN;
72035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            set_cb_pso_status(pCB, pPN);
72043d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis            set_pipeline_state(pPN);
72055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
720683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
720783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 (uint64_t)pipeline, __LINE__, DRAWSTATE_INVALID_PIPELINE, "DS",
720883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 "Attempt to bind Pipeline 0x%" PRIxLEAST64 " that doesn't exist!", (uint64_t)(pipeline));
72095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
7210a86b57cf1145ee63d5997547ac0f9847933fc3b6Tobin Ehlis        addCommandBufferBinding(&getPipeline(dev_data, pipeline)->cb_bindings,
7211a86b57cf1145ee63d5997547ac0f9847933fc3b6Tobin Ehlis                                {reinterpret_cast<uint64_t &>(pipeline), VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT}, pCB);
72125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7213b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
721483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
72154a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline);
72165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
72175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
721889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
721989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport *pViewports) {
722083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
72215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7222b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
72235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
72245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
722583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, pCB, CMD_SETVIEWPORTSTATE, "vkCmdSetViewport()");
7226b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes        pCB->viewportMask |= ((1u<<viewportCount) - 1u) << firstViewport;
72275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7228b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
722983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
72304a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdSetViewport(commandBuffer, firstViewport, viewportCount, pViewports);
72315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
72325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
723389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
723489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, const VkRect2D *pScissors) {
723583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
72365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7237b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
72385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
72395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
724083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, pCB, CMD_SETSCISSORSTATE, "vkCmdSetScissor()");
7241b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes        pCB->scissorMask |= ((1u<<scissorCount) - 1u) << firstScissor;
72425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7243b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
724483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
72454a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdSetScissor(commandBuffer, firstScissor, scissorCount, pScissors);
72465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
72475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
724889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth) {
7249a27508babf63d50aea75883a3702979193c23683Mark Young    bool skip_call = false;
72505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7251b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
72525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
72535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
7254a27508babf63d50aea75883a3702979193c23683Mark Young        skip_call |= addCmd(dev_data, pCB, CMD_SETLINEWIDTHSTATE, "vkCmdSetLineWidth()");
72555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->status |= CBSTATUS_LINE_WIDTH_SET;
7256a27508babf63d50aea75883a3702979193c23683Mark Young
72575c288f35b2eab0dab95d18768235fef6ffd69b30Tobin Ehlis        PIPELINE_NODE *pPipeTrav = pCB->lastBound[VK_PIPELINE_BIND_POINT_GRAPHICS].pipeline_node;
7258a27508babf63d50aea75883a3702979193c23683Mark Young        if (pPipeTrav != NULL && !isDynamic(pPipeTrav, VK_DYNAMIC_STATE_LINE_WIDTH)) {
7259a27508babf63d50aea75883a3702979193c23683Mark Young            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0,
7260a27508babf63d50aea75883a3702979193c23683Mark Young                                 reinterpret_cast<uint64_t &>(commandBuffer), __LINE__, DRAWSTATE_INVALID_SET, "DS",
7261386d9a9a77f884789a7ae4c3890aecd47132f2babaldurk                                 "vkCmdSetLineWidth called but pipeline was created without VK_DYNAMIC_STATE_LINE_WIDTH "
7262a27508babf63d50aea75883a3702979193c23683Mark Young                                 "flag.  This is undefined behavior and could be ignored.");
7263a27508babf63d50aea75883a3702979193c23683Mark Young        } else {
7264a27508babf63d50aea75883a3702979193c23683Mark Young            skip_call |= verifyLineWidth(dev_data, DRAWSTATE_INVALID_SET, reinterpret_cast<uint64_t &>(commandBuffer), lineWidth);
7265a27508babf63d50aea75883a3702979193c23683Mark Young        }
72665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7267b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
7268a27508babf63d50aea75883a3702979193c23683Mark Young    if (!skip_call)
72694a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdSetLineWidth(commandBuffer, lineWidth);
72705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
72715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
727289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
727389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdSetDepthBias(VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor) {
727483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
72755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7276b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
72775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
72785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
727983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, pCB, CMD_SETDEPTHBIASSTATE, "vkCmdSetDepthBias()");
72805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->status |= CBSTATUS_DEPTH_BIAS_SET;
72815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7282b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
728383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
72844a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdSetDepthBias(commandBuffer, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor);
72855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
72865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
728789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdSetBlendConstants(VkCommandBuffer commandBuffer, const float blendConstants[4]) {
728883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
72895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7290b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
72915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
72925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
729383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, pCB, CMD_SETBLENDSTATE, "vkCmdSetBlendConstants()");
72943d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        pCB->status |= CBSTATUS_BLEND_CONSTANTS_SET;
72955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7296b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
729783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
72984a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdSetBlendConstants(commandBuffer, blendConstants);
72995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
73005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
730189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
730289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdSetDepthBounds(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds) {
730383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
73045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7305b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
73065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
73075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
730883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, pCB, CMD_SETDEPTHBOUNDSSTATE, "vkCmdSetDepthBounds()");
73095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->status |= CBSTATUS_DEPTH_BOUNDS_SET;
73105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7311b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
731283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
73134a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdSetDepthBounds(commandBuffer, minDepthBounds, maxDepthBounds);
73145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
73155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
731689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
731789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdSetStencilCompareMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t compareMask) {
731883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
73195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7320b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
73215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
73225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
732383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, pCB, CMD_SETSTENCILREADMASKSTATE, "vkCmdSetStencilCompareMask()");
73245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->status |= CBSTATUS_STENCIL_READ_MASK_SET;
73255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7326b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
732783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
73284a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdSetStencilCompareMask(commandBuffer, faceMask, compareMask);
73295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
73305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
733189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
733289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdSetStencilWriteMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask) {
733383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
73345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7335b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
73365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
73375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
733883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, pCB, CMD_SETSTENCILWRITEMASKSTATE, "vkCmdSetStencilWriteMask()");
73395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->status |= CBSTATUS_STENCIL_WRITE_MASK_SET;
73405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7341b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
734283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
73434a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdSetStencilWriteMask(commandBuffer, faceMask, writeMask);
73445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
73455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
734689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
734789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdSetStencilReference(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference) {
734883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
73495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7350b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
73515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
73525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
735383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, pCB, CMD_SETSTENCILREFERENCESTATE, "vkCmdSetStencilReference()");
73545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->status |= CBSTATUS_STENCIL_REFERENCE_SET;
73555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7356b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
735783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
73584a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdSetStencilReference(commandBuffer, faceMask, reference);
73595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
73605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
736189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
736289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout,
736389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                      uint32_t firstSet, uint32_t setCount, const VkDescriptorSet *pDescriptorSets, uint32_t dynamicOffsetCount,
736489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                      const uint32_t *pDynamicOffsets) {
736583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
73665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7367b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
73685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
73695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
73705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (pCB->state == CB_RECORDING) {
7371787f29d93dee194c015789cf61c079504c980572Tobin Ehlis            // Track total count of dynamic descriptor types to make sure we have an offset for each one
7372787f29d93dee194c015789cf61c079504c980572Tobin Ehlis            uint32_t totalDynamicDescriptors = 0;
7373787f29d93dee194c015789cf61c079504c980572Tobin Ehlis            string errorString = "";
7374787f29d93dee194c015789cf61c079504c980572Tobin Ehlis            uint32_t lastSetIndex = firstSet + setCount - 1;
7375dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes            if (lastSetIndex >= pCB->lastBound[pipelineBindPoint].boundDescriptorSets.size()) {
737672d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                pCB->lastBound[pipelineBindPoint].boundDescriptorSets.resize(lastSetIndex + 1);
7377dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes                pCB->lastBound[pipelineBindPoint].dynamicOffsets.resize(lastSetIndex + 1);
7378dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes            }
737971511c5a10533c910bfe62c3bcf58e2a4054e7acTobin Ehlis            auto oldFinalBoundSet = pCB->lastBound[pipelineBindPoint].boundDescriptorSets[lastSetIndex];
738069b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis            auto pipeline_layout = getPipelineLayout(dev_data, layout);
7381787f29d93dee194c015789cf61c079504c980572Tobin Ehlis            for (uint32_t i = 0; i < setCount; i++) {
7382397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis                cvdescriptorset::DescriptorSet *pSet = getSetNode(dev_data, pDescriptorSets[i]);
7383787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                if (pSet) {
738469b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis                    pCB->lastBound[pipelineBindPoint].pipeline_layout = *pipeline_layout;
738571511c5a10533c910bfe62c3bcf58e2a4054e7acTobin Ehlis                    pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i + firstSet] = pSet;
738683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                    skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT,
738783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                         VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[i], __LINE__,
738883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                         DRAWSTATE_NONE, "DS", "DS 0x%" PRIxLEAST64 " bound on pipeline %s",
738983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                         (uint64_t)pDescriptorSets[i], string_VkPipelineBindPoint(pipelineBindPoint));
7390397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis                    if (!pSet->IsUpdated() && (pSet->GetTotalDescriptorCount() != 0)) {
739183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                        skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
739283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                             VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[i], __LINE__,
739383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                             DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS",
739483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                             "DS 0x%" PRIxLEAST64
739583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                             " bound but it was never updated. You may want to either update it or not bind it.",
739683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                             (uint64_t)pDescriptorSets[i]);
7397787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                    }
7398787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                    // Verify that set being bound is compatible with overlapping setLayout of pipelineLayout
739969b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis                    if (!verify_set_layout_compatibility(dev_data, pSet, pipeline_layout, i + firstSet, errorString)) {
740083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                        skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
740183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                             VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[i], __LINE__,
740283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                             DRAWSTATE_PIPELINE_LAYOUTS_INCOMPATIBLE, "DS",
740383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                             "descriptorSet #%u being bound is not compatible with overlapping descriptorSetLayout "
740483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                             "at index %u of pipelineLayout 0x%" PRIxLEAST64 " due to: %s",
740583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                             i, i + firstSet, reinterpret_cast<uint64_t &>(layout), errorString.c_str());
7406787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                    }
7407dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes
7408dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes                    auto setDynamicDescriptorCount = pSet->GetDynamicDescriptorCount();
7409dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes
7410dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes                    pCB->lastBound[pipelineBindPoint].dynamicOffsets[firstSet + i].clear();
7411dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes
7412dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes                    if (setDynamicDescriptorCount) {
7413787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                        // First make sure we won't overstep bounds of pDynamicOffsets array
7414dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes                        if ((totalDynamicDescriptors + setDynamicDescriptorCount) > dynamicOffsetCount) {
741583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            skip_call |=
7416787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7417787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                                        VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[i], __LINE__,
7418787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                                        DRAWSTATE_INVALID_DYNAMIC_OFFSET_COUNT, "DS",
7419414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                        "descriptorSet #%u (0x%" PRIxLEAST64
7420787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                                        ") requires %u dynamicOffsets, but only %u dynamicOffsets are left in pDynamicOffsets "
7421787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                                        "array. There must be one dynamic offset for each dynamic descriptor being bound.",
7422397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis                                        i, (uint64_t)pDescriptorSets[i], pSet->GetDynamicDescriptorCount(),
7423787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                                        (dynamicOffsetCount - totalDynamicDescriptors));
7424787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                        } else { // Validate and store dynamic offsets with the set
7425787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                            // Validate Dynamic Offset Minimums
7426787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                            uint32_t cur_dyn_offset = totalDynamicDescriptors;
7427397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis                            for (uint32_t d = 0; d < pSet->GetTotalDescriptorCount(); d++) {
7428397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis                                if (pSet->GetTypeFromGlobalIndex(d) == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) {
7429787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                                    if (vk_safe_modulo(
7430787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                                            pDynamicOffsets[cur_dyn_offset],
7431b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis                                            dev_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment) != 0) {
743283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                        skip_call |= log_msg(
7433787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                                            dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7434787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                                            VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__,
7435787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                                            DRAWSTATE_INVALID_UNIFORM_BUFFER_OFFSET, "DS",
7436787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                                            "vkCmdBindDescriptorSets(): pDynamicOffsets[%d] is %d but must be a multiple of "
7437414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                            "device limit minUniformBufferOffsetAlignment 0x%" PRIxLEAST64,
7438787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                                            cur_dyn_offset, pDynamicOffsets[cur_dyn_offset],
7439b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis                                            dev_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment);
7440787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                                    }
7441787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                                    cur_dyn_offset++;
7442397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis                                } else if (pSet->GetTypeFromGlobalIndex(d) == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) {
7443787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                                    if (vk_safe_modulo(
7444787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                                            pDynamicOffsets[cur_dyn_offset],
7445b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis                                            dev_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment) != 0) {
744683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                        skip_call |= log_msg(
7447787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                                            dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7448787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                                            VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__,
7449787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                                            DRAWSTATE_INVALID_STORAGE_BUFFER_OFFSET, "DS",
7450787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                                            "vkCmdBindDescriptorSets(): pDynamicOffsets[%d] is %d but must be a multiple of "
7451414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                            "device limit minStorageBufferOffsetAlignment 0x%" PRIxLEAST64,
7452787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                                            cur_dyn_offset, pDynamicOffsets[cur_dyn_offset],
7453b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis                                            dev_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment);
74545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                    }
7455787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                                    cur_dyn_offset++;
74565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                }
74575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            }
7458dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes
7459dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes                            pCB->lastBound[pipelineBindPoint].dynamicOffsets[firstSet + i] =
7460dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes                                std::vector<uint32_t>(pDynamicOffsets + totalDynamicDescriptors,
7461dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes                                                      pDynamicOffsets + totalDynamicDescriptors + setDynamicDescriptorCount);
7462787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                            // Keep running total of dynamic descriptor count to verify at the end
7463dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes                            totalDynamicDescriptors += setDynamicDescriptorCount;
7464dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes
74655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        }
74665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
7467787f29d93dee194c015789cf61c079504c980572Tobin Ehlis                } else {
746883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                    skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
746983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                         VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[i], __LINE__,
747083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                         DRAWSTATE_INVALID_SET, "DS", "Attempt to bind DS 0x%" PRIxLEAST64 " that doesn't exist!",
747183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                         (uint64_t)pDescriptorSets[i]);
74725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
747383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                skip_call |= addCmd(dev_data, pCB, CMD_BINDDESCRIPTORSETS, "vkCmdBindDescriptorSets()");
747472d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                // For any previously bound sets, need to set them to "invalid" if they were disturbed by this update
747572d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                if (firstSet > 0) { // Check set #s below the first bound set
747672d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                    for (uint32_t i = 0; i < firstSet; ++i) {
747772d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                        if (pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i] &&
747871511c5a10533c910bfe62c3bcf58e2a4054e7acTobin Ehlis                            !verify_set_layout_compatibility(dev_data, pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i],
747969b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis                                                             pipeline_layout, i, errorString)) {
748083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            skip_call |= log_msg(
748172d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                                dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
748272d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                                VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
748372d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                                (uint64_t)pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i], __LINE__, DRAWSTATE_NONE, "DS",
7484414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                "DescriptorSetDS 0x%" PRIxLEAST64
7485414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                " previously bound as set #%u was disturbed by newly bound pipelineLayout (0x%" PRIxLEAST64 ")",
748672d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                                (uint64_t)pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i], i, (uint64_t)layout);
748772d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                            pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i] = VK_NULL_HANDLE;
748872d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                        }
748972d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                    }
749072d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                }
749172d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                // Check if newly last bound set invalidates any remaining bound sets
749272d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                if ((pCB->lastBound[pipelineBindPoint].boundDescriptorSets.size() - 1) > (lastSetIndex)) {
749372d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                    if (oldFinalBoundSet &&
749469b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis                        !verify_set_layout_compatibility(dev_data, oldFinalBoundSet, pipeline_layout, lastSetIndex, errorString)) {
749571511c5a10533c910bfe62c3bcf58e2a4054e7acTobin Ehlis                        auto old_set = oldFinalBoundSet->GetSet();
749683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                        skip_call |=
749772d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                            log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
749871511c5a10533c910bfe62c3bcf58e2a4054e7acTobin Ehlis                                    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, reinterpret_cast<uint64_t &>(old_set), __LINE__,
7499414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                    DRAWSTATE_NONE, "DS", "DescriptorSetDS 0x%" PRIxLEAST64
7500414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                                          " previously bound as set #%u is incompatible with set 0x%" PRIxLEAST64
750172d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                                                          " newly bound as set #%u so set #%u and any subsequent sets were "
7502414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                                          "disturbed by newly bound pipelineLayout (0x%" PRIxLEAST64 ")",
750371511c5a10533c910bfe62c3bcf58e2a4054e7acTobin Ehlis                                    reinterpret_cast<uint64_t &>(old_set), lastSetIndex,
750472d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                                    (uint64_t)pCB->lastBound[pipelineBindPoint].boundDescriptorSets[lastSetIndex], lastSetIndex,
750572d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                                    lastSetIndex + 1, (uint64_t)layout);
750672d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                        pCB->lastBound[pipelineBindPoint].boundDescriptorSets.resize(lastSetIndex + 1);
75075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
75085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
75095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
7510787f29d93dee194c015789cf61c079504c980572Tobin Ehlis            //  dynamicOffsetCount must equal the total number of dynamic descriptors in the sets being bound
7511787f29d93dee194c015789cf61c079504c980572Tobin Ehlis            if (totalDynamicDescriptors != dynamicOffsetCount) {
751283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                skip_call |=
751383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
751483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            (uint64_t)commandBuffer, __LINE__, DRAWSTATE_INVALID_DYNAMIC_OFFSET_COUNT, "DS",
751583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            "Attempting to bind %u descriptorSets with %u dynamic descriptors, but dynamicOffsetCount "
751683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            "is %u. It should exactly match the number of dynamic descriptors.",
751783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            setCount, totalDynamicDescriptors, dynamicOffsetCount);
7518787f29d93dee194c015789cf61c079504c980572Tobin Ehlis            }
75195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
752083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdBindDescriptorSets()");
75215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
75225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7523b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
752483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
75254a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdBindDescriptorSets(commandBuffer, pipelineBindPoint, layout, firstSet, setCount,
75264a0754042cf090e131e9e769d8a3633c228625beChris Forbes                                                       pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
75275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
75285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
752989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
753089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType) {
753183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
75325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7533593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis    // TODO : Somewhere need to verify that IBs have correct usage state flagged
7534b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
7535b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski
7536ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    auto buff_node = getBufferNode(dev_data, buffer);
75379f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis    auto cb_node = getCBNode(dev_data, commandBuffer);
7538ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    if (cb_node && buff_node) {
7539b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, buff_node, "vkCmdBindIndexBuffer()");
7540ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        std::function<bool()> function = [=]() {
7541f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis            return ValidateBufferMemoryIsValid(dev_data, buff_node, "vkCmdBindIndexBuffer()");
7542ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        };
75439f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        cb_node->validate_functions.push_back(function);
754483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, cb_node, CMD_BINDINDEXBUFFER, "vkCmdBindIndexBuffer()");
75455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        VkDeviceSize offset_align = 0;
75465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        switch (indexType) {
75475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case VK_INDEX_TYPE_UINT16:
75485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            offset_align = 2;
75495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            break;
75505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        case VK_INDEX_TYPE_UINT32:
75515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            offset_align = 4;
75525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            break;
75535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        default:
75545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // ParamChecker should catch bad enum, we'll also throw alignment error below if offset_align stays 0
75555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            break;
75565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
75575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (!offset_align || (offset % offset_align)) {
755883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
755983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 DRAWSTATE_VTX_INDEX_ALIGNMENT_ERROR, "DS",
756083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 "vkCmdBindIndexBuffer() offset (0x%" PRIxLEAST64 ") does not fall on alignment (%s) boundary.",
756183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 offset, string_VkIndexType(indexType));
75625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
75639f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        cb_node->status |= CBSTATUS_INDEX_BUFFER_BOUND;
7564ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    } else {
7565ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        assert(0);
75665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7567b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
756883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
75694a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdBindIndexBuffer(commandBuffer, buffer, offset, indexType);
75705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
75715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
75725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisvoid updateResourceTracking(GLOBAL_CB_NODE *pCB, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer *pBuffers) {
75735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t end = firstBinding + bindingCount;
75745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB->currentDrawData.buffers.size() < end) {
75755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->currentDrawData.buffers.resize(end);
75765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
75775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < bindingCount; ++i) {
75785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->currentDrawData.buffers[i + firstBinding] = pBuffers[i];
75795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
75805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
75815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
7582e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic inline void updateResourceTrackingOnDraw(GLOBAL_CB_NODE *pCB) { pCB->drawData.push_back(pCB->currentDrawData); }
75835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
758489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdBindVertexBuffers(VkCommandBuffer commandBuffer, uint32_t firstBinding,
758589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                uint32_t bindingCount, const VkBuffer *pBuffers,
758689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                const VkDeviceSize *pOffsets) {
758783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
75885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7589593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis    // TODO : Somewhere need to verify that VBs have correct usage state flagged
7590b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
7591b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski
75929f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis    auto cb_node = getCBNode(dev_data, commandBuffer);
75939f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis    if (cb_node) {
7594593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        for (uint32_t i = 0; i < bindingCount; ++i) {
7595ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis            auto buff_node = getBufferNode(dev_data, pBuffers[i]);
7596ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis            assert(buff_node);
7597b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski            skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, buff_node, "vkCmdBindVertexBuffers()");
7598ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis            std::function<bool()> function = [=]() {
7599f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis                return ValidateBufferMemoryIsValid(dev_data, buff_node, "vkCmdBindVertexBuffers()");
7600ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis            };
76019f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis            cb_node->validate_functions.push_back(function);
76025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
76039f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        addCmd(dev_data, cb_node, CMD_BINDVERTEXBUFFER, "vkCmdBindVertexBuffer()");
76049f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        updateResourceTracking(cb_node, firstBinding, bindingCount, pBuffers);
76055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
760683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdBindVertexBuffer()");
76075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7608b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
760983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
76104a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdBindVertexBuffers(commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets);
76115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
76125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
7613b9e992386a44404152747d66817a733aa127e281Jeremy Hayes/* expects global_lock to be held by caller */
7614e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool markStoreImagesAndBuffersAsWritten(layer_data *dev_data, GLOBAL_CB_NODE *pCB) {
76155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    bool skip_call = false;
76167a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis
76177a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis    for (auto imageView : pCB->updateImages) {
761879fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis        auto view_state = getImageViewState(dev_data, imageView);
761979fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis        if (!view_state)
76205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            continue;
7621249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis
762279fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis        auto img_node = getImageNode(dev_data, view_state->create_info.image);
7623249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis        assert(img_node);
7624e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        std::function<bool()> function = [=]() {
7625f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis            SetImageMemoryValid(dev_data, img_node, true);
7626e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves            return false;
76277a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis        };
76287a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis        pCB->validate_functions.push_back(function);
76297a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis    }
76307a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis    for (auto buffer : pCB->updateBuffers) {
7631ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        auto buff_node = getBufferNode(dev_data, buffer);
7632ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        assert(buff_node);
7633e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        std::function<bool()> function = [=]() {
7634f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis            SetBufferMemoryValid(dev_data, buff_node, true);
7635e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves            return false;
76367a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis        };
76377a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis        pCB->validate_functions.push_back(function);
76385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
76395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return skip_call;
76405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
76415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
764289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
764389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                   uint32_t firstVertex, uint32_t firstInstance) {
764483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
76455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7646b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
76475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
76485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
764983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, pCB, CMD_DRAW, "vkCmdDraw()");
76505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->drawCount[DRAW]++;
7651e7f1fab24ce4b59bce87246a510b7e52638f83d0Mark Lobodzinski        skip_call |= validate_and_update_draw_state(dev_data, pCB, false, VK_PIPELINE_BIND_POINT_GRAPHICS, "vkCmdDraw");
765283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= markStoreImagesAndBuffersAsWritten(dev_data, pCB);
76535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // TODO : Need to pass commandBuffer as srcObj here
765483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |=
76555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
7656414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                    __LINE__, DRAWSTATE_NONE, "DS", "vkCmdDraw() call 0x%" PRIx64 ", reporting DS state:", g_drawCount[DRAW]++);
765783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= synchAndPrintDSConfig(dev_data, commandBuffer);
765883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        if (!skip_call) {
76595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            updateResourceTrackingOnDraw(pCB);
76605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
766183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= outsideRenderPass(dev_data, pCB, "vkCmdDraw");
76625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7663b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
766483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
76654a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
76665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
76675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
766889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount,
766989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                          uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset,
76705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                            uint32_t firstInstance) {
76715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
767283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
7673b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
76745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
76755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
767683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, pCB, CMD_DRAWINDEXED, "vkCmdDrawIndexed()");
76775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->drawCount[DRAW_INDEXED]++;
7678e7f1fab24ce4b59bce87246a510b7e52638f83d0Mark Lobodzinski        skip_call |= validate_and_update_draw_state(dev_data, pCB, true, VK_PIPELINE_BIND_POINT_GRAPHICS, "vkCmdDrawIndexed");
767983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= markStoreImagesAndBuffersAsWritten(dev_data, pCB);
76805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // TODO : Need to pass commandBuffer as srcObj here
768183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT,
768283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                             VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, DRAWSTATE_NONE, "DS",
768383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                             "vkCmdDrawIndexed() call 0x%" PRIx64 ", reporting DS state:", g_drawCount[DRAW_INDEXED]++);
768483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= synchAndPrintDSConfig(dev_data, commandBuffer);
768583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        if (!skip_call) {
76865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            updateResourceTrackingOnDraw(pCB);
76875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
768883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= outsideRenderPass(dev_data, pCB, "vkCmdDrawIndexed");
76895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7690b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
769183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
76924a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdDrawIndexed(commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
76935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
76945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
769589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
769689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride) {
76975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
769883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
7699b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
7700ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis
7701ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    auto cb_node = getCBNode(dev_data, commandBuffer);
7702ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    auto buff_node = getBufferNode(dev_data, buffer);
7703ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    if (cb_node && buff_node) {
7704b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, buff_node, "vkCmdDrawIndirect()");
7705c3eda058338f7ba4e776ec74202b1c95ce6e6220Tobin Ehlis        AddCommandBufferBindingBuffer(dev_data, cb_node, buff_node);
7706ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        skip_call |= addCmd(dev_data, cb_node, CMD_DRAWINDIRECT, "vkCmdDrawIndirect()");
7707ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        cb_node->drawCount[DRAW_INDIRECT]++;
7708e7f1fab24ce4b59bce87246a510b7e52638f83d0Mark Lobodzinski        skip_call |= validate_and_update_draw_state(dev_data, cb_node, false, VK_PIPELINE_BIND_POINT_GRAPHICS, "vkCmdDrawIndirect");
7709ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        skip_call |= markStoreImagesAndBuffersAsWritten(dev_data, cb_node);
77105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // TODO : Need to pass commandBuffer as srcObj here
771183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT,
771283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                             VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, DRAWSTATE_NONE, "DS",
771383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                             "vkCmdDrawIndirect() call 0x%" PRIx64 ", reporting DS state:", g_drawCount[DRAW_INDIRECT]++);
771483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= synchAndPrintDSConfig(dev_data, commandBuffer);
771583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        if (!skip_call) {
7716ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis            updateResourceTrackingOnDraw(cb_node);
77175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
7718b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= outsideRenderPass(dev_data, cb_node, "vkCmdDrawIndirect()");
7719ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    } else {
7720ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        assert(0);
77215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7722b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
772383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
77244a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdDrawIndirect(commandBuffer, buffer, offset, count, stride);
77255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
77265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
772789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
772889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride) {
772983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
77305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7731b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
7732ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis
7733ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    auto cb_node = getCBNode(dev_data, commandBuffer);
7734ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    auto buff_node = getBufferNode(dev_data, buffer);
7735ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    if (cb_node && buff_node) {
7736b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, buff_node, "vkCmdDrawIndexedIndirect()");
7737c3eda058338f7ba4e776ec74202b1c95ce6e6220Tobin Ehlis        AddCommandBufferBindingBuffer(dev_data, cb_node, buff_node);
7738ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        skip_call |= addCmd(dev_data, cb_node, CMD_DRAWINDEXEDINDIRECT, "vkCmdDrawIndexedIndirect()");
7739ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        cb_node->drawCount[DRAW_INDEXED_INDIRECT]++;
7740e7f1fab24ce4b59bce87246a510b7e52638f83d0Mark Lobodzinski        skip_call |=
7741e7f1fab24ce4b59bce87246a510b7e52638f83d0Mark Lobodzinski            validate_and_update_draw_state(dev_data, cb_node, true, VK_PIPELINE_BIND_POINT_GRAPHICS, "vkCmdDrawIndexedIndirect");
7742ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        skip_call |= markStoreImagesAndBuffersAsWritten(dev_data, cb_node);
77435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // TODO : Need to pass commandBuffer as srcObj here
774483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |=
77455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
7746414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                    __LINE__, DRAWSTATE_NONE, "DS", "vkCmdDrawIndexedIndirect() call 0x%" PRIx64 ", reporting DS state:",
77475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    g_drawCount[DRAW_INDEXED_INDIRECT]++);
774883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= synchAndPrintDSConfig(dev_data, commandBuffer);
774983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        if (!skip_call) {
7750ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis            updateResourceTrackingOnDraw(cb_node);
77515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
7752b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= outsideRenderPass(dev_data, cb_node, "vkCmdDrawIndexedIndirect()");
7753ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    } else {
7754ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        assert(0);
77555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7756b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
775783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
77584a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdDrawIndexedIndirect(commandBuffer, buffer, offset, count, stride);
77595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
77605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
776189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
776283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
77635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7764b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
77655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
77665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
7767e7f1fab24ce4b59bce87246a510b7e52638f83d0Mark Lobodzinski        skip_call |= validate_and_update_draw_state(dev_data, pCB, false, VK_PIPELINE_BIND_POINT_COMPUTE, "vkCmdDispatch");
776883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= markStoreImagesAndBuffersAsWritten(dev_data, pCB);
776983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, pCB, CMD_DISPATCH, "vkCmdDispatch()");
777083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= insideRenderPass(dev_data, pCB, "vkCmdDispatch");
77715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7772b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
777383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
77744a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdDispatch(commandBuffer, x, y, z);
77755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
77765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
777789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
777889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
777983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
77805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7781b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
7782ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis
7783ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    auto cb_node = getCBNode(dev_data, commandBuffer);
7784ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    auto buff_node = getBufferNode(dev_data, buffer);
7785b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski    if (cb_node && buff_node) {
7786b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, buff_node, "vkCmdDispatchIndirect()");
7787c3eda058338f7ba4e776ec74202b1c95ce6e6220Tobin Ehlis        AddCommandBufferBindingBuffer(dev_data, cb_node, buff_node);
7788e7f1fab24ce4b59bce87246a510b7e52638f83d0Mark Lobodzinski        skip_call |=
7789e7f1fab24ce4b59bce87246a510b7e52638f83d0Mark Lobodzinski            validate_and_update_draw_state(dev_data, cb_node, false, VK_PIPELINE_BIND_POINT_COMPUTE, "vkCmdDispatchIndirect");
7790ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        skip_call |= markStoreImagesAndBuffersAsWritten(dev_data, cb_node);
7791ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        skip_call |= addCmd(dev_data, cb_node, CMD_DISPATCHINDIRECT, "vkCmdDispatchIndirect()");
7792b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= insideRenderPass(dev_data, cb_node, "vkCmdDispatchIndirect()");
77935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7794b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
779583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
77964a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdDispatchIndirect(commandBuffer, buffer, offset);
77975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
77985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
779989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer,
780089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                         uint32_t regionCount, const VkBufferCopy *pRegions) {
780183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
78025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7803b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
7804ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis
78059f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis    auto cb_node = getCBNode(dev_data, commandBuffer);
7806ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    auto src_buff_node = getBufferNode(dev_data, srcBuffer);
7807ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    auto dst_buff_node = getBufferNode(dev_data, dstBuffer);
7808ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    if (cb_node && src_buff_node && dst_buff_node) {
7809b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, src_buff_node, "vkCmdCopyBuffer()");
7810b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_node, "vkCmdCopyBuffer()");
7811ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        // Update bindings between buffers and cmd buffer
7812c3eda058338f7ba4e776ec74202b1c95ce6e6220Tobin Ehlis        AddCommandBufferBindingBuffer(dev_data, cb_node, src_buff_node);
7813c3eda058338f7ba4e776ec74202b1c95ce6e6220Tobin Ehlis        AddCommandBufferBindingBuffer(dev_data, cb_node, dst_buff_node);
7814ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        // Validate that SRC & DST buffers have correct usage flags set
781559b0561b0bd298885f90b9f524c0583cd8ee6f61Tobin Ehlis        skip_call |= ValidateBufferUsageFlags(dev_data, src_buff_node, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, true, "vkCmdCopyBuffer()",
7816ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis                                              "VK_BUFFER_USAGE_TRANSFER_SRC_BIT");
781759b0561b0bd298885f90b9f524c0583cd8ee6f61Tobin Ehlis        skip_call |= ValidateBufferUsageFlags(dev_data, dst_buff_node, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, "vkCmdCopyBuffer()",
7818ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis                                              "VK_BUFFER_USAGE_TRANSFER_DST_BIT");
7819ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis
7820ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        std::function<bool()> function = [=]() {
7821f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis            return ValidateBufferMemoryIsValid(dev_data, src_buff_node, "vkCmdCopyBuffer()");
7822ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        };
78239f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        cb_node->validate_functions.push_back(function);
7824593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        function = [=]() {
7825f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis            SetBufferMemoryValid(dev_data, dst_buff_node, true);
7826e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves            return false;
78275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        };
78289f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        cb_node->validate_functions.push_back(function);
7829593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
783083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, cb_node, CMD_COPYBUFFER, "vkCmdCopyBuffer()");
7831b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= insideRenderPass(dev_data, cb_node, "vkCmdCopyBuffer()");
7832ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    } else {
7833ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        // Param_checker will flag errors on invalid objects, just assert here as debugging aid
7834ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        assert(0);
78355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7836b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
783783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
78384a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions);
78395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
78405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
784127e2917587adf1738c71851a128806f7de578cbeTobin Ehlisstatic bool VerifySourceImageLayout(layer_data *dev_data, GLOBAL_CB_NODE *cb_node, VkImage srcImage,
784227e2917587adf1738c71851a128806f7de578cbeTobin Ehlis                                    VkImageSubresourceLayers subLayers, VkImageLayout srcImageLayout) {
7843e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool skip_call = false;
78445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
78455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < subLayers.layerCount; ++i) {
78465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        uint32_t layer = i + subLayers.baseArrayLayer;
78475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        VkImageSubresource sub = {subLayers.aspectMask, subLayers.mipLevel, layer};
78485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        IMAGE_CMD_BUF_LAYOUT_NODE node;
784927e2917587adf1738c71851a128806f7de578cbeTobin Ehlis        if (!FindLayout(cb_node, srcImage, sub, node)) {
785027e2917587adf1738c71851a128806f7de578cbeTobin Ehlis            SetLayout(cb_node, srcImage, sub, IMAGE_CMD_BUF_LAYOUT_NODE(srcImageLayout, srcImageLayout));
78515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            continue;
78525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
78535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (node.layout != srcImageLayout) {
78545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // TODO: Improve log message in the next pass
78555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            skip_call |=
78565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
78575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", "Cannot copy from an image whose source layout is %s "
78585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                                        "and doesn't match the current layout %s.",
78595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        string_VkImageLayout(srcImageLayout), string_VkImageLayout(node.layout));
78605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
78615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
78625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (srcImageLayout != VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) {
78635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (srcImageLayout == VK_IMAGE_LAYOUT_GENERAL) {
786407b081bc51bf0151b7d2074967b948c02961c166Tobin Ehlis            // TODO : Can we deal with image node from the top of call tree and avoid map look-up here?
786507b081bc51bf0151b7d2074967b948c02961c166Tobin Ehlis            auto image_node = getImageNode(dev_data, srcImage);
786607b081bc51bf0151b7d2074967b948c02961c166Tobin Ehlis            if (image_node->createInfo.tiling != VK_IMAGE_TILING_LINEAR) {
786707b081bc51bf0151b7d2074967b948c02961c166Tobin Ehlis                // LAYOUT_GENERAL is allowed, but may not be performance optimal, flag as perf warning.
786807b081bc51bf0151b7d2074967b948c02961c166Tobin Ehlis                skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
786907b081bc51bf0151b7d2074967b948c02961c166Tobin Ehlis                                     (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
787007b081bc51bf0151b7d2074967b948c02961c166Tobin Ehlis                                     "Layout for input image should be TRANSFER_SRC_OPTIMAL instead of GENERAL.");
787107b081bc51bf0151b7d2074967b948c02961c166Tobin Ehlis            }
78725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
78735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
78745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                 DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", "Layout for input image is %s but can only be "
78755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                                       "TRANSFER_SRC_OPTIMAL or GENERAL.",
78765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                 string_VkImageLayout(srcImageLayout));
78775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
78785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
78795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return skip_call;
78805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
78815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
788227e2917587adf1738c71851a128806f7de578cbeTobin Ehlisstatic bool VerifyDestImageLayout(layer_data *dev_data, GLOBAL_CB_NODE *cb_node, VkImage destImage,
788327e2917587adf1738c71851a128806f7de578cbeTobin Ehlis                                  VkImageSubresourceLayers subLayers, VkImageLayout destImageLayout) {
7884e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool skip_call = false;
78855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
78865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < subLayers.layerCount; ++i) {
78875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        uint32_t layer = i + subLayers.baseArrayLayer;
78885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        VkImageSubresource sub = {subLayers.aspectMask, subLayers.mipLevel, layer};
78895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        IMAGE_CMD_BUF_LAYOUT_NODE node;
789027e2917587adf1738c71851a128806f7de578cbeTobin Ehlis        if (!FindLayout(cb_node, destImage, sub, node)) {
789127e2917587adf1738c71851a128806f7de578cbeTobin Ehlis            SetLayout(cb_node, destImage, sub, IMAGE_CMD_BUF_LAYOUT_NODE(destImageLayout, destImageLayout));
78925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            continue;
78935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
78945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (node.layout != destImageLayout) {
78955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            skip_call |=
78965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
78975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", "Cannot copy from an image whose dest layout is %s and "
78985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                                        "doesn't match the current layout %s.",
78995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        string_VkImageLayout(destImageLayout), string_VkImageLayout(node.layout));
79005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
79015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
79025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (destImageLayout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
79035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (destImageLayout == VK_IMAGE_LAYOUT_GENERAL) {
790407b081bc51bf0151b7d2074967b948c02961c166Tobin Ehlis            auto image_node = getImageNode(dev_data, destImage);
790507b081bc51bf0151b7d2074967b948c02961c166Tobin Ehlis            if (image_node->createInfo.tiling != VK_IMAGE_TILING_LINEAR) {
790607b081bc51bf0151b7d2074967b948c02961c166Tobin Ehlis                // LAYOUT_GENERAL is allowed, but may not be performance optimal, flag as perf warning.
790707b081bc51bf0151b7d2074967b948c02961c166Tobin Ehlis                skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
790807b081bc51bf0151b7d2074967b948c02961c166Tobin Ehlis                                     (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
790907b081bc51bf0151b7d2074967b948c02961c166Tobin Ehlis                                     "Layout for output image should be TRANSFER_DST_OPTIMAL instead of GENERAL.");
791007b081bc51bf0151b7d2074967b948c02961c166Tobin Ehlis            }
79115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
79125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
79135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                 DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", "Layout for output image is %s but can only be "
79145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                                       "TRANSFER_DST_OPTIMAL or GENERAL.",
79155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                 string_VkImageLayout(destImageLayout));
79165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
79175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
79185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return skip_call;
79195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
79205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
79219ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano// Test if two VkExtent3D structs are equivalent
79229ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitranostatic inline bool IsExtentEqual(const VkExtent3D *extent, const VkExtent3D *other_extent) {
79239ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    bool result = true;
79249ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    if ((extent->width != other_extent->width) || (extent->height != other_extent->height) ||
79259ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano        (extent->depth != other_extent->depth)) {
79269ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano        result = false;
79279ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    }
79289ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    return result;
79299ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano}
79309ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano
79319ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano// Returns the image extent of a specific subresource.
79329ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitranostatic inline VkExtent3D GetImageSubresourceExtent(const IMAGE_NODE *img, const VkImageSubresourceLayers *subresource) {
79339ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    const uint32_t mip = subresource->mipLevel;
79349ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    VkExtent3D extent = img->createInfo.extent;
793590b7c8c094c263b33382ff4756f2a23f484e8400Gregory Mitrano    extent.width = std::max(1U, extent.width >> mip);
793690b7c8c094c263b33382ff4756f2a23f484e8400Gregory Mitrano    extent.height = std::max(1U, extent.height >> mip);
793790b7c8c094c263b33382ff4756f2a23f484e8400Gregory Mitrano    extent.depth = std::max(1U, extent.depth >> mip);
79389ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    return extent;
79399ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano}
79409ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano
79419ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano// Test if the extent argument has all dimensions set to 0.
79429ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitranostatic inline bool IsExtentZero(const VkExtent3D *extent) {
79439ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    return ((extent->width == 0) && (extent->height == 0) && (extent->depth == 0));
79449ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano}
79459ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano
79469ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano// Returns the image transfer granularity for a specific image scaled by compressed block size if necessary.
79479ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitranostatic inline VkExtent3D GetScaledItg(layer_data *dev_data, const GLOBAL_CB_NODE *cb_node, const IMAGE_NODE *img) {
79489ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    // Default to (0, 0, 0) granularity in case we can't find the real granularity for the physical device.
79499ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    VkExtent3D granularity = { 0, 0, 0 };
7950f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski    auto pPool = getCommandPoolNode(dev_data, cb_node->createInfo.commandPool);
7951f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski    if (pPool) {
79529ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano        granularity = dev_data->phys_dev_properties.queue_family_properties[pPool->queueFamilyIndex].minImageTransferGranularity;
79539ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano        if (vk_format_is_compressed(img->createInfo.format)) {
79549ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano            auto block_size = vk_format_compressed_block_size(img->createInfo.format);
79559ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano            granularity.width *= block_size.width;
79569ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano            granularity.height *= block_size.height;
7957f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski        }
7958f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski    }
79599ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    return granularity;
79609ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano}
79619ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano
79629ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano// Test elements of a VkExtent3D structure against alignment constraints contained in another VkExtent3D structure
79639ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitranostatic inline bool IsExtentAligned(const VkExtent3D *extent, const VkExtent3D *granularity) {
79649ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    bool valid = true;
79659ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    if ((vk_safe_modulo(extent->depth, granularity->depth) != 0) || (vk_safe_modulo(extent->width, granularity->width) != 0) ||
79669ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano        (vk_safe_modulo(extent->height, granularity->height) != 0)) {
79679ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano        valid = false;
79689ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    }
7969f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski    return valid;
7970f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski}
7971f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski
7972f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski// Check elements of a VkOffset3D structure against a queue family's Image Transfer Granularity values
79739ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitranostatic inline bool CheckItgOffset(layer_data *dev_data, const GLOBAL_CB_NODE *cb_node, const VkOffset3D *offset,
79749ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                                  const VkExtent3D *granularity, const uint32_t i, const char *function, const char *member) {
7975f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski    bool skip = false;
79769ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    VkExtent3D offset_extent = {};
79779ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    offset_extent.width = static_cast<uint32_t>(abs(offset->x));
79789ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    offset_extent.height = static_cast<uint32_t>(abs(offset->y));
79799ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    offset_extent.depth = static_cast<uint32_t>(abs(offset->z));
79809ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    if (IsExtentZero(granularity)) {
79819ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano        // If the queue family image transfer granularity is (0, 0, 0), then the offset must always be (0, 0, 0)
79829ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano        if (IsExtentZero(&offset_extent) == false) {
79839ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
79849ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                            DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS",
79859ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                            "%s: pRegion[%d].%s (x=%d, y=%d, z=%d) must be (x=0, y=0, z=0) "
79869ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                            "when the command buffer's queue family image transfer granularity is (w=0, h=0, d=0).",
79879ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                            function, i, member, offset->x, offset->y, offset->z);
79889ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano        }
79899ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    } else {
79909ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano        // If the queue family image transfer granularity is not (0, 0, 0), then the offset dimensions must always be even
79919ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano        // integer multiples of the image transfer granularity.
79929ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano        if (IsExtentAligned(&offset_extent, granularity) == false) {
79939ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
79949ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                            DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS",
79959ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                            "%s: pRegion[%d].%s (x=%d, y=%d, z=%d) dimensions must be even integer "
79969ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                            "multiples of this command buffer's queue family image transfer granularity (w=%d, h=%d, d=%d).",
79979ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                            function, i, member, offset->x, offset->y, offset->z, granularity->width, granularity->height,
79989ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                            granularity->depth);
79999ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano        }
8000f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski    }
8001f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski    return skip;
8002f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski}
8003f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski
8004f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski// Check elements of a VkExtent3D structure against a queue family's Image Transfer Granularity values
80059ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitranostatic inline bool CheckItgExtent(layer_data *dev_data, const GLOBAL_CB_NODE *cb_node, const VkExtent3D *extent,
80069ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                                  const VkOffset3D *offset, const VkExtent3D *granularity, const VkExtent3D *subresource_extent,
80079ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                                  const uint32_t i, const char *function, const char *member) {
8008f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski    bool skip = false;
80099ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    if (IsExtentZero(granularity)) {
80109ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano        // If the queue family image transfer granularity is (0, 0, 0), then the extent must always match the image
80119ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano        // subresource extent.
80129ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano        if (IsExtentEqual(extent, subresource_extent) == false) {
80139ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
80149ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                            DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS",
80159ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                            "%s: pRegion[%d].%s (w=%d, h=%d, d=%d) must match the image subresource extents (w=%d, h=%d, d=%d) "
80169ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                            "when the command buffer's queue family image transfer granularity is (w=0, h=0, d=0).",
80179ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                            function, i, member, extent->width, extent->height, extent->depth, subresource_extent->width,
80189ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                            subresource_extent->height, subresource_extent->depth);
80199ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano        }
80209ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    } else {
80219ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano        // If the queue family image transfer granularity is not (0, 0, 0), then the extent dimensions must always be even
80229ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano        // integer multiples of the image transfer granularity or the offset + extent dimensions must always match the image
80239ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano        // subresource extent dimensions.
80249ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano        VkExtent3D offset_extent_sum = {};
80259ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano        offset_extent_sum.width = static_cast<uint32_t>(abs(offset->x)) + extent->width;
80269ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano        offset_extent_sum.height = static_cast<uint32_t>(abs(offset->y)) + extent->height;
80279ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano        offset_extent_sum.depth = static_cast<uint32_t>(abs(offset->z)) + extent->depth;
80289ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano        if ((IsExtentAligned(extent, granularity) == false) && (IsExtentEqual(&offset_extent_sum, subresource_extent) == false)) {
80299ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano            skip |=
80309ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
8031f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski                        DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS",
80329ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                        "%s: pRegion[%d].%s (w=%d, h=%d, d=%d) dimensions must be even integer multiples of this command buffer's "
80339ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                        "queue family image transfer granularity (w=%d, h=%d, d=%d) or offset (x=%d, y=%d, z=%d) + "
80349ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                        "extent (w=%d, h=%d, d=%d) must match the image subresource extents (w=%d, h=%d, d=%d).",
80359ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                        function, i, member, extent->width, extent->height, extent->depth, granularity->width, granularity->height,
80369ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                        granularity->depth, offset->x, offset->y, offset->z, extent->width, extent->height, extent->depth,
80379ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                        subresource_extent->width, subresource_extent->height, subresource_extent->depth);
80389ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano        }
8039f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski    }
8040f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski    return skip;
8041f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski}
8042f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski
8043f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski// Check a uint32_t width or stride value against a queue family's Image Transfer Granularity width value
80449ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitranostatic inline bool CheckItgInt(layer_data *dev_data, const GLOBAL_CB_NODE *cb_node, const uint32_t value,
80459ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                               const uint32_t granularity, const uint32_t i, const char *function, const char *member) {
8046f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski    bool skip = false;
80479ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    if (vk_safe_modulo(value, granularity) != 0) {
8048f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
8049f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski                        DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS",
80509ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                        "%s: pRegion[%d].%s (%d) must be an even integer multiple of this command buffer's queue family image "
80519ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                        "transfer granularity width (%d).",
80529ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                        function, i, member, value, granularity);
8053f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski    }
8054f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski    return skip;
8055f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski}
8056f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski
8057f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski// Check a VkDeviceSize value against a queue family's Image Transfer Granularity width value
80589ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitranostatic inline bool CheckItgSize(layer_data *dev_data, const GLOBAL_CB_NODE *cb_node, const VkDeviceSize value,
80599ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                                const uint32_t granularity, const uint32_t i, const char *function, const char *member) {
8060f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski    bool skip = false;
80619ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    if (vk_safe_modulo(value, granularity) != 0) {
80629ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
80639ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                        DRAWSTATE_IMAGE_TRANSFER_GRANULARITY, "DS",
80649ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                        "%s: pRegion[%d].%s (%" PRIdLEAST64
80659ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                        ") must be an even integer multiple of this command buffer's queue family image transfer "
80669ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                        "granularity width (%d).",
80679ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                        function, i, member, value, granularity);
8068f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski    }
8069f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski    return skip;
8070f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski}
8071f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski
8072f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski// Check valid usage Image Tranfer Granularity requirements for elements of a VkImageCopy structure
8073f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinskistatic inline bool ValidateCopyImageTransferGranularityRequirements(layer_data *dev_data, const GLOBAL_CB_NODE *cb_node,
80749ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                                                                    const IMAGE_NODE *img, const VkImageCopy *region,
80759ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                                                                    const uint32_t i, const char *function) {
8076f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski    bool skip = false;
80779ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    VkExtent3D granularity = GetScaledItg(dev_data, cb_node, img);
80789ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    skip |= CheckItgOffset(dev_data, cb_node, &region->srcOffset, &granularity, i, function, "srcOffset");
80799ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    skip |= CheckItgOffset(dev_data, cb_node, &region->dstOffset, &granularity, i, function, "dstOffset");
80809ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    VkExtent3D subresource_extent = GetImageSubresourceExtent(img, &region->dstSubresource);
80819ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    skip |= CheckItgExtent(dev_data, cb_node, &region->extent, &region->dstOffset, &granularity, &subresource_extent, i, function,
80829ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                           "extent");
8083f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski    return skip;
8084f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski}
8085f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski
8086f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski// Check valid usage Image Tranfer Granularity requirements for elements of a VkBufferImageCopy structure
8087f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinskistatic inline bool ValidateCopyBufferImageTransferGranularityRequirements(layer_data *dev_data, const GLOBAL_CB_NODE *cb_node,
80889ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                                                                          const IMAGE_NODE *img, const VkBufferImageCopy *region,
80899ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                                                                          const uint32_t i, const char *function) {
8090f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski    bool skip = false;
80919ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    VkExtent3D granularity = GetScaledItg(dev_data, cb_node, img);
80929ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    skip |= CheckItgSize(dev_data, cb_node, region->bufferOffset, granularity.width, i, function, "bufferOffset");
80939ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    skip |= CheckItgInt(dev_data, cb_node, region->bufferRowLength, granularity.width, i, function, "bufferRowLength");
80949ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    skip |= CheckItgInt(dev_data, cb_node, region->bufferImageHeight, granularity.width, i, function, "bufferImageHeight");
80959ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    skip |= CheckItgOffset(dev_data, cb_node, &region->imageOffset, &granularity, i, function, "imageOffset");
80969ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    VkExtent3D subresource_extent = GetImageSubresourceExtent(img, &region->imageSubresource);
80979ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano    skip |= CheckItgExtent(dev_data, cb_node, &region->imageExtent, &region->imageOffset, &granularity, &subresource_extent, i,
80989ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                           function, "imageExtent");
8099f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski    return skip;
8100f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski}
8101f7f74f870488f026061dec2d4d3c3329a25d4dcdMark Lobodzinski
810289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
810389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
810489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu             VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy *pRegions) {
810583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
81065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
8107b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
8108249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis
81099f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis    auto cb_node = getCBNode(dev_data, commandBuffer);
8110249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis    auto src_img_node = getImageNode(dev_data, srcImage);
8111249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis    auto dst_img_node = getImageNode(dev_data, dstImage);
8112249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis    if (cb_node && src_img_node && dst_img_node) {
8113b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= ValidateMemoryIsBoundToImage(dev_data, src_img_node, "vkCmdCopyImage()");
8114b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= ValidateMemoryIsBoundToImage(dev_data, dst_img_node, "vkCmdCopyImage()");
8115249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis        // Update bindings between images and cmd buffer
8116c3eda058338f7ba4e776ec74202b1c95ce6e6220Tobin Ehlis        AddCommandBufferBindingImage(dev_data, cb_node, src_img_node);
8117c3eda058338f7ba4e776ec74202b1c95ce6e6220Tobin Ehlis        AddCommandBufferBindingImage(dev_data, cb_node, dst_img_node);
8118249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis        // Validate that SRC & DST images have correct usage flags set
811959b0561b0bd298885f90b9f524c0583cd8ee6f61Tobin Ehlis        skip_call |= ValidateImageUsageFlags(dev_data, src_img_node, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, true, "vkCmdCopyImage()",
8120ff97b06aed7555ae043b3920bdfbd36b31498d89Tobin Ehlis                                             "VK_IMAGE_USAGE_TRANSFER_SRC_BIT");
812159b0561b0bd298885f90b9f524c0583cd8ee6f61Tobin Ehlis        skip_call |= ValidateImageUsageFlags(dev_data, dst_img_node, VK_IMAGE_USAGE_TRANSFER_DST_BIT, true, "vkCmdCopyImage()",
8122ff97b06aed7555ae043b3920bdfbd36b31498d89Tobin Ehlis                                             "VK_IMAGE_USAGE_TRANSFER_DST_BIT");
8123f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis        std::function<bool()> function = [=]() { return ValidateImageMemoryIsValid(dev_data, src_img_node, "vkCmdCopyImage()"); };
81249f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        cb_node->validate_functions.push_back(function);
8125593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        function = [=]() {
8126f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis            SetImageMemoryValid(dev_data, dst_img_node, true);
8127e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves            return false;
81285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        };
81299f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        cb_node->validate_functions.push_back(function);
8130593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
813183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, cb_node, CMD_COPYIMAGE, "vkCmdCopyImage()");
8132b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= insideRenderPass(dev_data, cb_node, "vkCmdCopyImage()");
81335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t i = 0; i < regionCount; ++i) {
813427e2917587adf1738c71851a128806f7de578cbeTobin Ehlis            skip_call |= VerifySourceImageLayout(dev_data, cb_node, srcImage, pRegions[i].srcSubresource, srcImageLayout);
813527e2917587adf1738c71851a128806f7de578cbeTobin Ehlis            skip_call |= VerifyDestImageLayout(dev_data, cb_node, dstImage, pRegions[i].dstSubresource, dstImageLayout);
81369ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano            skip_call |= ValidateCopyImageTransferGranularityRequirements(dev_data, cb_node, dst_img_node, &pRegions[i], i,
81379ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                                                                          "vkCmdCopyImage()");
81385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
8139249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis    } else {
8140249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis        assert(0);
81415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8142b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
814383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
81444a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdCopyImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount,
81454a0754042cf090e131e9e769d8a3633c228625beChris Forbes                                              pRegions);
81465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
81475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8148eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski// Validate that an image's sampleCount matches the requirement for a specific API call
8149eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinskistatic inline bool ValidateImageSampleCount(layer_data *dev_data, IMAGE_NODE *image_node, VkSampleCountFlagBits sample_count,
8150eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski                                            const char *location) {
8151eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski    bool skip = false;
8152eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski    if (image_node->createInfo.samples != sample_count) {
8153eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski        skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
8154eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski                       reinterpret_cast<uint64_t &>(image_node->image), 0, DRAWSTATE_NUM_SAMPLES_MISMATCH, "DS",
8155eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski                       "%s for image 0x%" PRIxLEAST64 " was created with a sample count of %s but must be %s.", location,
8156eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski                       reinterpret_cast<uint64_t &>(image_node->image),
8157eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski                       string_VkSampleCountFlagBits(image_node->createInfo.samples), string_VkSampleCountFlagBits(sample_count));
8158eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski    }
8159eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski    return skip;
8160eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski}
8161eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski
816289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
816389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
816489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu             VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit *pRegions, VkFilter filter) {
816583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
81665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
8167b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
8168593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
81699f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis    auto cb_node = getCBNode(dev_data, commandBuffer);
8170249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis    auto src_img_node = getImageNode(dev_data, srcImage);
8171249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis    auto dst_img_node = getImageNode(dev_data, dstImage);
8172249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis    if (cb_node && src_img_node && dst_img_node) {
8173eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski        skip_call |= ValidateImageSampleCount(dev_data, src_img_node, VK_SAMPLE_COUNT_1_BIT, "vkCmdBlitImage(): srcImage");
8174eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski        skip_call |= ValidateImageSampleCount(dev_data, dst_img_node, VK_SAMPLE_COUNT_1_BIT, "vkCmdBlitImage(): dstImage");
8175b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= ValidateMemoryIsBoundToImage(dev_data, src_img_node, "vkCmdBlitImage()");
8176b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= ValidateMemoryIsBoundToImage(dev_data, dst_img_node, "vkCmdBlitImage()");
8177249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis        // Update bindings between images and cmd buffer
8178c3eda058338f7ba4e776ec74202b1c95ce6e6220Tobin Ehlis        AddCommandBufferBindingImage(dev_data, cb_node, src_img_node);
8179c3eda058338f7ba4e776ec74202b1c95ce6e6220Tobin Ehlis        AddCommandBufferBindingImage(dev_data, cb_node, dst_img_node);
8180249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis        // Validate that SRC & DST images have correct usage flags set
818159b0561b0bd298885f90b9f524c0583cd8ee6f61Tobin Ehlis        skip_call |= ValidateImageUsageFlags(dev_data, src_img_node, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, true, "vkCmdBlitImage()",
8182ff97b06aed7555ae043b3920bdfbd36b31498d89Tobin Ehlis                                             "VK_IMAGE_USAGE_TRANSFER_SRC_BIT");
818359b0561b0bd298885f90b9f524c0583cd8ee6f61Tobin Ehlis        skip_call |= ValidateImageUsageFlags(dev_data, dst_img_node, VK_IMAGE_USAGE_TRANSFER_DST_BIT, true, "vkCmdBlitImage()",
8184ff97b06aed7555ae043b3920bdfbd36b31498d89Tobin Ehlis                                             "VK_IMAGE_USAGE_TRANSFER_DST_BIT");
8185f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis        std::function<bool()> function = [=]() { return ValidateImageMemoryIsValid(dev_data, src_img_node, "vkCmdBlitImage()"); };
81869f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        cb_node->validate_functions.push_back(function);
8187593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        function = [=]() {
8188f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis            SetImageMemoryValid(dev_data, dst_img_node, true);
8189e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves            return false;
81905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        };
81919f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        cb_node->validate_functions.push_back(function);
8192593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
819383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, cb_node, CMD_BLITIMAGE, "vkCmdBlitImage()");
8194b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= insideRenderPass(dev_data, cb_node, "vkCmdBlitImage()");
8195249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis    } else {
8196249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis        assert(0);
81975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8198b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
819983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
82004a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdBlitImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount,
82014a0754042cf090e131e9e769d8a3633c228625beChris Forbes                                              pRegions, filter);
82025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
82035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
820489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer,
820589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                VkImage dstImage, VkImageLayout dstImageLayout,
820689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                uint32_t regionCount, const VkBufferImageCopy *pRegions) {
820783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
82085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
8209b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
8210593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
82119f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis    auto cb_node = getCBNode(dev_data, commandBuffer);
8212ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    auto src_buff_node = getBufferNode(dev_data, srcBuffer);
8213249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis    auto dst_img_node = getImageNode(dev_data, dstImage);
8214249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis    if (cb_node && src_buff_node && dst_img_node) {
8215eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski        skip_call |= ValidateImageSampleCount(dev_data, dst_img_node, VK_SAMPLE_COUNT_1_BIT, "vkCmdCopyBufferToImage(): dstImage");
8216b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, src_buff_node, "vkCmdCopyBufferToImage()");
8217b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= ValidateMemoryIsBoundToImage(dev_data, dst_img_node, "vkCmdCopyBufferToImage()");
8218c3eda058338f7ba4e776ec74202b1c95ce6e6220Tobin Ehlis        AddCommandBufferBindingBuffer(dev_data, cb_node, src_buff_node);
8219c3eda058338f7ba4e776ec74202b1c95ce6e6220Tobin Ehlis        AddCommandBufferBindingImage(dev_data, cb_node, dst_img_node);
822059b0561b0bd298885f90b9f524c0583cd8ee6f61Tobin Ehlis        skip_call |= ValidateBufferUsageFlags(dev_data, src_buff_node, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, true,
8221ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis                                              "vkCmdCopyBufferToImage()", "VK_BUFFER_USAGE_TRANSFER_SRC_BIT");
822259b0561b0bd298885f90b9f524c0583cd8ee6f61Tobin Ehlis        skip_call |= ValidateImageUsageFlags(dev_data, dst_img_node, VK_IMAGE_USAGE_TRANSFER_DST_BIT, true,
8223ff97b06aed7555ae043b3920bdfbd36b31498d89Tobin Ehlis                                             "vkCmdCopyBufferToImage()", "VK_IMAGE_USAGE_TRANSFER_DST_BIT");
8224e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        std::function<bool()> function = [=]() {
8225f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis            SetImageMemoryValid(dev_data, dst_img_node, true);
8226e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves            return false;
82275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        };
82289f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        cb_node->validate_functions.push_back(function);
8229f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis        function = [=]() { return ValidateBufferMemoryIsValid(dev_data, src_buff_node, "vkCmdCopyBufferToImage()"); };
82309f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        cb_node->validate_functions.push_back(function);
8231593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
823283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, cb_node, CMD_COPYBUFFERTOIMAGE, "vkCmdCopyBufferToImage()");
8233b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= insideRenderPass(dev_data, cb_node, "vkCmdCopyBufferToImage()");
82345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t i = 0; i < regionCount; ++i) {
823527e2917587adf1738c71851a128806f7de578cbeTobin Ehlis            skip_call |= VerifyDestImageLayout(dev_data, cb_node, dstImage, pRegions[i].imageSubresource, dstImageLayout);
82369ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano            skip_call |= ValidateCopyBufferImageTransferGranularityRequirements(dev_data, cb_node, dst_img_node, &pRegions[i], i,
82379ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                                                                                "vkCmdCopyBufferToImage()");
82385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
8239ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    } else {
8240ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        assert(0);
82415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8242b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
824383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
82444a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions);
82455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
82465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
824789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage,
824889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                VkImageLayout srcImageLayout, VkBuffer dstBuffer,
824989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                uint32_t regionCount, const VkBufferImageCopy *pRegions) {
825083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
82515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
8252b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
8253593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
82549f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis    auto cb_node = getCBNode(dev_data, commandBuffer);
8255249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis    auto src_img_node = getImageNode(dev_data, srcImage);
8256ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    auto dst_buff_node = getBufferNode(dev_data, dstBuffer);
8257249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis    if (cb_node && src_img_node && dst_buff_node) {
8258eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski        skip_call |= ValidateImageSampleCount(dev_data, src_img_node, VK_SAMPLE_COUNT_1_BIT, "vkCmdCopyImageToBuffer(): srcImage");
8259b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= ValidateMemoryIsBoundToImage(dev_data, src_img_node, "vkCmdCopyImageToBuffer()");
8260b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_node, "vkCmdCopyImageToBuffer()");
8261249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis        // Update bindings between buffer/image and cmd buffer
8262c3eda058338f7ba4e776ec74202b1c95ce6e6220Tobin Ehlis        AddCommandBufferBindingImage(dev_data, cb_node, src_img_node);
8263c3eda058338f7ba4e776ec74202b1c95ce6e6220Tobin Ehlis        AddCommandBufferBindingBuffer(dev_data, cb_node, dst_buff_node);
8264249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis        // Validate that SRC image & DST buffer have correct usage flags set
826559b0561b0bd298885f90b9f524c0583cd8ee6f61Tobin Ehlis        skip_call |= ValidateImageUsageFlags(dev_data, src_img_node, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, true,
8266ff97b06aed7555ae043b3920bdfbd36b31498d89Tobin Ehlis                                             "vkCmdCopyImageToBuffer()", "VK_IMAGE_USAGE_TRANSFER_SRC_BIT");
826759b0561b0bd298885f90b9f524c0583cd8ee6f61Tobin Ehlis        skip_call |= ValidateBufferUsageFlags(dev_data, dst_buff_node, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true,
8268ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis                                              "vkCmdCopyImageToBuffer()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT");
8269e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        std::function<bool()> function = [=]() {
8270f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis            return ValidateImageMemoryIsValid(dev_data, src_img_node, "vkCmdCopyImageToBuffer()");
8271e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        };
82729f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        cb_node->validate_functions.push_back(function);
8273593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        function = [=]() {
8274f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis            SetBufferMemoryValid(dev_data, dst_buff_node, true);
8275e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves            return false;
82765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        };
82779f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        cb_node->validate_functions.push_back(function);
8278593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
827983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, cb_node, CMD_COPYIMAGETOBUFFER, "vkCmdCopyImageToBuffer()");
8280b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= insideRenderPass(dev_data, cb_node, "vkCmdCopyImageToBuffer()");
82815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t i = 0; i < regionCount; ++i) {
828227e2917587adf1738c71851a128806f7de578cbeTobin Ehlis            skip_call |= VerifySourceImageLayout(dev_data, cb_node, srcImage, pRegions[i].imageSubresource, srcImageLayout);
82839ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano            skip_call |= ValidateCopyBufferImageTransferGranularityRequirements(dev_data, cb_node, src_img_node, &pRegions[i], i,
82849ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano                                                                                "CmdCopyImageToBuffer");
82855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
8286ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    } else {
8287ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        assert(0);
82885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8289b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
829083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
82914a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdCopyImageToBuffer(commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount, pRegions);
82925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
82935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
829489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer,
829589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                           VkDeviceSize dstOffset, VkDeviceSize dataSize, const uint32_t *pData) {
829683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
82975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
8298b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
8299593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
83009f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis    auto cb_node = getCBNode(dev_data, commandBuffer);
8301ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    auto dst_buff_node = getBufferNode(dev_data, dstBuffer);
8302ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    if (cb_node && dst_buff_node) {
8303b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_node, "vkCmdUpdateBuffer()");
8304ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        // Update bindings between buffer and cmd buffer
8305c3eda058338f7ba4e776ec74202b1c95ce6e6220Tobin Ehlis        AddCommandBufferBindingBuffer(dev_data, cb_node, dst_buff_node);
8306ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        // Validate that DST buffer has correct usage flags set
830759b0561b0bd298885f90b9f524c0583cd8ee6f61Tobin Ehlis        skip_call |= ValidateBufferUsageFlags(dev_data, dst_buff_node, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true,
8308ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis                                              "vkCmdUpdateBuffer()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT");
8309e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        std::function<bool()> function = [=]() {
8310f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis            SetBufferMemoryValid(dev_data, dst_buff_node, true);
8311e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves            return false;
83125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        };
83139f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        cb_node->validate_functions.push_back(function);
8314593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
831583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, cb_node, CMD_UPDATEBUFFER, "vkCmdUpdateBuffer()");
8316b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= insideRenderPass(dev_data, cb_node, "vkCmdCopyUpdateBuffer()");
8317ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    } else {
8318ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        assert(0);
83195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8320b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
832183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
83224a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdUpdateBuffer(commandBuffer, dstBuffer, dstOffset, dataSize, pData);
83235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
83245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
832589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
832689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data) {
832783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
83285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
8329b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
8330593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
83319f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis    auto cb_node = getCBNode(dev_data, commandBuffer);
8332ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    auto dst_buff_node = getBufferNode(dev_data, dstBuffer);
8333ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    if (cb_node && dst_buff_node) {
8334b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_node, "vkCmdFillBuffer()");
8335ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        // Update bindings between buffer and cmd buffer
8336c3eda058338f7ba4e776ec74202b1c95ce6e6220Tobin Ehlis        AddCommandBufferBindingBuffer(dev_data, cb_node, dst_buff_node);
8337ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        // Validate that DST buffer has correct usage flags set
833859b0561b0bd298885f90b9f524c0583cd8ee6f61Tobin Ehlis        skip_call |= ValidateBufferUsageFlags(dev_data, dst_buff_node, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, "vkCmdFillBuffer()",
8339ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis                                              "VK_BUFFER_USAGE_TRANSFER_DST_BIT");
8340e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        std::function<bool()> function = [=]() {
8341f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis            SetBufferMemoryValid(dev_data, dst_buff_node, true);
8342e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves            return false;
83435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        };
83449f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        cb_node->validate_functions.push_back(function);
8345593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
834683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, cb_node, CMD_FILLBUFFER, "vkCmdFillBuffer()");
8347b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= insideRenderPass(dev_data, cb_node, "vkCmdCopyFillBuffer()");
8348ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    } else {
8349ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        assert(0);
83505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8351b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
835283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
83534a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdFillBuffer(commandBuffer, dstBuffer, dstOffset, size, data);
83545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
83555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
835689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount,
835789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                               const VkClearAttachment *pAttachments, uint32_t rectCount,
835889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                               const VkClearRect *pRects) {
835983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
83605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
8361b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
83625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
83635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
836483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, pCB, CMD_CLEARATTACHMENTS, "vkCmdClearAttachments()");
83655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Warn if this is issued prior to Draw Cmd and clearing the entire attachment
83665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (!hasDrawCmd(pCB) && (pCB->activeRenderPassBeginInfo.renderArea.extent.width == pRects[0].rect.extent.width) &&
83675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            (pCB->activeRenderPassBeginInfo.renderArea.extent.height == pRects[0].rect.extent.height)) {
83685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // There are times where app needs to use ClearAttachments (generally when reusing a buffer inside of a render pass)
83695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // Can we make this warning more specific? I'd like to avoid triggering this test if we can tell it's a use that must
83705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // call CmdClearAttachments
83715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // Otherwise this seems more like a performance warning.
837283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
8373a1a137ec383fef3881f86d4c202b1de56a91edf0Chris Forbes                                 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(commandBuffer),
8374a1a137ec383fef3881f86d4c202b1de56a91edf0Chris Forbes                                 0, DRAWSTATE_CLEAR_CMD_BEFORE_DRAW, "DS",
837583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 "vkCmdClearAttachments() issued on CB object 0x%" PRIxLEAST64 " prior to any Draw Cmds."
837683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 " It is recommended you use RenderPass LOAD_OP_CLEAR on Attachments prior to any Draw.",
837783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                 (uint64_t)(commandBuffer));
83785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
8379b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= outsideRenderPass(dev_data, pCB, "vkCmdClearAttachments()");
83805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
83815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
83825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Validate that attachment is in reference list of active subpass
83835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB->activeRenderPass) {
8384fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes        const VkRenderPassCreateInfo *pRPCI = pCB->activeRenderPass->createInfo.ptr();
83855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        const VkSubpassDescription *pSD = &pRPCI->pSubpasses[pCB->activeSubpass];
83865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
83875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t attachment_idx = 0; attachment_idx < attachmentCount; attachment_idx++) {
83885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            const VkClearAttachment *attachment = &pAttachments[attachment_idx];
83895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (attachment->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
83901710af939cd452f3c02e93f598f20e5e12eb6c3bChris Forbes                if (attachment->colorAttachment >= pSD->colorAttachmentCount) {
839183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                    skip_call |= log_msg(
839221a714edaf9b670a60102430c36b221ff27f0f25Chris Forbes                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
83935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        (uint64_t)commandBuffer, __LINE__, DRAWSTATE_MISSING_ATTACHMENT_REFERENCE, "DS",
83941710af939cd452f3c02e93f598f20e5e12eb6c3bChris Forbes                        "vkCmdClearAttachments() color attachment index %d out of range for active subpass %d; ignored",
83955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        attachment->colorAttachment, pCB->activeSubpass);
83965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
8397dd2e11f29131ab2a77ccb9ae0c4c5c3bcf95c1d5Chris Forbes                else if (pSD->pColorAttachments[attachment->colorAttachment].attachment == VK_ATTACHMENT_UNUSED) {
8398dd2e11f29131ab2a77ccb9ae0c4c5c3bcf95c1d5Chris Forbes                    skip_call |= log_msg(
839921a714edaf9b670a60102430c36b221ff27f0f25Chris Forbes                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
8400dd2e11f29131ab2a77ccb9ae0c4c5c3bcf95c1d5Chris Forbes                        (uint64_t)commandBuffer, __LINE__, DRAWSTATE_MISSING_ATTACHMENT_REFERENCE, "DS",
8401dd2e11f29131ab2a77ccb9ae0c4c5c3bcf95c1d5Chris Forbes                        "vkCmdClearAttachments() color attachment index %d is VK_ATTACHMENT_UNUSED; ignored",
8402dd2e11f29131ab2a77ccb9ae0c4c5c3bcf95c1d5Chris Forbes                        attachment->colorAttachment);
8403dd2e11f29131ab2a77ccb9ae0c4c5c3bcf95c1d5Chris Forbes                }
84045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            } else if (attachment->aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
84055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if (!pSD->pDepthStencilAttachment || // Says no DS will be used in active subpass
84065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    (pSD->pDepthStencilAttachment->attachment ==
84075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                     VK_ATTACHMENT_UNUSED)) { // Says no DS will be used in active subpass
84085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
840983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                    skip_call |= log_msg(
841021a714edaf9b670a60102430c36b221ff27f0f25Chris Forbes                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
84115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        (uint64_t)commandBuffer, __LINE__, DRAWSTATE_MISSING_ATTACHMENT_REFERENCE, "DS",
84127386605ae0fe78241c997605a843bdc9a5499e2bChris Forbes                        "vkCmdClearAttachments() depth/stencil clear with no depth/stencil attachment in subpass; ignored");
84135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
84145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
84155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
84165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8417b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
841883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
84194a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdClearAttachments(commandBuffer, attachmentCount, pAttachments, rectCount, pRects);
84205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
84215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
842289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image,
842389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                              VkImageLayout imageLayout, const VkClearColorValue *pColor,
842489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                              uint32_t rangeCount, const VkImageSubresourceRange *pRanges) {
842583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
84265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
8427b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
84285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TODO : Verify memory is in VK_IMAGE_STATE_CLEAR state
8429249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis
84309f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis    auto cb_node = getCBNode(dev_data, commandBuffer);
8431249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis    auto img_node = getImageNode(dev_data, image);
8432249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis    if (cb_node && img_node) {
8433b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= ValidateMemoryIsBoundToImage(dev_data, img_node, "vkCmdClearColorImage()");
8434c3eda058338f7ba4e776ec74202b1c95ce6e6220Tobin Ehlis        AddCommandBufferBindingImage(dev_data, cb_node, img_node);
8435e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        std::function<bool()> function = [=]() {
8436f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis            SetImageMemoryValid(dev_data, img_node, true);
8437e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves            return false;
84385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        };
84399f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        cb_node->validate_functions.push_back(function);
8440593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
844183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, cb_node, CMD_CLEARCOLORIMAGE, "vkCmdClearColorImage()");
8442b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= insideRenderPass(dev_data, cb_node, "vkCmdClearColorImage()");
8443249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis    } else {
8444249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis        assert(0);
84455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8446b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
844783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
84484a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdClearColorImage(commandBuffer, image, imageLayout, pColor, rangeCount, pRanges);
84495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
84505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
845189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
845289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout,
845389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                          const VkClearDepthStencilValue *pDepthStencil, uint32_t rangeCount,
845489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                          const VkImageSubresourceRange *pRanges) {
845583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
84565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
8457b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
84585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TODO : Verify memory is in VK_IMAGE_STATE_CLEAR state
8459249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis
84609f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis    auto cb_node = getCBNode(dev_data, commandBuffer);
8461249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis    auto img_node = getImageNode(dev_data, image);
8462249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis    if (cb_node && img_node) {
8463b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= ValidateMemoryIsBoundToImage(dev_data, img_node, "vkCmdClearDepthStencilImage()");
8464c3eda058338f7ba4e776ec74202b1c95ce6e6220Tobin Ehlis        AddCommandBufferBindingImage(dev_data, cb_node, img_node);
8465e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        std::function<bool()> function = [=]() {
8466f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis            SetImageMemoryValid(dev_data, img_node, true);
8467e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves            return false;
84685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        };
84699f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        cb_node->validate_functions.push_back(function);
8470593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
847183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, cb_node, CMD_CLEARDEPTHSTENCILIMAGE, "vkCmdClearDepthStencilImage()");
8472b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= insideRenderPass(dev_data, cb_node, "vkCmdClearDepthStencilImage()");
8473249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis    } else {
8474249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis        assert(0);
84755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8476b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
847783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
84784a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdClearDepthStencilImage(commandBuffer, image, imageLayout, pDepthStencil, rangeCount, pRanges);
84795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
84805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
848189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
848289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
848389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve *pRegions) {
848483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
84855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
8486b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
8487593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
84889f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis    auto cb_node = getCBNode(dev_data, commandBuffer);
8489249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis    auto src_img_node = getImageNode(dev_data, srcImage);
8490249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis    auto dst_img_node = getImageNode(dev_data, dstImage);
8491249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis    if (cb_node && src_img_node && dst_img_node) {
8492b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= ValidateMemoryIsBoundToImage(dev_data, src_img_node, "vkCmdResolveImage()");
8493b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= ValidateMemoryIsBoundToImage(dev_data, dst_img_node, "vkCmdResolveImage()");
8494249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis        // Update bindings between images and cmd buffer
8495c3eda058338f7ba4e776ec74202b1c95ce6e6220Tobin Ehlis        AddCommandBufferBindingImage(dev_data, cb_node, src_img_node);
8496c3eda058338f7ba4e776ec74202b1c95ce6e6220Tobin Ehlis        AddCommandBufferBindingImage(dev_data, cb_node, dst_img_node);
8497e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        std::function<bool()> function = [=]() {
8498f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis            return ValidateImageMemoryIsValid(dev_data, src_img_node, "vkCmdResolveImage()");
8499593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        };
85009f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        cb_node->validate_functions.push_back(function);
8501593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        function = [=]() {
8502f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis            SetImageMemoryValid(dev_data, dst_img_node, true);
8503e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves            return false;
85045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        };
85059f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        cb_node->validate_functions.push_back(function);
8506593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
850783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, cb_node, CMD_RESOLVEIMAGE, "vkCmdResolveImage()");
8508b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= insideRenderPass(dev_data, cb_node, "vkCmdResolveImage()");
8509249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis    } else {
8510249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis        assert(0);
85115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8512b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
851383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
85144a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdResolveImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount,
85154a0754042cf090e131e9e769d8a3633c228625beChris Forbes                                                 pRegions);
85165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
85175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8518b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentinebool setEventStageMask(VkQueue queue, VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
8519b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
8520b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
8521b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    if (pCB) {
8522b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        pCB->eventToStageMap[event] = stageMask;
8523b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    }
8524b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    auto queue_data = dev_data->queueMap.find(queue);
8525b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    if (queue_data != dev_data->queueMap.end()) {
8526b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        queue_data->second.eventToStageMap[event] = stageMask;
8527b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    }
8528b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    return false;
8529b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine}
8530b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine
853189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
853289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
853383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
85345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
8535b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
85365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
85375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
853883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, pCB, CMD_SETEVENT, "vkCmdSetEvent()");
853983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= insideRenderPass(dev_data, pCB, "vkCmdSetEvent");
8540ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis        auto event_node = getEventNode(dev_data, event);
8541ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis        if (event_node) {
8542ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis            addCommandBufferBinding(&event_node->cb_bindings,
8543ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis                                    {reinterpret_cast<uint64_t &>(event), VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT}, pCB);
8544ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis            event_node->cb_bindings.insert(pCB);
8545ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis        }
85465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->events.push_back(event);
8547c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine        if (!pCB->waitedEvents.count(event)) {
8548c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine            pCB->writeEventsBeforeWait.push_back(event);
8549c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine        }
8550b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        std::function<bool(VkQueue)> eventUpdate =
8551b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine            std::bind(setEventStageMask, std::placeholders::_1, commandBuffer, event, stageMask);
8552b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        pCB->eventUpdates.push_back(eventUpdate);
85535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8554b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
855583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
85564a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdSetEvent(commandBuffer, event, stageMask);
85575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
85585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
855989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
856089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
856183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
85625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
8563b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
85645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
85655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
856683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, pCB, CMD_RESETEVENT, "vkCmdResetEvent()");
856783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= insideRenderPass(dev_data, pCB, "vkCmdResetEvent");
8568ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis        auto event_node = getEventNode(dev_data, event);
8569ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis        if (event_node) {
8570ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis            addCommandBufferBinding(&event_node->cb_bindings,
8571ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis                                    {reinterpret_cast<uint64_t &>(event), VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT}, pCB);
8572ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis            event_node->cb_bindings.insert(pCB);
8573ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis        }
85745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->events.push_back(event);
8575c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine        if (!pCB->waitedEvents.count(event)) {
8576c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine            pCB->writeEventsBeforeWait.push_back(event);
8577c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine        }
8578b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        std::function<bool(VkQueue)> eventUpdate =
8579b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine            std::bind(setEventStageMask, std::placeholders::_1, commandBuffer, event, VkPipelineStageFlags(0));
8580b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        pCB->eventUpdates.push_back(eventUpdate);
85815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8582b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
858383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
85844a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdResetEvent(commandBuffer, event, stageMask);
85855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
85865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8587e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool TransitionImageLayouts(VkCommandBuffer cmdBuffer, uint32_t memBarrierCount,
8588e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                                   const VkImageMemoryBarrier *pImgMemBarriers) {
85895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
85905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, cmdBuffer);
8591e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool skip = false;
85925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t levelCount = 0;
85935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t layerCount = 0;
85945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
85955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < memBarrierCount; ++i) {
85965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto mem_barrier = &pImgMemBarriers[i];
85975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (!mem_barrier)
85985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            continue;
85995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // TODO: Do not iterate over every possibility - consolidate where
86005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // possible
86015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        ResolveRemainingLevelsLayers(dev_data, &levelCount, &layerCount, mem_barrier->subresourceRange, mem_barrier->image);
86025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
86035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t j = 0; j < levelCount; j++) {
86045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            uint32_t level = mem_barrier->subresourceRange.baseMipLevel + j;
86055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            for (uint32_t k = 0; k < layerCount; k++) {
86065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                uint32_t layer = mem_barrier->subresourceRange.baseArrayLayer + k;
86075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                VkImageSubresource sub = {mem_barrier->subresourceRange.aspectMask, level, layer};
86085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                IMAGE_CMD_BUF_LAYOUT_NODE node;
86095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if (!FindLayout(pCB, mem_barrier->image, sub, node)) {
861008682cd3f4809493847b6bdf7605e0a2fede0d56Michael Lentine                    SetLayout(pCB, mem_barrier->image, sub,
861108682cd3f4809493847b6bdf7605e0a2fede0d56Michael Lentine                              IMAGE_CMD_BUF_LAYOUT_NODE(mem_barrier->oldLayout, mem_barrier->newLayout));
86125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    continue;
86135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
86145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if (mem_barrier->oldLayout == VK_IMAGE_LAYOUT_UNDEFINED) {
86155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    // TODO: Set memory invalid which is in mem_tracker currently
86165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                } else if (node.layout != mem_barrier->oldLayout) {
86175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
86185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                    __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", "You cannot transition the layout from %s "
86195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                                                    "when current layout is %s.",
86205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                    string_VkImageLayout(mem_barrier->oldLayout), string_VkImageLayout(node.layout));
86215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
86225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                SetLayout(pCB, mem_barrier->image, sub, mem_barrier->newLayout);
86235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
86245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
86255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
86265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return skip;
86275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
86285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
86295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Print readable FlagBits in FlagMask
8630e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic std::string string_VkAccessFlags(VkAccessFlags accessMask) {
86315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    std::string result;
86325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    std::string separator;
86335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
86345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (accessMask == 0) {
86355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        result = "[None]";
86365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
86375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        result = "[";
86385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (auto i = 0; i < 32; i++) {
86395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (accessMask & (1 << i)) {
86405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                result = result + separator + string_VkAccessFlagBits((VkAccessFlagBits)(1 << i));
86415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                separator = " | ";
86425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
86435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
86445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        result = result + "]";
86455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
86465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
86475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
86485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
86495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// AccessFlags MUST have 'required_bit' set, and may have one or more of 'optional_bits' set.
86505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// If required_bit is zero, accessMask must have at least one of 'optional_bits' set
86515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// TODO: Add tracking to ensure that at least one barrier has been set for these layout transitions
8652e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool ValidateMaskBits(const layer_data *my_data, VkCommandBuffer cmdBuffer, const VkAccessFlags &accessMask,
8653e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                             const VkImageLayout &layout, VkAccessFlags required_bit, VkAccessFlags optional_bits,
8654e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                             const char *type) {
8655e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool skip_call = false;
86565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
86575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if ((accessMask & required_bit) || (!required_bit && (accessMask & optional_bits))) {
865843986b69242d252623f4ee7278f1ecd07370adc8Chris Forbes        if (accessMask & ~(required_bit | optional_bits)) {
86595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // TODO: Verify against Valid Use
86605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            skip_call |=
86615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                log_msg(my_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
8662577d4588e09a06f957ca76991d5bd7b645261d6dTobin Ehlis                        DRAWSTATE_INVALID_BARRIER, "DS", "Additional bits in %s accessMask 0x%X %s are specified when layout is %s.",
86635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        type, accessMask, string_VkAccessFlags(accessMask).c_str(), string_VkImageLayout(layout));
86645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
86655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
86665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (!required_bit) {
86676044e94c13064f4663b31854951b7d4edf7877b2Michael Lentine            skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
86685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                 DRAWSTATE_INVALID_BARRIER, "DS", "%s AccessMask %d %s must contain at least one of access bits %d "
86695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                                  "%s when layout is %s, unless the app has previously added a "
86705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                                  "barrier for this transition.",
86715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                 type, accessMask, string_VkAccessFlags(accessMask).c_str(), optional_bits,
86725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                 string_VkAccessFlags(optional_bits).c_str(), string_VkImageLayout(layout));
86735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
86745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            std::string opt_bits;
86755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (optional_bits != 0) {
86765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                std::stringstream ss;
86775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                ss << optional_bits;
86785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                opt_bits = "and may have optional bits " + ss.str() + ' ' + string_VkAccessFlags(optional_bits);
86795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
86806044e94c13064f4663b31854951b7d4edf7877b2Michael Lentine            skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
86815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                 DRAWSTATE_INVALID_BARRIER, "DS", "%s AccessMask %d %s must have required access bit %d %s %s when "
86825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                                  "layout is %s, unless the app has previously added a barrier for "
86835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                                  "this transition.",
86845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                 type, accessMask, string_VkAccessFlags(accessMask).c_str(), required_bit,
86855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                 string_VkAccessFlags(required_bit).c_str(), opt_bits.c_str(), string_VkImageLayout(layout));
86865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
86875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
86885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return skip_call;
86895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
86905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8691e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool ValidateMaskBitsFromLayouts(const layer_data *my_data, VkCommandBuffer cmdBuffer, const VkAccessFlags &accessMask,
8692e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                                        const VkImageLayout &layout, const char *type) {
8693e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool skip_call = false;
86945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    switch (layout) {
86955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: {
86965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        skip_call |= ValidateMaskBits(my_data, cmdBuffer, accessMask, layout, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
86975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                      VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, type);
86985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        break;
86995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
87005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: {
87015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        skip_call |= ValidateMaskBits(my_data, cmdBuffer, accessMask, layout, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
87025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                      VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, type);
87035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        break;
87045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
87055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: {
87065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        skip_call |= ValidateMaskBits(my_data, cmdBuffer, accessMask, layout, VK_ACCESS_TRANSFER_WRITE_BIT, 0, type);
87075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        break;
87085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
87095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_IMAGE_LAYOUT_PREINITIALIZED: {
87105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        skip_call |= ValidateMaskBits(my_data, cmdBuffer, accessMask, layout, VK_ACCESS_HOST_WRITE_BIT, 0, type);
87115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        break;
87125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
87135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: {
87145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        skip_call |= ValidateMaskBits(my_data, cmdBuffer, accessMask, layout, 0,
87155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                      VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT, type);
87165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        break;
87175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
87185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: {
87195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        skip_call |= ValidateMaskBits(my_data, cmdBuffer, accessMask, layout, 0,
87205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                      VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT, type);
87215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        break;
87225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
87235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: {
87245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        skip_call |= ValidateMaskBits(my_data, cmdBuffer, accessMask, layout, VK_ACCESS_TRANSFER_READ_BIT, 0, type);
87255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        break;
87265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
872708d0512735df3d7ee6d2b085e4a2fbcac9d990c2Tony Barbour    case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: {
872808d0512735df3d7ee6d2b085e4a2fbcac9d990c2Tony Barbour        skip_call |= ValidateMaskBits(my_data, cmdBuffer, accessMask, layout, VK_ACCESS_MEMORY_READ_BIT, 0, type);
872908d0512735df3d7ee6d2b085e4a2fbcac9d990c2Tony Barbour        break;
873008d0512735df3d7ee6d2b085e4a2fbcac9d990c2Tony Barbour    }
87315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_IMAGE_LAYOUT_UNDEFINED: {
87325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (accessMask != 0) {
87335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // TODO: Verify against Valid Use section spec
87345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            skip_call |=
87355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                log_msg(my_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
8736577d4588e09a06f957ca76991d5bd7b645261d6dTobin Ehlis                        DRAWSTATE_INVALID_BARRIER, "DS", "Additional bits in %s accessMask 0x%X %s are specified when layout is %s.",
87375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        type, accessMask, string_VkAccessFlags(accessMask).c_str(), string_VkImageLayout(layout));
87385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
87395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        break;
87405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
87415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    case VK_IMAGE_LAYOUT_GENERAL:
87425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    default: { break; }
87435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
87445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return skip_call;
87455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
87465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8747e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool ValidateBarriers(const char *funcName, VkCommandBuffer cmdBuffer, uint32_t memBarrierCount,
8748e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                             const VkMemoryBarrier *pMemBarriers, uint32_t bufferBarrierCount,
8749e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                             const VkBufferMemoryBarrier *pBufferMemBarriers, uint32_t imageMemBarrierCount,
8750e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                             const VkImageMemoryBarrier *pImageMemBarriers) {
8751e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool skip_call = false;
87525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
87535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, cmdBuffer);
87545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB->activeRenderPass && memBarrierCount) {
8755ee691f5c5fa87aac3750454d2bca2cb582e4e817Chris Forbes        if (!pCB->activeRenderPass->hasSelfDependency[pCB->activeSubpass]) {
87565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
87575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                 DRAWSTATE_INVALID_BARRIER, "DS", "%s: Barriers cannot be set during subpass %d "
87585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                                  "with no self dependency specified.",
87595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                 funcName, pCB->activeSubpass);
87605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
87615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
87625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < imageMemBarrierCount; ++i) {
87635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto mem_barrier = &pImageMemBarriers[i];
87646d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis        auto image_data = getImageNode(dev_data, mem_barrier->image);
87656d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis        if (image_data) {
87665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            uint32_t src_q_f_index = mem_barrier->srcQueueFamilyIndex;
87675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            uint32_t dst_q_f_index = mem_barrier->dstQueueFamilyIndex;
87686d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            if (image_data->createInfo.sharingMode == VK_SHARING_MODE_CONCURRENT) {
87695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                // srcQueueFamilyIndex and dstQueueFamilyIndex must both
87705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                // be VK_QUEUE_FAMILY_IGNORED
87715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if ((src_q_f_index != VK_QUEUE_FAMILY_IGNORED) || (dst_q_f_index != VK_QUEUE_FAMILY_IGNORED)) {
87725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
87735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                         __LINE__, DRAWSTATE_INVALID_QUEUE_INDEX, "DS",
87745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                         "%s: Image Barrier for image 0x%" PRIx64 " was created with sharingMode of "
87755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                         "VK_SHARING_MODE_CONCURRENT.  Src and dst "
87765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                         " queueFamilyIndices must be VK_QUEUE_FAMILY_IGNORED.",
87775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                         funcName, reinterpret_cast<const uint64_t &>(mem_barrier->image));
87785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
87795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            } else {
87805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                // Sharing mode is VK_SHARING_MODE_EXCLUSIVE. srcQueueFamilyIndex and
87815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                // dstQueueFamilyIndex must either both be VK_QUEUE_FAMILY_IGNORED,
87825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                // or both be a valid queue family
87835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if (((src_q_f_index == VK_QUEUE_FAMILY_IGNORED) || (dst_q_f_index == VK_QUEUE_FAMILY_IGNORED)) &&
87845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    (src_q_f_index != dst_q_f_index)) {
87855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    skip_call |=
87865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
87875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                DRAWSTATE_INVALID_QUEUE_INDEX, "DS", "%s: Image 0x%" PRIx64 " was created with sharingMode "
87885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                                     "of VK_SHARING_MODE_EXCLUSIVE. If one of src- or "
87895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                                     "dstQueueFamilyIndex is VK_QUEUE_FAMILY_IGNORED, both "
87905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                                     "must be.",
87915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                funcName, reinterpret_cast<const uint64_t &>(mem_barrier->image));
87925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                } else if (((src_q_f_index != VK_QUEUE_FAMILY_IGNORED) && (dst_q_f_index != VK_QUEUE_FAMILY_IGNORED)) &&
8793b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis                           ((src_q_f_index >= dev_data->phys_dev_properties.queue_family_properties.size()) ||
8794b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis                            (dst_q_f_index >= dev_data->phys_dev_properties.queue_family_properties.size()))) {
87955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
87965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                         __LINE__, DRAWSTATE_INVALID_QUEUE_INDEX, "DS",
87975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                         "%s: Image 0x%" PRIx64 " was created with sharingMode "
87985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                         "of VK_SHARING_MODE_EXCLUSIVE, but srcQueueFamilyIndex %d"
87995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                         " or dstQueueFamilyIndex %d is greater than " PRINTF_SIZE_T_SPECIFIER
88005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                         "queueFamilies crated for this device.",
88015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                         funcName, reinterpret_cast<const uint64_t &>(mem_barrier->image), src_q_f_index,
8802b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis                                         dst_q_f_index, dev_data->phys_dev_properties.queue_family_properties.size());
88035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
88045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
88055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
88065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
88075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (mem_barrier) {
8808d678ec4f57d80aa89c24562e9ffe941d8d69e455Tony Barbour            if (mem_barrier->oldLayout != mem_barrier->newLayout) {
8809d678ec4f57d80aa89c24562e9ffe941d8d69e455Tony Barbour                skip_call |=
8810d678ec4f57d80aa89c24562e9ffe941d8d69e455Tony Barbour                    ValidateMaskBitsFromLayouts(dev_data, cmdBuffer, mem_barrier->srcAccessMask, mem_barrier->oldLayout, "Source");
8811d678ec4f57d80aa89c24562e9ffe941d8d69e455Tony Barbour                skip_call |=
8812d678ec4f57d80aa89c24562e9ffe941d8d69e455Tony Barbour                    ValidateMaskBitsFromLayouts(dev_data, cmdBuffer, mem_barrier->dstAccessMask, mem_barrier->newLayout, "Dest");
8813d678ec4f57d80aa89c24562e9ffe941d8d69e455Tony Barbour            }
88145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (mem_barrier->newLayout == VK_IMAGE_LAYOUT_UNDEFINED || mem_barrier->newLayout == VK_IMAGE_LAYOUT_PREINITIALIZED) {
88155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
88165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        DRAWSTATE_INVALID_BARRIER, "DS", "%s: Image Layout cannot be transitioned to UNDEFINED or "
88175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                         "PREINITIALIZED.",
88185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        funcName);
88195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
88206d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            auto image_data = getImageNode(dev_data, mem_barrier->image);
88211d5109d5e0dcc530b27e632e73e1be5e12a28dcdJamie Madill            VkFormat format = VK_FORMAT_UNDEFINED;
88221d5109d5e0dcc530b27e632e73e1be5e12a28dcdJamie Madill            uint32_t arrayLayers = 0, mipLevels = 0;
88235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            bool imageFound = false;
88246d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            if (image_data) {
88256d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis                format = image_data->createInfo.format;
88266d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis                arrayLayers = image_data->createInfo.arrayLayers;
88276d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis                mipLevels = image_data->createInfo.mipLevels;
88285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                imageFound = true;
88295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            } else if (dev_data->device_extensions.wsi_enabled) {
8830170dc65b45f6bcdec47e02b3aa19435e55b32804Tobin Ehlis                auto imageswap_data = getSwapchainFromImage(dev_data, mem_barrier->image);
8831170dc65b45f6bcdec47e02b3aa19435e55b32804Tobin Ehlis                if (imageswap_data) {
8832b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis                    auto swapchain_data = getSwapchainNode(dev_data, imageswap_data);
8833b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis                    if (swapchain_data) {
8834b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis                        format = swapchain_data->createInfo.imageFormat;
8835b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis                        arrayLayers = swapchain_data->createInfo.imageArrayLayers;
88365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        mipLevels = 1;
88375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        imageFound = true;
88385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
88395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
88405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
88415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (imageFound) {
8842c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                auto aspect_mask = mem_barrier->subresourceRange.aspectMask;
8843c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                if (vk_format_is_depth_or_stencil(format)) {
8844c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                    if (vk_format_is_depth_and_stencil(format)) {
8845c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                        if (!(aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) && !(aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT)) {
8846c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                            log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
8847c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                                    __LINE__, DRAWSTATE_INVALID_BARRIER, "DS",
8848c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                                    "%s: Image is a depth and stencil format and thus must "
8849c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                                    "have either one or both of VK_IMAGE_ASPECT_DEPTH_BIT and "
8850c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                                    "VK_IMAGE_ASPECT_STENCIL_BIT set.",
8851c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                                    funcName);
8852c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                        }
8853c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                    } else if (vk_format_is_depth_only(format)) {
8854c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                        if (!(aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT)) {
8855c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                            log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
8856c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                                    __LINE__, DRAWSTATE_INVALID_BARRIER, "DS", "%s: Image is a depth-only format and thus must "
8857c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                                                                               "have VK_IMAGE_ASPECT_DEPTH_BIT set.",
8858c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                                    funcName);
8859c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                        }
8860c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                    } else { // stencil-only case
8861a968f468c0aafdf33b7af68fb8e7961e37e32f7fTobin Ehlis                        if (!(aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT)) {
8862c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                            log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
8863c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                                    __LINE__, DRAWSTATE_INVALID_BARRIER, "DS", "%s: Image is a stencil-only format and thus must "
8864c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                                                                               "have VK_IMAGE_ASPECT_STENCIL_BIT set.",
8865c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                                    funcName);
8866c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                        }
8867c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                    }
8868c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                } else { // image is a color format
8869c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                    if (!(aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT)) {
8870c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                        log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
8871c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                                DRAWSTATE_INVALID_BARRIER, "DS", "%s: Image is a color format and thus must "
8872c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                                                                 "have VK_IMAGE_ASPECT_COLOR_BIT set.",
8873c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                                funcName);
8874c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis                    }
88755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
8876f0d091deca3d4b90e1f31d75e062684dca160ad1Michael Lentine                int layerCount = (mem_barrier->subresourceRange.layerCount == VK_REMAINING_ARRAY_LAYERS)
8877f0d091deca3d4b90e1f31d75e062684dca160ad1Michael Lentine                                     ? 1
8878f0d091deca3d4b90e1f31d75e062684dca160ad1Michael Lentine                                     : mem_barrier->subresourceRange.layerCount;
8879f0d091deca3d4b90e1f31d75e062684dca160ad1Michael Lentine                if ((mem_barrier->subresourceRange.baseArrayLayer + layerCount) > arrayLayers) {
88805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
88815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            DRAWSTATE_INVALID_BARRIER, "DS", "%s: Subresource must have the sum of the "
88825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                             "baseArrayLayer (%d) and layerCount (%d) be less "
88835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                             "than or equal to the total number of layers (%d).",
88845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            funcName, mem_barrier->subresourceRange.baseArrayLayer, mem_barrier->subresourceRange.layerCount,
88855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            arrayLayers);
88865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
8887f0d091deca3d4b90e1f31d75e062684dca160ad1Michael Lentine                int levelCount = (mem_barrier->subresourceRange.levelCount == VK_REMAINING_MIP_LEVELS)
8888f0d091deca3d4b90e1f31d75e062684dca160ad1Michael Lentine                                     ? 1
8889f0d091deca3d4b90e1f31d75e062684dca160ad1Michael Lentine                                     : mem_barrier->subresourceRange.levelCount;
8890f0d091deca3d4b90e1f31d75e062684dca160ad1Michael Lentine                if ((mem_barrier->subresourceRange.baseMipLevel + levelCount) > mipLevels) {
88915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
88925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            DRAWSTATE_INVALID_BARRIER, "DS", "%s: Subresource must have the sum of the baseMipLevel "
88935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                             "(%d) and levelCount (%d) be less than or equal to "
88945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                             "the total number of levels (%d).",
88955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            funcName, mem_barrier->subresourceRange.baseMipLevel, mem_barrier->subresourceRange.levelCount,
88965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            mipLevels);
88975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
88985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
88995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
89005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
89015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < bufferBarrierCount; ++i) {
89025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto mem_barrier = &pBufferMemBarriers[i];
89035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (pCB->activeRenderPass) {
89045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            skip_call |=
89055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
89065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        DRAWSTATE_INVALID_BARRIER, "DS", "%s: Buffer Barriers cannot be used during a render pass.", funcName);
89075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
89085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (!mem_barrier)
89095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            continue;
89105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
89115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Validate buffer barrier queue family indices
89125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if ((mem_barrier->srcQueueFamilyIndex != VK_QUEUE_FAMILY_IGNORED &&
8913b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis             mem_barrier->srcQueueFamilyIndex >= dev_data->phys_dev_properties.queue_family_properties.size()) ||
89145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            (mem_barrier->dstQueueFamilyIndex != VK_QUEUE_FAMILY_IGNORED &&
8915b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis             mem_barrier->dstQueueFamilyIndex >= dev_data->phys_dev_properties.queue_family_properties.size())) {
89165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
89175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                 DRAWSTATE_INVALID_QUEUE_INDEX, "DS",
89185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                 "%s: Buffer Barrier 0x%" PRIx64 " has QueueFamilyIndex greater "
89195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                 "than the number of QueueFamilies (" PRINTF_SIZE_T_SPECIFIER ") for this device.",
89205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                 funcName, reinterpret_cast<const uint64_t &>(mem_barrier->buffer),
8921b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis                                 dev_data->phys_dev_properties.queue_family_properties.size());
89225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
89235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
89248718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis        auto buffer_node = getBufferNode(dev_data, mem_barrier->buffer);
89258718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis        if (buffer_node) {
89260c6dd4dd7c7e444efc979299f8f445fb4fc4febeChris Forbes            auto buffer_size = buffer_node->memSize;
89275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (mem_barrier->offset >= buffer_size) {
892894c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis                skip_call |= log_msg(
892994c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis                    dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
893094c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis                    DRAWSTATE_INVALID_BARRIER, "DS",
8931414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                    "%s: Buffer Barrier 0x%" PRIx64 " has offset 0x%" PRIx64 " which is not less than total size 0x%" PRIx64 ".",
893294c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis                    funcName, reinterpret_cast<const uint64_t &>(mem_barrier->buffer),
893394c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis                    reinterpret_cast<const uint64_t &>(mem_barrier->offset), reinterpret_cast<const uint64_t &>(buffer_size));
89345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            } else if (mem_barrier->size != VK_WHOLE_SIZE && (mem_barrier->offset + mem_barrier->size > buffer_size)) {
893594c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis                skip_call |= log_msg(
893694c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis                    dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
8937414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                    DRAWSTATE_INVALID_BARRIER, "DS", "%s: Buffer Barrier 0x%" PRIx64 " has offset 0x%" PRIx64 " and size 0x%" PRIx64
8938414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                                     " whose sum is greater than total size 0x%" PRIx64 ".",
893994c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis                    funcName, reinterpret_cast<const uint64_t &>(mem_barrier->buffer),
894094c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis                    reinterpret_cast<const uint64_t &>(mem_barrier->offset), reinterpret_cast<const uint64_t &>(mem_barrier->size),
894194c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis                    reinterpret_cast<const uint64_t &>(buffer_size));
89425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
89435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
89445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
89455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return skip_call;
89465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
89475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
89482ab14387df9b890fe4b13494ea249dd03cf898d2Chris Forbesbool validateEventStageMask(VkQueue queue, GLOBAL_CB_NODE *pCB, uint32_t eventCount, size_t firstEventIndex, VkPipelineStageFlags sourceStageMask) {
8949b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    bool skip_call = false;
8950b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    VkPipelineStageFlags stageMask = 0;
8951b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
8952b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    for (uint32_t i = 0; i < eventCount; ++i) {
89532ab14387df9b890fe4b13494ea249dd03cf898d2Chris Forbes        auto event = pCB->events[firstEventIndex + i];
8954b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        auto queue_data = dev_data->queueMap.find(queue);
8955b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        if (queue_data == dev_data->queueMap.end())
8956b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine            return false;
89572ab14387df9b890fe4b13494ea249dd03cf898d2Chris Forbes        auto event_data = queue_data->second.eventToStageMap.find(event);
8958b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        if (event_data != queue_data->second.eventToStageMap.end()) {
8959b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine            stageMask |= event_data->second;
8960b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        } else {
89619556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis            auto global_event_data = getEventNode(dev_data, event);
89629556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis            if (!global_event_data) {
8963b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine                skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT,
896427c3e0dda9e30d1d334728bbd373e8d7011257d4Chris Forbes                                     reinterpret_cast<const uint64_t &>(event), __LINE__, DRAWSTATE_INVALID_EVENT, "DS",
896527c3e0dda9e30d1d334728bbd373e8d7011257d4Chris Forbes                                     "Event 0x%" PRIx64 " cannot be waited on if it has never been set.",
89662ab14387df9b890fe4b13494ea249dd03cf898d2Chris Forbes                                     reinterpret_cast<const uint64_t &>(event));
8967b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine            } else {
89689556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis                stageMask |= global_event_data->stageMask;
8969b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine            }
8970b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        }
8971b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    }
8972c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine    // TODO: Need to validate that host_bit is only set if set event is called
8973c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine    // but set event can be called at any time.
8974c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine    if (sourceStageMask != stageMask && sourceStageMask != (stageMask | VK_PIPELINE_STAGE_HOST_BIT)) {
8975c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine        skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
8976c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine                             DRAWSTATE_INVALID_EVENT, "DS", "Submitting cmdbuffer with call to VkCmdWaitEvents "
89774261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski                                                            "using srcStageMask 0x%X which must be the bitwise "
8978c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine                                                            "OR of the stageMask parameters used in calls to "
8979c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine                                                            "vkCmdSetEvent and VK_PIPELINE_STAGE_HOST_BIT if "
89804261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski                                                            "used with vkSetEvent but instead is 0x%X.",
8981c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine                             sourceStageMask, stageMask);
8982b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    }
8983b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    return skip_call;
8984b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine}
8985b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine
898689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
898789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents, VkPipelineStageFlags sourceStageMask,
898889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu              VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
898989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu              uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers,
899089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu              uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) {
899183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
89925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
8993b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
89945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
89955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
89962ab14387df9b890fe4b13494ea249dd03cf898d2Chris Forbes        auto firstEventIndex = pCB->events.size();
89975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t i = 0; i < eventCount; ++i) {
8998ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis            auto event_node = getEventNode(dev_data, pEvents[i]);
8999ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis            if (event_node) {
9000ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis                addCommandBufferBinding(&event_node->cb_bindings,
9001ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis                                        {reinterpret_cast<const uint64_t &>(pEvents[i]), VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT},
9002ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis                                        pCB);
9003ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis                event_node->cb_bindings.insert(pCB);
9004ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis            }
9005c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine            pCB->waitedEvents.insert(pEvents[i]);
90065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            pCB->events.push_back(pEvents[i]);
90075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
9008b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        std::function<bool(VkQueue)> eventUpdate =
90092ab14387df9b890fe4b13494ea249dd03cf898d2Chris Forbes            std::bind(validateEventStageMask, std::placeholders::_1, pCB, eventCount, firstEventIndex, sourceStageMask);
9010b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        pCB->eventUpdates.push_back(eventUpdate);
90115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (pCB->state == CB_RECORDING) {
901283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= addCmd(dev_data, pCB, CMD_WAITEVENTS, "vkCmdWaitEvents()");
90135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
901483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdWaitEvents()");
90155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
901683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= TransitionImageLayouts(commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers);
901783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |=
90185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            ValidateBarriers("vkCmdWaitEvents", commandBuffer, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount,
90195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                             pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
90205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
9021b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
902283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
90234a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdWaitEvents(commandBuffer, eventCount, pEvents, sourceStageMask, dstStageMask,
90244a0754042cf090e131e9e769d8a3633c228625beChris Forbes                                               memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers,
90254a0754042cf090e131e9e769d8a3633c228625beChris Forbes                                               imageMemoryBarrierCount, pImageMemoryBarriers);
90265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
90275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
902889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
902989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
903089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                   VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
903189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                   uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers,
903289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                   uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) {
903383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
90345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
9035b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
90365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
90375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
903883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, pCB, CMD_PIPELINEBARRIER, "vkCmdPipelineBarrier()");
903983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= TransitionImageLayouts(commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers);
904083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |=
90415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            ValidateBarriers("vkCmdPipelineBarrier", commandBuffer, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount,
90425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                             pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
90435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
9044b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
904583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
90464a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount,
90474a0754042cf090e131e9e769d8a3633c228625beChris Forbes                                                    pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers,
90484a0754042cf090e131e9e769d8a3633c228625beChris Forbes                                                    imageMemoryBarrierCount, pImageMemoryBarriers);
90495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
90505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
9051d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentinebool setQueryState(VkQueue queue, VkCommandBuffer commandBuffer, QueryObject object, bool value) {
9052d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
9053d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
9054d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    if (pCB) {
9055d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine        pCB->queryToStateMap[object] = value;
9056d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    }
9057d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    auto queue_data = dev_data->queueMap.find(queue);
9058d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    if (queue_data != dev_data->queueMap.end()) {
9059d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine        queue_data->second.queryToStateMap[object] = value;
9060d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    }
9061d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    return false;
9062d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine}
9063d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine
906489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
906589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot, VkFlags flags) {
906683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
90675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
9068b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
90695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
90705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
90715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        QueryObject query = {queryPool, slot};
90725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->activeQueries.insert(query);
90735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (!pCB->startedQueries.count(query)) {
90745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            pCB->startedQueries.insert(query);
90755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
907683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, pCB, CMD_BEGINQUERY, "vkCmdBeginQuery()");
9077ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis        addCommandBufferBinding(&getQueryPoolNode(dev_data, queryPool)->cb_bindings,
9078ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis                                {reinterpret_cast<uint64_t &>(queryPool), VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT}, pCB);
90795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
9080b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
908183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
90824a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdBeginQuery(commandBuffer, queryPool, slot, flags);
90835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
90845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
908589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot) {
908683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
90875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
9088b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
90895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
90905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
90915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        QueryObject query = {queryPool, slot};
90925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (!pCB->activeQueries.count(query)) {
909383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |=
90945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
9095414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        DRAWSTATE_INVALID_QUERY, "DS", "Ending a query before it was started: queryPool 0x%" PRIx64 ", index %d",
90965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        (uint64_t)(queryPool), slot);
90975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
90985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            pCB->activeQueries.erase(query);
90995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
9100c2ec509029604290e981885108c06a9b7de565c1Karl Schultz        std::function<bool(VkQueue)> queryUpdate = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, true);
9101d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine        pCB->queryUpdates.push_back(queryUpdate);
91025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (pCB->state == CB_RECORDING) {
910383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= addCmd(dev_data, pCB, CMD_ENDQUERY, "VkCmdEndQuery()");
91045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
910583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdEndQuery()");
91065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
9107ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis        addCommandBufferBinding(&getQueryPoolNode(dev_data, queryPool)->cb_bindings,
9108ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis                                {reinterpret_cast<uint64_t &>(queryPool), VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT}, pCB);
91095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
9110b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
911183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
91124a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdEndQuery(commandBuffer, queryPool, slot);
91135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
91145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
911589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
911689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount) {
911783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
91185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
9119b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
91205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
91215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
91225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t i = 0; i < queryCount; i++) {
91235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            QueryObject query = {queryPool, firstQuery + i};
91245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            pCB->waitedEventsBeforeQueryReset[query] = pCB->waitedEvents;
9125c2ec509029604290e981885108c06a9b7de565c1Karl Schultz            std::function<bool(VkQueue)> queryUpdate = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, false);
9126d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine            pCB->queryUpdates.push_back(queryUpdate);
91275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
91285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (pCB->state == CB_RECORDING) {
912983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= addCmd(dev_data, pCB, CMD_RESETQUERYPOOL, "VkCmdResetQueryPool()");
91305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
913183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdResetQueryPool()");
91325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
913383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= insideRenderPass(dev_data, pCB, "vkCmdQueryPool");
9134ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis        addCommandBufferBinding(&getQueryPoolNode(dev_data, queryPool)->cb_bindings,
9135ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis                                {reinterpret_cast<uint64_t &>(queryPool), VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT}, pCB);
91365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
9137b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
913883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
91394a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdResetQueryPool(commandBuffer, queryPool, firstQuery, queryCount);
91405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
91415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
9142d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentinebool validateQuery(VkQueue queue, GLOBAL_CB_NODE *pCB, VkQueryPool queryPool, uint32_t queryCount, uint32_t firstQuery) {
9143d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    bool skip_call = false;
9144d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(pCB->commandBuffer), layer_data_map);
9145d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    auto queue_data = dev_data->queueMap.find(queue);
9146d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    if (queue_data == dev_data->queueMap.end())
9147d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine        return false;
9148d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    for (uint32_t i = 0; i < queryCount; i++) {
9149d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine        QueryObject query = {queryPool, firstQuery + i};
9150d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine        auto query_data = queue_data->second.queryToStateMap.find(query);
9151d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine        bool fail = false;
9152d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine        if (query_data != queue_data->second.queryToStateMap.end()) {
9153d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine            if (!query_data->second) {
9154d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine                fail = true;
9155d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine            }
9156d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine        } else {
9157d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine            auto global_query_data = dev_data->queryToStateMap.find(query);
9158d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine            if (global_query_data != dev_data->queryToStateMap.end()) {
9159d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine                if (!global_query_data->second) {
9160d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine                    fail = true;
9161d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine                }
9162d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine            } else {
9163d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine                fail = true;
9164d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine            }
9165d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine        }
9166d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine        if (fail) {
9167d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
9168d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine                                 DRAWSTATE_INVALID_QUERY, "DS",
9169d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine                                 "Requesting a copy from query to buffer with invalid query: queryPool 0x%" PRIx64 ", index %d",
9170d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine                                 reinterpret_cast<uint64_t &>(queryPool), firstQuery + i);
9171d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine        }
9172d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    }
9173d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    return skip_call;
9174d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine}
9175d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine
917689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
917789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount,
917889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                        VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags) {
917983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
91805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
9181b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
9182ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis
91839f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis    auto cb_node = getCBNode(dev_data, commandBuffer);
9184ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    auto dst_buff_node = getBufferNode(dev_data, dstBuffer);
9185ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    if (cb_node && dst_buff_node) {
9186b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_node, "vkCmdCopyQueryPoolResults()");
9187ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        // Update bindings between buffer and cmd buffer
9188c3eda058338f7ba4e776ec74202b1c95ce6e6220Tobin Ehlis        AddCommandBufferBindingBuffer(dev_data, cb_node, dst_buff_node);
9189ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        // Validate that DST buffer has correct usage flags set
919059b0561b0bd298885f90b9f524c0583cd8ee6f61Tobin Ehlis        skip_call |= ValidateBufferUsageFlags(dev_data, dst_buff_node, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true,
9191ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis                                              "vkCmdCopyQueryPoolResults()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT");
9192e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        std::function<bool()> function = [=]() {
9193f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis            SetBufferMemoryValid(dev_data, dst_buff_node, true);
9194e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves            return false;
91955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        };
91969f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        cb_node->validate_functions.push_back(function);
9197d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine        std::function<bool(VkQueue)> queryUpdate =
9198ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis            std::bind(validateQuery, std::placeholders::_1, cb_node, queryPool, queryCount, firstQuery);
9199ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        cb_node->queryUpdates.push_back(queryUpdate);
9200ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        if (cb_node->state == CB_RECORDING) {
9201ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis            skip_call |= addCmd(dev_data, cb_node, CMD_COPYQUERYPOOLRESULTS, "vkCmdCopyQueryPoolResults()");
92025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
920383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdCopyQueryPoolResults()");
92045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
9205b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski        skip_call |= insideRenderPass(dev_data, cb_node, "vkCmdCopyQueryPoolResults()");
9206ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis        addCommandBufferBinding(&getQueryPoolNode(dev_data, queryPool)->cb_bindings,
9207ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis                                {reinterpret_cast<uint64_t &>(queryPool), VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT}, cb_node);
9208ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    } else {
9209ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        assert(0);
92105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
9211b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
921283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
92134a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdCopyQueryPoolResults(commandBuffer, queryPool, firstQuery, queryCount, dstBuffer, dstOffset,
92144a0754042cf090e131e9e769d8a3633c228625beChris Forbes                                                         stride, flags);
92155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
92165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
921789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdPushConstants(VkCommandBuffer commandBuffer, VkPipelineLayout layout,
921889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                            VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size,
921989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                            const void *pValues) {
922083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
92215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
9222b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
92235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
92245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
92255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (pCB->state == CB_RECORDING) {
922683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= addCmd(dev_data, pCB, CMD_PUSHCONSTANTS, "vkCmdPushConstants()");
92275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
922883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdPushConstants()");
92295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
92305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
923183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    skip_call |= validatePushConstantRange(dev_data, offset, size, "vkCmdPushConstants()");
92329e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    if (0 == stageFlags) {
923383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
923483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                             DRAWSTATE_PUSH_CONSTANTS_ERROR, "DS", "vkCmdPushConstants() call has no stageFlags set.");
92359e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    }
92369e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz
9237a95cb74c9d0947ab3821b15e1289755286ea78eeKarl Schultz    // Check if push constant update is within any of the ranges with the same stage flags specified in pipeline layout.
92384a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes    auto pipeline_layout = getPipelineLayout(dev_data, layout);
923915a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis    // Coalesce adjacent/overlapping pipeline ranges before checking to see if incoming range is
924015a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis    // contained in the pipeline ranges.
924115a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis    // Build a {start, end} span list for ranges with matching stage flags.
924215a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis    const auto &ranges = pipeline_layout->push_constant_ranges;
924315a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis    struct span {
924415a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis        uint32_t start;
924515a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis        uint32_t end;
924615a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis    };
924715a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis    std::vector<span> spans;
924815a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis    spans.reserve(ranges.size());
924915a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis    for (const auto &iter : ranges) {
925015a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis        if (iter.stageFlags == stageFlags) {
925115a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis            spans.push_back({iter.offset, iter.offset + iter.size});
925215a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis        }
925315a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis    }
925415a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis    if (spans.size() == 0) {
925515a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis        // There were no ranges that matched the stageFlags.
925615a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis        skip_call |=
925715a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis            log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
925815a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis                    DRAWSTATE_PUSH_CONSTANTS_ERROR, "DS", "vkCmdPushConstants() stageFlags = 0x%" PRIx32 " do not match "
925915a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis                                                          "the stageFlags in any of the ranges in pipeline layout 0x%" PRIx64 ".",
926015a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis                    (uint32_t)stageFlags, (uint64_t)layout);
92619e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    } else {
926215a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis        // Sort span list by start value.
926315a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis        struct comparer {
926415a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis            bool operator()(struct span i, struct span j) { return i.start < j.start; }
926515a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis        } my_comparer;
926615a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis        std::sort(spans.begin(), spans.end(), my_comparer);
926715a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis
926815a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis        // Examine two spans at a time.
926915a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis        std::vector<span>::iterator current = spans.begin();
927015a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis        std::vector<span>::iterator next = current + 1;
927115a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis        while (next != spans.end()) {
927215a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis            if (current->end < next->start) {
927315a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis                // There is a gap; cannot coalesce. Move to the next two spans.
927415a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis                ++current;
927515a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis                ++next;
927615a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis            } else {
927715a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis                // Coalesce the two spans.  The start of the next span
927815a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis                // is within the current span, so pick the larger of
927915a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis                // the end values to extend the current span.
928015a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis                // Then delete the next span and set next to the span after it.
928115a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis                current->end = max(current->end, next->end);
928215a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis                next = spans.erase(next);
92839e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz            }
92849e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        }
9285a95cb74c9d0947ab3821b15e1289755286ea78eeKarl Schultz
928615a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis        // Now we can check if the incoming range is within any of the spans.
928715a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis        bool contained_in_a_range = false;
928815a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis        for (uint32_t i = 0; i < spans.size(); ++i) {
928915a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis            if ((offset >= spans[i].start) && ((uint64_t)offset + (uint64_t)size <= (uint64_t)spans[i].end)) {
929015a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis                contained_in_a_range = true;
929115a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis                break;
9292a95cb74c9d0947ab3821b15e1289755286ea78eeKarl Schultz            }
92939e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        }
929415a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis        if (!contained_in_a_range) {
929515a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis            skip_call |=
929615a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
929715a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis                        DRAWSTATE_PUSH_CONSTANTS_ERROR, "DS", "vkCmdPushConstants() Push constant range [%d, %d) "
929815a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis                                                              "with stageFlags = 0x%" PRIx32 " "
929915a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis                                                              "not within flag-matching ranges in pipeline layout 0x%" PRIx64 ".",
930015a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis                        offset, offset + size, (uint32_t)stageFlags, (uint64_t)layout);
930115a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis        }
93025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
9303b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
930483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
93054a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdPushConstants(commandBuffer, layout, stageFlags, offset, size, pValues);
93065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
93075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
930889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
930989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, uint32_t slot) {
931083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
93115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
9312b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
93135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
93145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
93155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        QueryObject query = {queryPool, slot};
9316c2ec509029604290e981885108c06a9b7de565c1Karl Schultz        std::function<bool(VkQueue)> queryUpdate = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, true);
9317d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine        pCB->queryUpdates.push_back(queryUpdate);
93185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (pCB->state == CB_RECORDING) {
931983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= addCmd(dev_data, pCB, CMD_WRITETIMESTAMP, "vkCmdWriteTimestamp()");
93205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
932183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdWriteTimestamp()");
93225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
93235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
9324b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
932583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
93264a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdWriteTimestamp(commandBuffer, pipelineStage, queryPool, slot);
93275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
93285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
93296600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinskistatic bool MatchUsage(layer_data *dev_data, uint32_t count, const VkAttachmentReference *attachments,
93306600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                       const VkFramebufferCreateInfo *fbci, VkImageUsageFlagBits usage_flag) {
93316600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski    bool skip_call = false;
93326600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski
93336600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski    for (uint32_t attach = 0; attach < count; attach++) {
93346600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski        if (attachments[attach].attachment != VK_ATTACHMENT_UNUSED) {
93356600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski            // Attachment counts are verified elsewhere, but prevent an invalid access
93366600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski            if (attachments[attach].attachment < fbci->attachmentCount) {
93376600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                const VkImageView *image_view = &fbci->pAttachments[attachments[attach].attachment];
933879fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                auto view_state = getImageViewState(dev_data, *image_view);
933979fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                if (view_state) {
934079fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                    const VkImageCreateInfo *ici = &getImageNode(dev_data, view_state->create_info.image)->createInfo;
93416600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                    if (ici != nullptr) {
93426600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                        if ((ici->usage & usage_flag) == 0) {
93436600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
93446600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                                                 (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_USAGE, "DS",
93456600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                                                 "vkCreateFramebuffer:  Framebuffer Attachment (%d) conflicts with the image's "
93466600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                                                 "IMAGE_USAGE flags (%s).",
93476600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                                                 attachments[attach].attachment, string_VkImageUsageFlagBits(usage_flag));
93486600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                        }
93496600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                    }
93506600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                }
93516600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski            }
93526600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski        }
93536600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski    }
93546600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski    return skip_call;
93556600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski}
93566600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski
9357d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis// Validate VkFramebufferCreateInfo which includes:
9358d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis// 1. attachmentCount equals renderPass attachmentCount
93595ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 2. corresponding framebuffer and renderpass attachments have matching formats
93605ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 3. corresponding framebuffer and renderpass attachments have matching sample counts
93615ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 4. fb attachments only have a single mip level
93625ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 5. fb attachment dimensions are each at least as large as the fb
93635ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 6. fb attachments use idenity swizzle
93645ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 7. fb attachments used by renderPass for color/input/ds have correct usage bit set
93656fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis// 8. fb dimensions are within physical device limits
9366d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlisstatic bool ValidateFramebufferCreateInfo(layer_data *dev_data, const VkFramebufferCreateInfo *pCreateInfo) {
93676600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski    bool skip_call = false;
93686600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski
9369d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis    auto rp_node = getRenderPass(dev_data, pCreateInfo->renderPass);
9370d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis    if (rp_node) {
9371fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes        const VkRenderPassCreateInfo *rpci = rp_node->createInfo.ptr();
9372d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis        if (rpci->attachmentCount != pCreateInfo->attachmentCount) {
9373d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis            skip_call |= log_msg(
9374d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis                dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
9375d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis                reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS",
9376d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis                "vkCreateFramebuffer(): VkFramebufferCreateInfo attachmentCount of %u does not match attachmentCount of %u of "
9377d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis                "renderPass (0x%" PRIxLEAST64 ") being used to create Framebuffer.",
9378d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis                pCreateInfo->attachmentCount, rpci->attachmentCount, reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass));
93795ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis        } else {
938041ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis            // attachmentCounts match, so make sure corresponding attachment details line up
93815ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis            const VkImageView *image_views = pCreateInfo->pAttachments;
93825ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis            for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) {
938379fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                auto view_state = getImageViewState(dev_data, image_views[i]);
938412d5600c2f9e32343016fd944432ba95df370797Tobin Ehlis                auto &ivci = view_state->create_info;
938579fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                if (ivci.format != rpci->pAttachments[i].format) {
93865ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                    skip_call |= log_msg(
93875ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
93885ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                        reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE,
93895ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                        "DS", "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has format of %s that does not match "
93905ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                              "the format of "
93915ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                              "%s used by the corresponding attachment for renderPass (0x%" PRIxLEAST64 ").",
939279fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                        i, string_VkFormat(ivci.format), string_VkFormat(rpci->pAttachments[i].format),
93935ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                        reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass));
93945ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                }
939579fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                const VkImageCreateInfo *ici = &getImageNode(dev_data, ivci.image)->createInfo;
93965ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                if (ici->samples != rpci->pAttachments[i].samples) {
939741ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis                    skip_call |= log_msg(
939841ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
939941ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis                        reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE,
940041ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis                        "DS", "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has %s samples that do not match "
940141ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis                              "the %s samples used by the corresponding attachment for renderPass (0x%" PRIxLEAST64 ").",
940241ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis                        i, string_VkSampleCountFlagBits(ici->samples), string_VkSampleCountFlagBits(rpci->pAttachments[i].samples),
940341ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis                        reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass));
94045ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                }
94055ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                // Verify that view only has a single mip level
940679fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                if (ivci.subresourceRange.levelCount != 1) {
94076fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis                    skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0,
94086fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis                                         __LINE__, DRAWSTATE_INVALID_FRAMEBUFFER_CREATE_INFO, "DS",
94096fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis                                         "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has mip levelCount of %u "
94106fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis                                         "but only a single mip level (levelCount ==  1) is allowed when creating a Framebuffer.",
941179fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                                         i, ivci.subresourceRange.levelCount);
94125ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                }
941379fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                const uint32_t mip_level = ivci.subresourceRange.baseMipLevel;
9414aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis                uint32_t mip_width = max(1u, ici->extent.width >> mip_level);
9415aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis                uint32_t mip_height = max(1u, ici->extent.height >> mip_level);
941679fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                if ((ivci.subresourceRange.layerCount < pCreateInfo->layers) || (mip_width < pCreateInfo->width) ||
9417aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis                    (mip_height < pCreateInfo->height)) {
9418aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis                    skip_call |=
94196fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis                        log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__,
9420aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis                                DRAWSTATE_INVALID_FRAMEBUFFER_CREATE_INFO, "DS",
9421aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis                                "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u mip level %u has dimensions smaller "
9422aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis                                "than the corresponding "
9423aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis                                "framebuffer dimensions. Attachment dimensions must be at least as large. Here are the respective "
9424aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis                                "dimensions for "
9425aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis                                "attachment #%u, framebuffer:\n"
9426aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis                                "width: %u, %u\n"
9427aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis                                "height: %u, %u\n"
9428aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis                                "layerCount: %u, %u\n",
942979fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                                i, ivci.subresourceRange.baseMipLevel, i, mip_width, pCreateInfo->width, mip_height,
943079fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                                pCreateInfo->height, ivci.subresourceRange.layerCount, pCreateInfo->layers);
94315ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                }
943279fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                if (((ivci.components.r != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.r != VK_COMPONENT_SWIZZLE_R)) ||
943379fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                    ((ivci.components.g != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.g != VK_COMPONENT_SWIZZLE_G)) ||
943479fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                    ((ivci.components.b != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.b != VK_COMPONENT_SWIZZLE_B)) ||
943579fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                    ((ivci.components.a != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.a != VK_COMPONENT_SWIZZLE_A))) {
9436da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis                    skip_call |= log_msg(
94376fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__,
9438da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis                        DRAWSTATE_INVALID_FRAMEBUFFER_CREATE_INFO, "DS",
9439da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis                        "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has non-identy swizzle. All framebuffer "
9440da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis                        "attachments must have been created with the identity swizzle. Here are the actual swizzle values:\n"
9441da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis                        "r swizzle = %s\n"
9442da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis                        "g swizzle = %s\n"
9443da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis                        "b swizzle = %s\n"
9444da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis                        "a swizzle = %s\n",
944579fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                        i, string_VkComponentSwizzle(ivci.components.r), string_VkComponentSwizzle(ivci.components.g),
944679fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                        string_VkComponentSwizzle(ivci.components.b), string_VkComponentSwizzle(ivci.components.a));
94475ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                }
94485ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis            }
9449d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis        }
94505ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis        // Verify correct attachment usage flags
94516600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski        for (uint32_t subpass = 0; subpass < rpci->subpassCount; subpass++) {
94526600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski            // Verify input attachments:
94536600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski            skip_call |= MatchUsage(dev_data, rpci->pSubpasses[subpass].inputAttachmentCount,
94546600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                                    rpci->pSubpasses[subpass].pInputAttachments, pCreateInfo, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT);
94556600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski            // Verify color attachments:
94566600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski            skip_call |= MatchUsage(dev_data, rpci->pSubpasses[subpass].colorAttachmentCount,
94576600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                                    rpci->pSubpasses[subpass].pColorAttachments, pCreateInfo, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
94586600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski            // Verify depth/stencil attachments:
94596600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski            if (rpci->pSubpasses[subpass].pDepthStencilAttachment != nullptr) {
94606600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                skip_call |= MatchUsage(dev_data, 1, rpci->pSubpasses[subpass].pDepthStencilAttachment, pCreateInfo,
94616600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                                        VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
94626600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski            }
94636600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski        }
9464d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis    } else {
9465d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis        skip_call |=
9466d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis            log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
9467d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis                    reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
9468d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis                    "vkCreateFramebuffer(): Attempt to create framebuffer with invalid renderPass (0x%" PRIxLEAST64 ").",
9469d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis                    reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass));
94706600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski    }
94716fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis    // Verify FB dimensions are within physical device limits
94726fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis    if ((pCreateInfo->height > dev_data->phys_dev_properties.properties.limits.maxFramebufferHeight) ||
94736fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis        (pCreateInfo->width > dev_data->phys_dev_properties.properties.limits.maxFramebufferWidth) ||
94746fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis        (pCreateInfo->layers > dev_data->phys_dev_properties.properties.limits.maxFramebufferLayers)) {
94756fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis        skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__,
94766fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis                             DRAWSTATE_INVALID_FRAMEBUFFER_CREATE_INFO, "DS",
94776fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis                             "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo dimensions exceed physical device limits. "
94786fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis                             "Here are the respective dimensions: requested, device max:\n"
94796fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis                             "width: %u, %u\n"
94806fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis                             "height: %u, %u\n"
94816fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis                             "layerCount: %u, %u\n",
94826fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis                             pCreateInfo->width, dev_data->phys_dev_properties.properties.limits.maxFramebufferWidth,
94836fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis                             pCreateInfo->height, dev_data->phys_dev_properties.properties.limits.maxFramebufferHeight,
94846fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis                             pCreateInfo->layers, dev_data->phys_dev_properties.properties.limits.maxFramebufferLayers);
94856fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis    }
94866600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski    return skip_call;
94876600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski}
94886600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski
948964c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis// Validate VkFramebufferCreateInfo state prior to calling down chain to create Framebuffer object
949064c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis//  Return true if an error is encountered and callback returns true to skip call down chain
949164c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis//   false indicates that call down chain should proceed
949264c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlisstatic bool PreCallValidateCreateFramebuffer(layer_data *dev_data, const VkFramebufferCreateInfo *pCreateInfo) {
949364c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis    // TODO : Verify that renderPass FB is created with is compatible with FB
949464c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis    bool skip_call = false;
9495d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis    skip_call |= ValidateFramebufferCreateInfo(dev_data, pCreateInfo);
949664c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis    return skip_call;
949764c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis}
949864c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis
949954e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis// CreateFramebuffer state has been validated and call down chain completed so record new framebuffer object
950054e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlisstatic void PostCallRecordCreateFramebuffer(layer_data *dev_data, const VkFramebufferCreateInfo *pCreateInfo, VkFramebuffer fb) {
950154e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis    // Shadow create info and store in map
950276f04ca0e692f9f15d5ef7e0c658c24d11f34ebcTobin Ehlis    std::unique_ptr<FRAMEBUFFER_NODE> fb_node(
9503fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes        new FRAMEBUFFER_NODE(fb, pCreateInfo, dev_data->renderPassMap[pCreateInfo->renderPass]->createInfo.ptr()));
950476f04ca0e692f9f15d5ef7e0c658c24d11f34ebcTobin Ehlis
950554e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis    for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) {
950654e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis        VkImageView view = pCreateInfo->pAttachments[i];
950779fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis        auto view_state = getImageViewState(dev_data, view);
950879fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis        if (!view_state) {
950954e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis            continue;
951054e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis        }
951154e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis        MT_FB_ATTACHMENT_INFO fb_info;
951279fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis        fb_info.mem = getImageNode(dev_data, view_state->create_info.image)->mem;
9513883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis        fb_info.view_state = view_state;
951479fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis        fb_info.image = view_state->create_info.image;
951576f04ca0e692f9f15d5ef7e0c658c24d11f34ebcTobin Ehlis        fb_node->attachments.push_back(fb_info);
951654e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis    }
951776f04ca0e692f9f15d5ef7e0c658c24d11f34ebcTobin Ehlis    dev_data->frameBufferMap[fb] = std::move(fb_node);
951854e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis}
951954e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis
952089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo *pCreateInfo,
952189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                 const VkAllocationCallbacks *pAllocator,
952289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                 VkFramebuffer *pFramebuffer) {
95235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
952464c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis    std::unique_lock<std::mutex> lock(global_lock);
952564c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis    bool skip_call = PreCallValidateCreateFramebuffer(dev_data, pCreateInfo);
952664c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis    lock.unlock();
952764c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis
952864c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis    if (skip_call)
952964c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis        return VK_ERROR_VALIDATION_FAILED_EXT;
953064c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis
95314a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateFramebuffer(device, pCreateInfo, pAllocator, pFramebuffer);
95326600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski
95335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
953464c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis        lock.lock();
953554e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis        PostCallRecordCreateFramebuffer(dev_data, pCreateInfo, *pFramebuffer);
953654e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis        lock.unlock();
95375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
95385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
95395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
95405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
9541e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool FindDependency(const int index, const int dependent, const std::vector<DAGNode> &subpass_to_node,
9542e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                           std::unordered_set<uint32_t> &processed_nodes) {
95435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // If we have already checked this node we have not found a dependency path so return false.
95445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (processed_nodes.count(index))
9545e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        return false;
95465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    processed_nodes.insert(index);
95475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    const DAGNode &node = subpass_to_node[index];
95485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Look for a dependency path. If one exists return true else recurse on the previous nodes.
95495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (std::find(node.prev.begin(), node.prev.end(), dependent) == node.prev.end()) {
95505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (auto elem : node.prev) {
95515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (FindDependency(elem, dependent, subpass_to_node, processed_nodes))
9552e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                return true;
95535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
95545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
9555e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        return true;
95565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
9557e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    return false;
95585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
95595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
95608860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool CheckDependencyExists(const layer_data *dev_data, const int subpass, const std::vector<uint32_t> &dependent_subpasses,
9561e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                                  const std::vector<DAGNode> &subpass_to_node, bool &skip_call) {
9562e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool result = true;
95635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Loop through all subpasses that share the same attachment and make sure a dependency exists
95645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t k = 0; k < dependent_subpasses.size(); ++k) {
95651d5109d5e0dcc530b27e632e73e1be5e12a28dcdJamie Madill        if (static_cast<uint32_t>(subpass) == dependent_subpasses[k])
95665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            continue;
95675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        const DAGNode &node = subpass_to_node[subpass];
95685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Check for a specified dependency between the two nodes. If one exists we are done.
95695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto prev_elem = std::find(node.prev.begin(), node.prev.end(), dependent_subpasses[k]);
95705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto next_elem = std::find(node.next.begin(), node.next.end(), dependent_subpasses[k]);
95715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (prev_elem == node.prev.end() && next_elem == node.next.end()) {
95727655cb8b5eb52badee0b011729a05afa36316d69Jan-Harald Fredriksen            // If no dependency exits an implicit dependency still might. If not, throw an error.
95735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            std::unordered_set<uint32_t> processed_nodes;
95747655cb8b5eb52badee0b011729a05afa36316d69Jan-Harald Fredriksen            if (!(FindDependency(subpass, dependent_subpasses[k], subpass_to_node, processed_nodes) ||
95757655cb8b5eb52badee0b011729a05afa36316d69Jan-Harald Fredriksen                FindDependency(dependent_subpasses[k], subpass, subpass_to_node, processed_nodes))) {
95768860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
95775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                     __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
95785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                     "A dependency between subpasses %d and %d must exist but one is not specified.", subpass,
95795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                     dependent_subpasses[k]);
9580e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                result = false;
95815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
95825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
95835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
95845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
95855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
95865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
95878860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool CheckPreserved(const layer_data *dev_data, const VkRenderPassCreateInfo *pCreateInfo, const int index,
9588e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                           const uint32_t attachment, const std::vector<DAGNode> &subpass_to_node, int depth, bool &skip_call) {
95895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    const DAGNode &node = subpass_to_node[index];
95905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // If this node writes to the attachment return true as next nodes need to preserve the attachment.
95915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[index];
95925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
95935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (attachment == subpass.pColorAttachments[j].attachment)
9594e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves            return true;
95955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
95965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
95975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (attachment == subpass.pDepthStencilAttachment->attachment)
9598e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves            return true;
95995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
9600e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool result = false;
96015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Loop through previous nodes and see if any of them write to the attachment.
96025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (auto elem : node.prev) {
96038860b85a52096f9f9b28616bc37feed505497a54Chris Forbes        result |= CheckPreserved(dev_data, pCreateInfo, elem, attachment, subpass_to_node, depth + 1, skip_call);
96045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
96055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // If the attachment was written to by a previous node than this node needs to preserve it.
96065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (result && depth > 0) {
96075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[index];
9608e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        bool has_preserved = false;
96095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t j = 0; j < subpass.preserveAttachmentCount; ++j) {
96105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (subpass.pPreserveAttachments[j] == attachment) {
9611e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                has_preserved = true;
96125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                break;
96135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
96145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
9615e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        if (!has_preserved) {
96165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            skip_call |=
96178860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
96185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        DRAWSTATE_INVALID_RENDERPASS, "DS",
96195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        "Attachment %d is used by a later subpass and must be preserved in subpass %d.", attachment, index);
96205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
96215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
96225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
96235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
96245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
96255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlistemplate <class T> bool isRangeOverlapping(T offset1, T size1, T offset2, T size2) {
96265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return (((offset1 + size1) > offset2) && ((offset1 + size1) < (offset2 + size2))) ||
96275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis           ((offset1 > offset2) && (offset1 < (offset2 + size2)));
96285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
96295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
96305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisbool isRegionOverlapping(VkImageSubresourceRange range1, VkImageSubresourceRange range2) {
96315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return (isRangeOverlapping(range1.baseMipLevel, range1.levelCount, range2.baseMipLevel, range2.levelCount) &&
96325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            isRangeOverlapping(range1.baseArrayLayer, range1.layerCount, range2.baseArrayLayer, range2.layerCount));
96335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
96345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
96358860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool ValidateDependencies(const layer_data *dev_data, FRAMEBUFFER_NODE const *framebuffer,
96368860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                                 RENDER_PASS_NODE const *renderPass) {
9637e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool skip_call = false;
9638fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes    auto const pFramebufferInfo = framebuffer->createInfo.ptr();
9639fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes    auto const pCreateInfo = renderPass->createInfo.ptr();
964016387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes    auto const & subpass_to_node = renderPass->subpassToNode;
96415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    std::vector<std::vector<uint32_t>> output_attachment_to_subpass(pCreateInfo->attachmentCount);
96425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    std::vector<std::vector<uint32_t>> input_attachment_to_subpass(pCreateInfo->attachmentCount);
96435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    std::vector<std::vector<uint32_t>> overlapping_attachments(pCreateInfo->attachmentCount);
96445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Find overlapping attachments
96455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) {
96465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t j = i + 1; j < pCreateInfo->attachmentCount; ++j) {
96475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            VkImageView viewi = pFramebufferInfo->pAttachments[i];
96485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            VkImageView viewj = pFramebufferInfo->pAttachments[j];
96495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (viewi == viewj) {
96505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                overlapping_attachments[i].push_back(j);
96515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                overlapping_attachments[j].push_back(i);
96525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                continue;
96535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
96548860b85a52096f9f9b28616bc37feed505497a54Chris Forbes            auto view_state_i = getImageViewState(dev_data, viewi);
96558860b85a52096f9f9b28616bc37feed505497a54Chris Forbes            auto view_state_j = getImageViewState(dev_data, viewj);
965679fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis            if (!view_state_i || !view_state_j) {
96575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                continue;
96585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
965979fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis            auto view_ci_i = view_state_i->create_info;
966079fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis            auto view_ci_j = view_state_j->create_info;
966179fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis            if (view_ci_i.image == view_ci_j.image && isRegionOverlapping(view_ci_i.subresourceRange, view_ci_j.subresourceRange)) {
96625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                overlapping_attachments[i].push_back(j);
96635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                overlapping_attachments[j].push_back(i);
96645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                continue;
96655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
96668860b85a52096f9f9b28616bc37feed505497a54Chris Forbes            auto image_data_i = getImageNode(dev_data, view_ci_i.image);
96678860b85a52096f9f9b28616bc37feed505497a54Chris Forbes            auto image_data_j = getImageNode(dev_data, view_ci_j.image);
96686d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            if (!image_data_i || !image_data_j) {
96695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                continue;
96705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
96716d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            if (image_data_i->mem == image_data_j->mem && isRangeOverlapping(image_data_i->memOffset, image_data_i->memSize,
96726d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis                                                                             image_data_j->memOffset, image_data_j->memSize)) {
96735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                overlapping_attachments[i].push_back(j);
96745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                overlapping_attachments[j].push_back(i);
96755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
96765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
96775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
96785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < overlapping_attachments.size(); ++i) {
96795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        uint32_t attachment = i;
96805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (auto other_attachment : overlapping_attachments[i]) {
96815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (!(pCreateInfo->pAttachments[attachment].flags & VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT)) {
96825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                skip_call |=
96838860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
96845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            DRAWSTATE_INVALID_RENDERPASS, "DS", "Attachment %d aliases attachment %d but doesn't "
96855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                                "set VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT.",
96865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            attachment, other_attachment);
96875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
96885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (!(pCreateInfo->pAttachments[other_attachment].flags & VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT)) {
96895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                skip_call |=
96908860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
96915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            DRAWSTATE_INVALID_RENDERPASS, "DS", "Attachment %d aliases attachment %d but doesn't "
96925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                                "set VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT.",
96935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            other_attachment, attachment);
96945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
96955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
96965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
96975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Find for each attachment the subpasses that use them.
96981c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young    unordered_set<uint32_t> attachmentIndices;
96995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
97005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i];
97011c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young        attachmentIndices.clear();
97025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
97035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            uint32_t attachment = subpass.pInputAttachments[j].attachment;
970493fe72ec8460857bdb3c101095e6eb96d6171341Chris Forbes            if (attachment == VK_ATTACHMENT_UNUSED)
970593fe72ec8460857bdb3c101095e6eb96d6171341Chris Forbes                continue;
97065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            input_attachment_to_subpass[attachment].push_back(i);
97075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            for (auto overlapping_attachment : overlapping_attachments[attachment]) {
97085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                input_attachment_to_subpass[overlapping_attachment].push_back(i);
97095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
97105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
97115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
97125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            uint32_t attachment = subpass.pColorAttachments[j].attachment;
971393fe72ec8460857bdb3c101095e6eb96d6171341Chris Forbes            if (attachment == VK_ATTACHMENT_UNUSED)
971493fe72ec8460857bdb3c101095e6eb96d6171341Chris Forbes                continue;
97155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            output_attachment_to_subpass[attachment].push_back(i);
97165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            for (auto overlapping_attachment : overlapping_attachments[attachment]) {
97175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                output_attachment_to_subpass[overlapping_attachment].push_back(i);
97185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
97191c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young            attachmentIndices.insert(attachment);
97205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
97215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
97225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            uint32_t attachment = subpass.pDepthStencilAttachment->attachment;
97235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            output_attachment_to_subpass[attachment].push_back(i);
97245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            for (auto overlapping_attachment : overlapping_attachments[attachment]) {
97255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                output_attachment_to_subpass[overlapping_attachment].push_back(i);
97265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
97271c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young
97281c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young            if (attachmentIndices.count(attachment)) {
97291c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young                skip_call |=
97308860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
97318860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                            DRAWSTATE_INVALID_RENDERPASS, "DS",
97328860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                            "Cannot use same attachment (%u) as both color and depth output in same subpass (%u).", attachment, i);
97331c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young            }
97345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
97355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
97365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // If there is a dependency needed make sure one exists
97375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
97385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i];
97395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // If the attachment is an input then all subpasses that output must have a dependency relationship
97405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
974193fe72ec8460857bdb3c101095e6eb96d6171341Chris Forbes            uint32_t attachment = subpass.pInputAttachments[j].attachment;
974293fe72ec8460857bdb3c101095e6eb96d6171341Chris Forbes            if (attachment == VK_ATTACHMENT_UNUSED)
974393fe72ec8460857bdb3c101095e6eb96d6171341Chris Forbes                continue;
97448860b85a52096f9f9b28616bc37feed505497a54Chris Forbes            CheckDependencyExists(dev_data, i, output_attachment_to_subpass[attachment], subpass_to_node, skip_call);
97455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
97465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // If the attachment is an output then all subpasses that use the attachment must have a dependency relationship
97475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
974893fe72ec8460857bdb3c101095e6eb96d6171341Chris Forbes            uint32_t attachment = subpass.pColorAttachments[j].attachment;
974993fe72ec8460857bdb3c101095e6eb96d6171341Chris Forbes            if (attachment == VK_ATTACHMENT_UNUSED)
975093fe72ec8460857bdb3c101095e6eb96d6171341Chris Forbes                continue;
97518860b85a52096f9f9b28616bc37feed505497a54Chris Forbes            CheckDependencyExists(dev_data, i, output_attachment_to_subpass[attachment], subpass_to_node, skip_call);
97528860b85a52096f9f9b28616bc37feed505497a54Chris Forbes            CheckDependencyExists(dev_data, i, input_attachment_to_subpass[attachment], subpass_to_node, skip_call);
97535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
97545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
97555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            const uint32_t &attachment = subpass.pDepthStencilAttachment->attachment;
97568860b85a52096f9f9b28616bc37feed505497a54Chris Forbes            CheckDependencyExists(dev_data, i, output_attachment_to_subpass[attachment], subpass_to_node, skip_call);
97578860b85a52096f9f9b28616bc37feed505497a54Chris Forbes            CheckDependencyExists(dev_data, i, input_attachment_to_subpass[attachment], subpass_to_node, skip_call);
97585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
97595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
97605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Loop through implicit dependencies, if this pass reads make sure the attachment is preserved for all passes after it was
97615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // written.
97625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
97635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i];
97645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
97658860b85a52096f9f9b28616bc37feed505497a54Chris Forbes            CheckPreserved(dev_data, pCreateInfo, i, subpass.pInputAttachments[j].attachment, subpass_to_node, 0, skip_call);
97665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
97675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
97685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return skip_call;
97695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
9770be45dd763c94dfcb0b52709d8d613848c4c914e1Tobin Ehlis// ValidateLayoutVsAttachmentDescription is a general function where we can validate various state associated with the
9771be45dd763c94dfcb0b52709d8d613848c4c914e1Tobin Ehlis// VkAttachmentDescription structs that are used by the sub-passes of a renderpass. Initial check is to make sure that
9772be45dd763c94dfcb0b52709d8d613848c4c914e1Tobin Ehlis// READ_ONLY layout attachments don't have CLEAR as their loadOp.
9773be45dd763c94dfcb0b52709d8d613848c4c914e1Tobin Ehlisstatic bool ValidateLayoutVsAttachmentDescription(debug_report_data *report_data, const VkImageLayout first_layout,
9774be45dd763c94dfcb0b52709d8d613848c4c914e1Tobin Ehlis                                                  const uint32_t attachment,
9775be45dd763c94dfcb0b52709d8d613848c4c914e1Tobin Ehlis                                                  const VkAttachmentDescription &attachment_description) {
9776be45dd763c94dfcb0b52709d8d613848c4c914e1Tobin Ehlis    bool skip_call = false;
9777be45dd763c94dfcb0b52709d8d613848c4c914e1Tobin Ehlis    // Verify that initial loadOp on READ_ONLY attachments is not CLEAR
9778be45dd763c94dfcb0b52709d8d613848c4c914e1Tobin Ehlis    if (attachment_description.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR) {
9779be45dd763c94dfcb0b52709d8d613848c4c914e1Tobin Ehlis        if ((first_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL) ||
9780be45dd763c94dfcb0b52709d8d613848c4c914e1Tobin Ehlis            (first_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)) {
9781be45dd763c94dfcb0b52709d8d613848c4c914e1Tobin Ehlis            skip_call |=
9782be45dd763c94dfcb0b52709d8d613848c4c914e1Tobin Ehlis                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
9783be45dd763c94dfcb0b52709d8d613848c4c914e1Tobin Ehlis                        VkDebugReportObjectTypeEXT(0), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
9784be45dd763c94dfcb0b52709d8d613848c4c914e1Tobin Ehlis                        "Cannot clear attachment %d with invalid first layout %s.", attachment, string_VkImageLayout(first_layout));
9785be45dd763c94dfcb0b52709d8d613848c4c914e1Tobin Ehlis        }
9786be45dd763c94dfcb0b52709d8d613848c4c914e1Tobin Ehlis    }
9787be45dd763c94dfcb0b52709d8d613848c4c914e1Tobin Ehlis    return skip_call;
9788be45dd763c94dfcb0b52709d8d613848c4c914e1Tobin Ehlis}
97895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
97908860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool ValidateLayouts(const layer_data *dev_data, VkDevice device, const VkRenderPassCreateInfo *pCreateInfo) {
9791e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool skip = false;
97925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
979377c531defc2e8614acee0969b170cc2fa68f55d3Tobin Ehlis    // Track when we're observing the first use of an attachment
979477c531defc2e8614acee0969b170cc2fa68f55d3Tobin Ehlis    std::vector<bool> attach_first_use(pCreateInfo->attachmentCount, true);
97955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
97965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i];
97975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
97980ad39e0de2f23ebec8c8ffbf6b54754ebf5ae9a7Chris Forbes            auto attach_index = subpass.pColorAttachments[j].attachment;
97990ad39e0de2f23ebec8c8ffbf6b54754ebf5ae9a7Chris Forbes            if (attach_index == VK_ATTACHMENT_UNUSED)
98000ad39e0de2f23ebec8c8ffbf6b54754ebf5ae9a7Chris Forbes                continue;
98010ad39e0de2f23ebec8c8ffbf6b54754ebf5ae9a7Chris Forbes
9802c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes            switch (subpass.pColorAttachments[j].layout) {
9803c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes            case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
9804c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes                /* This is ideal. */
9805c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes                break;
9806c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes
9807c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes            case VK_IMAGE_LAYOUT_GENERAL:
9808c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes                /* May not be optimal; TODO: reconsider this warning based on
9809c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes                 * other constraints?
9810c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes                 */
98118860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
98128860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                                VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
9813c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes                                "Layout for color attachment is GENERAL but should be COLOR_ATTACHMENT_OPTIMAL.");
9814c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes                break;
9815c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes
9816c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes            default:
98178860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
98188860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                                __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
9819c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes                                "Layout for color attachment is %s but can only be COLOR_ATTACHMENT_OPTIMAL or GENERAL.",
9820c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes                                string_VkImageLayout(subpass.pColorAttachments[j].layout));
98215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
9822c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes
982377c531defc2e8614acee0969b170cc2fa68f55d3Tobin Ehlis            if (attach_first_use[attach_index]) {
98248860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                skip |= ValidateLayoutVsAttachmentDescription(dev_data->report_data, subpass.pColorAttachments[j].layout,
982577c531defc2e8614acee0969b170cc2fa68f55d3Tobin Ehlis                                                              attach_index, pCreateInfo->pAttachments[attach_index]);
982677c531defc2e8614acee0969b170cc2fa68f55d3Tobin Ehlis            }
982777c531defc2e8614acee0969b170cc2fa68f55d3Tobin Ehlis            attach_first_use[attach_index] = false;
98285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
9829c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes        if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
9830cfa128db908c2462aaf616950fb2fdb9d2f92bc1Chris Forbes            switch (subpass.pDepthStencilAttachment->layout) {
9831cfa128db908c2462aaf616950fb2fdb9d2f92bc1Chris Forbes            case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
9832cfa128db908c2462aaf616950fb2fdb9d2f92bc1Chris Forbes            case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
9833cfa128db908c2462aaf616950fb2fdb9d2f92bc1Chris Forbes                /* These are ideal. */
9834cfa128db908c2462aaf616950fb2fdb9d2f92bc1Chris Forbes                break;
9835cfa128db908c2462aaf616950fb2fdb9d2f92bc1Chris Forbes
9836cfa128db908c2462aaf616950fb2fdb9d2f92bc1Chris Forbes            case VK_IMAGE_LAYOUT_GENERAL:
9837cfa128db908c2462aaf616950fb2fdb9d2f92bc1Chris Forbes                /* May not be optimal; TODO: reconsider this warning based on
9838cfa128db908c2462aaf616950fb2fdb9d2f92bc1Chris Forbes                 * other constraints? GENERAL can be better than doing a bunch
9839cfa128db908c2462aaf616950fb2fdb9d2f92bc1Chris Forbes                 * of transitions.
9840cfa128db908c2462aaf616950fb2fdb9d2f92bc1Chris Forbes                 */
98418860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
98428860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                                VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
9843cfa128db908c2462aaf616950fb2fdb9d2f92bc1Chris Forbes                                "GENERAL layout for depth attachment may not give optimal performance.");
9844cfa128db908c2462aaf616950fb2fdb9d2f92bc1Chris Forbes                break;
9845cfa128db908c2462aaf616950fb2fdb9d2f92bc1Chris Forbes
9846cfa128db908c2462aaf616950fb2fdb9d2f92bc1Chris Forbes            default:
9847cfa128db908c2462aaf616950fb2fdb9d2f92bc1Chris Forbes                /* No other layouts are acceptable */
98488860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
98498860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                                __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
9850cfa128db908c2462aaf616950fb2fdb9d2f92bc1Chris Forbes                                "Layout for depth attachment is %s but can only be DEPTH_STENCIL_ATTACHMENT_OPTIMAL, "
9851cfa128db908c2462aaf616950fb2fdb9d2f92bc1Chris Forbes                                "DEPTH_STENCIL_READ_ONLY_OPTIMAL or GENERAL.",
98525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                string_VkImageLayout(subpass.pDepthStencilAttachment->layout));
98535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
9854cfa128db908c2462aaf616950fb2fdb9d2f92bc1Chris Forbes
9855be45dd763c94dfcb0b52709d8d613848c4c914e1Tobin Ehlis            auto attach_index = subpass.pDepthStencilAttachment->attachment;
985677c531defc2e8614acee0969b170cc2fa68f55d3Tobin Ehlis            if (attach_first_use[attach_index]) {
98578860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                skip |= ValidateLayoutVsAttachmentDescription(dev_data->report_data, subpass.pDepthStencilAttachment->layout,
985877c531defc2e8614acee0969b170cc2fa68f55d3Tobin Ehlis                                                              attach_index, pCreateInfo->pAttachments[attach_index]);
985977c531defc2e8614acee0969b170cc2fa68f55d3Tobin Ehlis            }
986077c531defc2e8614acee0969b170cc2fa68f55d3Tobin Ehlis            attach_first_use[attach_index] = false;
986177c531defc2e8614acee0969b170cc2fa68f55d3Tobin Ehlis        }
986277c531defc2e8614acee0969b170cc2fa68f55d3Tobin Ehlis        for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
986377c531defc2e8614acee0969b170cc2fa68f55d3Tobin Ehlis            auto attach_index = subpass.pInputAttachments[j].attachment;
986477c531defc2e8614acee0969b170cc2fa68f55d3Tobin Ehlis            if (attach_index == VK_ATTACHMENT_UNUSED)
986577c531defc2e8614acee0969b170cc2fa68f55d3Tobin Ehlis                continue;
986677c531defc2e8614acee0969b170cc2fa68f55d3Tobin Ehlis
9867c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes            switch (subpass.pInputAttachments[j].layout) {
9868c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes            case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
9869c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes            case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
9870c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes                /* These are ideal. */
9871c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes                break;
9872c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes
9873c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes            case VK_IMAGE_LAYOUT_GENERAL:
9874c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes                /* May not be optimal. TODO: reconsider this warning based on
9875c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes                 * other constraints.
9876c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes                 */
98778860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
98788860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                                VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
9879c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes                                "Layout for input attachment is GENERAL but should be READ_ONLY_OPTIMAL.");
9880c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes                break;
9881c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes
9882c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes            default:
9883c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes                /* No other layouts are acceptable */
98848860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
9885c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes                                DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
9886c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes                                "Layout for input attachment is %s but can only be READ_ONLY_OPTIMAL or GENERAL.",
9887c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes                                string_VkImageLayout(subpass.pInputAttachments[j].layout));
988877c531defc2e8614acee0969b170cc2fa68f55d3Tobin Ehlis            }
9889c74f9e8c7fe6b470f757da0c42367fe725fe0928Chris Forbes
989077c531defc2e8614acee0969b170cc2fa68f55d3Tobin Ehlis            if (attach_first_use[attach_index]) {
98918860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                skip |= ValidateLayoutVsAttachmentDescription(dev_data->report_data, subpass.pInputAttachments[j].layout,
989277c531defc2e8614acee0969b170cc2fa68f55d3Tobin Ehlis                                                              attach_index, pCreateInfo->pAttachments[attach_index]);
989377c531defc2e8614acee0969b170cc2fa68f55d3Tobin Ehlis            }
989477c531defc2e8614acee0969b170cc2fa68f55d3Tobin Ehlis            attach_first_use[attach_index] = false;
98955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
98965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
98975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return skip;
98985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
98995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
99008860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool CreatePassDAG(const layer_data *dev_data, VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
9901e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                          std::vector<DAGNode> &subpass_to_node, std::vector<bool> &has_self_dependency) {
9902e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool skip_call = false;
99035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
99045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        DAGNode &subpass_node = subpass_to_node[i];
99055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        subpass_node.pass = i;
99065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
99075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < pCreateInfo->dependencyCount; ++i) {
99085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        const VkSubpassDependency &dependency = pCreateInfo->pDependencies[i];
990966a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes        if (dependency.srcSubpass == VK_SUBPASS_EXTERNAL || dependency.dstSubpass == VK_SUBPASS_EXTERNAL) {
991066a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes            if (dependency.srcSubpass == dependency.dstSubpass) {
991166a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes                skip_call |=
99128860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
991366a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes                            DRAWSTATE_INVALID_RENDERPASS, "DS", "The src and dest subpasses cannot both be external.");
991466a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes            }
991566a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes
991666a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes            // We don't want to add edges to the DAG for dependencies to/from
991766a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes            // VK_SUBPASS_EXTERNAL. We don't use them for anything, and their
991866a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes            // presence complicates other code.
991966a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes            continue;
992066a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes        } else if (dependency.srcSubpass > dependency.dstSubpass) {
99218860b85a52096f9f9b28616bc37feed505497a54Chris Forbes            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
99225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                 DRAWSTATE_INVALID_RENDERPASS, "DS",
99235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                 "Depedency graph must be specified such that an earlier pass cannot depend on a later pass.");
99245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else if (dependency.srcSubpass == dependency.dstSubpass) {
99255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            has_self_dependency[dependency.srcSubpass] = true;
99265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
992766a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes
992866a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes        subpass_to_node[dependency.dstSubpass].prev.push_back(dependency.srcSubpass);
992966a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes        subpass_to_node[dependency.srcSubpass].next.push_back(dependency.dstSubpass);
99305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
99315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return skip_call;
99325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
9933918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes
99345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
993589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
993689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                  const VkAllocationCallbacks *pAllocator,
993789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                  VkShaderModule *pShaderModule) {
99388860b85a52096f9f9b28616bc37feed505497a54Chris Forbes    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
9939e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool skip_call = false;
9940b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes
9941b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes    /* Use SPIRV-Tools validator to try and catch any issues with the module itself */
9942b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes    spv_context ctx = spvContextCreate(SPV_ENV_VULKAN_1_0);
9943b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes    spv_const_binary_t binary { pCreateInfo->pCode, pCreateInfo->codeSize / sizeof(uint32_t) };
9944b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes    spv_diagnostic diag = nullptr;
9945b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes
9946b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes    auto result = spvValidate(ctx, &binary, &diag);
9947b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes    if (result != SPV_SUCCESS) {
99488860b85a52096f9f9b28616bc37feed505497a54Chris Forbes        skip_call |=
99498860b85a52096f9f9b28616bc37feed505497a54Chris Forbes            log_msg(dev_data->report_data, result == SPV_WARNING ? VK_DEBUG_REPORT_WARNING_BIT_EXT : VK_DEBUG_REPORT_ERROR_BIT_EXT,
99508860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                    VkDebugReportObjectTypeEXT(0), 0, __LINE__, SHADER_CHECKER_INCONSISTENT_SPIRV, "SC",
99518860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                    "SPIR-V module not valid: %s", diag && diag->error ? diag->error : "(no error text)");
99525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
99535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
9954b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes    spvDiagnosticDestroy(diag);
9955b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes    spvContextDestroy(ctx);
9956b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes
9957e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    if (skip_call)
99585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return VK_ERROR_VALIDATION_FAILED_EXT;
99595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
99604a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult res = dev_data->dispatch_table.CreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
99615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
99625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (res == VK_SUCCESS) {
9963b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        std::lock_guard<std::mutex> lock(global_lock);
99648860b85a52096f9f9b28616bc37feed505497a54Chris Forbes        dev_data->shaderModuleMap[*pShaderModule] = unique_ptr<shader_module>(new shader_module(pCreateInfo));
99655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
99665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return res;
99675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
99685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
99694f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinskistatic bool ValidateAttachmentIndex(layer_data *dev_data, uint32_t attachment, uint32_t attachment_count, const char *type) {
99704f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    bool skip_call = false;
99714f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    if (attachment >= attachment_count && attachment != VK_ATTACHMENT_UNUSED) {
99724f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
99734f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski                             DRAWSTATE_INVALID_ATTACHMENT_INDEX, "DS",
99744f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski                             "CreateRenderPass: %s attachment %d cannot be greater than the total number of attachments %d.",
99754f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski                             type, attachment, attachment_count);
99764f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    }
99774f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    return skip_call;
99784f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski}
99794f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski
9980805ec497391f6bc513f7653ba6d535c509b54062Chris Forbesstatic bool IsPowerOfTwo(unsigned x) {
9981805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes    return x && !(x & (x-1));
9982805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes}
9983805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes
99844f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinskistatic bool ValidateRenderpassAttachmentUsage(layer_data *dev_data, const VkRenderPassCreateInfo *pCreateInfo) {
99854f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    bool skip_call = false;
99864f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
99874f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i];
99884f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        if (subpass.pipelineBindPoint != VK_PIPELINE_BIND_POINT_GRAPHICS) {
99894f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            skip_call |=
99904f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
99914f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski                        DRAWSTATE_INVALID_RENDERPASS, "DS",
99924f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski                        "CreateRenderPass: Pipeline bind point for subpass %d must be VK_PIPELINE_BIND_POINT_GRAPHICS.", i);
99934f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        }
99944f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        for (uint32_t j = 0; j < subpass.preserveAttachmentCount; ++j) {
99954f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            uint32_t attachment = subpass.pPreserveAttachments[j];
99964f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            if (attachment == VK_ATTACHMENT_UNUSED) {
99974f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski                skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
99984f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski                                     __LINE__, DRAWSTATE_INVALID_ATTACHMENT_INDEX, "DS",
99994f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski                                     "CreateRenderPass:  Preserve attachment (%d) must not be VK_ATTACHMENT_UNUSED.", j);
100004f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            } else {
100014f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski                skip_call |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Preserve");
100024f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            }
100034f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        }
100046a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes
100056a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes        auto subpass_performs_resolve = subpass.pResolveAttachments && std::any_of(
100066a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes            subpass.pResolveAttachments, subpass.pResolveAttachments + subpass.colorAttachmentCount,
100076a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes            [](VkAttachmentReference ref) { return ref.attachment != VK_ATTACHMENT_UNUSED; });
100086a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes
10009805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes        unsigned sample_count = 0;
10010805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes
100114f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
100124f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            uint32_t attachment;
100134f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            if (subpass.pResolveAttachments) {
100144f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski                attachment = subpass.pResolveAttachments[j].attachment;
100154f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski                skip_call |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Resolve");
100166a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes
100176a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes                if (!skip_call && attachment != VK_ATTACHMENT_UNUSED &&
100186a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes                    pCreateInfo->pAttachments[attachment].samples != VK_SAMPLE_COUNT_1_BIT) {
100196a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes                    skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0,
100206a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes                                         __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
100216a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes                                         "CreateRenderPass:  Subpass %u requests multisample resolve into attachment %u, "
100226a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes                                         "which must have VK_SAMPLE_COUNT_1_BIT but has %s",
100236a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes                                         i, attachment, string_VkSampleCountFlagBits(pCreateInfo->pAttachments[attachment].samples));
100246a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes                }
100254f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            }
100264f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            attachment = subpass.pColorAttachments[j].attachment;
100274f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            skip_call |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Color");
100286a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes
10029805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes            if (!skip_call && attachment != VK_ATTACHMENT_UNUSED) {
10030805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes                sample_count |= (unsigned)pCreateInfo->pAttachments[attachment].samples;
10031805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes
10032dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes                if (subpass_performs_resolve &&
10033dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes                    pCreateInfo->pAttachments[attachment].samples == VK_SAMPLE_COUNT_1_BIT) {
10034dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes                    skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0,
10035dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes                                         __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
10036dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes                                         "CreateRenderPass:  Subpass %u requests multisample resolve from attachment %u "
10037dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes                                         "which has VK_SAMPLE_COUNT_1_BIT",
10038dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes                                         i, attachment);
10039dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes                }
100406a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes            }
100414f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        }
10042dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes
100434f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
100444f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            uint32_t attachment = subpass.pDepthStencilAttachment->attachment;
100454f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            skip_call |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Depth stencil");
10046805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes
10047805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes            if (!skip_call && attachment != VK_ATTACHMENT_UNUSED) {
10048805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes                sample_count |= (unsigned)pCreateInfo->pAttachments[attachment].samples;
10049805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes            }
100504f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        }
10051dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes
100524f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
100534f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            uint32_t attachment = subpass.pInputAttachments[j].attachment;
100544f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            skip_call |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Input");
100554f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        }
10056805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes
10057805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes        if (sample_count && !IsPowerOfTwo(sample_count)) {
10058805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0,
10059805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes                                 __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
10060805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes                                 "CreateRenderPass:  Subpass %u attempts to render to "
10061805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes                                 "attachments with inconsistent sample counts",
10062805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes                                 i);
10063805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes        }
100644f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    }
100654f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    return skip_call;
100664f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski}
100674f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski
1006889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
100694f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski                                                const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) {
10070e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool skip_call = false;
100715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
100724f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski
100734f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    std::unique_lock<std::mutex> lock(global_lock);
100744f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski
100754f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    skip_call |= ValidateLayouts(dev_data, device, pCreateInfo);
100764f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    // TODO: As part of wrapping up the mem_tracker/core_validation merge the following routine should be consolidated with
100774f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    //       ValidateLayouts.
100784f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    skip_call |= ValidateRenderpassAttachmentUsage(dev_data, pCreateInfo);
10079ff6101de02d1677fb54962e2ff57875e76898e26Chris Forbes    lock.unlock();
100804f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski
100814f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    if (skip_call) {
100824f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        return VK_ERROR_VALIDATION_FAILED_EXT;
100834f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    }
100844f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski
100854a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass);
10086ff6101de02d1677fb54962e2ff57875e76898e26Chris Forbes
100875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
100884f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        lock.lock();
100894f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski
100904f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        std::vector<bool> has_self_dependency(pCreateInfo->subpassCount);
100914f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        std::vector<DAGNode> subpass_to_node(pCreateInfo->subpassCount);
100924f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        skip_call |= CreatePassDAG(dev_data, device, pCreateInfo, subpass_to_node, has_self_dependency);
100934f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski
10094fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes        auto render_pass = unique_ptr<RENDER_PASS_NODE>(new RENDER_PASS_NODE(pCreateInfo));
1009598cddf7090b5d5dcc382045867753ef703d1c3d3Chris Forbes        render_pass->renderPass = *pRenderPass;
10096cf2686cdbb12af8a29ca598c126b5e37215f0ef7Chris Forbes        render_pass->hasSelfDependency = has_self_dependency;
10097cf2686cdbb12af8a29ca598c126b5e37215f0ef7Chris Forbes        render_pass->subpassToNode = subpass_to_node;
10098db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes
1009987e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis        // TODO: Maybe fill list and then copy instead of locking
10100cf2686cdbb12af8a29ca598c126b5e37215f0ef7Chris Forbes        std::unordered_map<uint32_t, bool> &attachment_first_read = render_pass->attachment_first_read;
101016600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski        std::unordered_map<uint32_t, VkImageLayout> &attachment_first_layout = render_pass->attachment_first_layout;
1010287e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis        for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
1010387e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis            const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i];
1010487e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis            for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
101054f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski                uint32_t attachment = subpass.pColorAttachments[j].attachment;
101064f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski                if (!attachment_first_read.count(attachment)) {
101074f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski                    attachment_first_read.insert(std::make_pair(attachment, false));
101084f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski                    attachment_first_layout.insert(std::make_pair(attachment, subpass.pColorAttachments[j].layout));
101090d615f0a5724edac98475366cf3e486dccc1f2d6Michael Lentine                }
1011087e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis            }
1011187e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis            if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
1011287e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis                uint32_t attachment = subpass.pDepthStencilAttachment->attachment;
101134f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski                if (!attachment_first_read.count(attachment)) {
101144f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski                    attachment_first_read.insert(std::make_pair(attachment, false));
101154f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski                    attachment_first_layout.insert(std::make_pair(attachment, subpass.pDepthStencilAttachment->layout));
1011624991fb692f7e2d457da50d50c40f2705591300cMichael Lentine                }
1011787e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis            }
10118a5ce96d7c88653668a2b33a6b72bd3cb16d73f48Michael Lentine            for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
10119a5ce96d7c88653668a2b33a6b72bd3cb16d73f48Michael Lentine                uint32_t attachment = subpass.pInputAttachments[j].attachment;
101204f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski                if (!attachment_first_read.count(attachment)) {
101214f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski                    attachment_first_read.insert(std::make_pair(attachment, true));
101224f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski                    attachment_first_layout.insert(std::make_pair(attachment, subpass.pInputAttachments[j].layout));
1012324991fb692f7e2d457da50d50c40f2705591300cMichael Lentine                }
10124a5ce96d7c88653668a2b33a6b72bd3cb16d73f48Michael Lentine            }
1012587e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis        }
10126db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes
10127fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes        dev_data->renderPassMap[*pRenderPass] = std::move(render_pass);
101285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
101295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
101305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
101314f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski
10132e3ad4b1284408353cc56a04951c1df1f35a636ceChris Forbesstatic bool VerifyFramebufferAndRenderPassLayouts(layer_data *dev_data, GLOBAL_CB_NODE *pCB, const VkRenderPassBeginInfo *pRenderPassBegin) {
10133e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool skip_call = false;
10134fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes    auto const pRenderPassInfo = getRenderPass(dev_data, pRenderPassBegin->renderPass)->createInfo.ptr();
1013548a43d923a7b126a78770bd209d63902ffa0520aChris Forbes    auto const & framebufferInfo = dev_data->frameBufferMap[pRenderPassBegin->framebuffer]->createInfo;
101365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pRenderPassInfo->attachmentCount != framebufferInfo.attachmentCount) {
101375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
101385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                             DRAWSTATE_INVALID_RENDERPASS, "DS", "You cannot start a render pass using a framebuffer "
101395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                                 "with a different number of attachments.");
101405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
101415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < pRenderPassInfo->attachmentCount; ++i) {
101425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        const VkImageView &image_view = framebufferInfo.pAttachments[i];
1014379fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis        auto view_state = getImageViewState(dev_data, image_view);
1014479fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis        assert(view_state);
1014579fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis        const VkImage &image = view_state->create_info.image;
1014679fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis        const VkImageSubresourceRange &subRange = view_state->create_info.subresourceRange;
101475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        IMAGE_CMD_BUF_LAYOUT_NODE newNode = {pRenderPassInfo->pAttachments[i].initialLayout,
101485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                             pRenderPassInfo->pAttachments[i].initialLayout};
101495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // TODO: Do not iterate over every possibility - consolidate where possible
101505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t j = 0; j < subRange.levelCount; j++) {
101515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            uint32_t level = subRange.baseMipLevel + j;
101525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            for (uint32_t k = 0; k < subRange.layerCount; k++) {
101535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                uint32_t layer = subRange.baseArrayLayer + k;
101545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                VkImageSubresource sub = {subRange.aspectMask, level, layer};
101555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                IMAGE_CMD_BUF_LAYOUT_NODE node;
101565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if (!FindLayout(pCB, image, sub, node)) {
101575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    SetLayout(pCB, image, sub, newNode);
101585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    continue;
101595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
10160c83d821f524b75cbcfa5e8b661a3a605ea221b92Chris Forbes                if (newNode.layout != VK_IMAGE_LAYOUT_UNDEFINED &&
10161c83d821f524b75cbcfa5e8b661a3a605ea221b92Chris Forbes                    newNode.layout != node.layout) {
101625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    skip_call |=
101635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
10164c83d821f524b75cbcfa5e8b661a3a605ea221b92Chris Forbes                                DRAWSTATE_INVALID_RENDERPASS, "DS",
10165c83d821f524b75cbcfa5e8b661a3a605ea221b92Chris Forbes                                "You cannot start a render pass using attachment %u "
10166c83d821f524b75cbcfa5e8b661a3a605ea221b92Chris Forbes                                "where the render pass initial layout is %s and the previous "
10167c83d821f524b75cbcfa5e8b661a3a605ea221b92Chris Forbes                                "known layout of the attachment is %s. The layouts must match, or "
10168c83d821f524b75cbcfa5e8b661a3a605ea221b92Chris Forbes                                "the render pass initial layout for the attachment must be "
10169c83d821f524b75cbcfa5e8b661a3a605ea221b92Chris Forbes                                "VK_IMAGE_LAYOUT_UNDEFINED",
101701c0f4ce5068dadb12be8715c18a7769d9457b5eaMichael Lentine                                i, string_VkImageLayout(newNode.layout), string_VkImageLayout(node.layout));
101715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
101725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
101735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
101745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
101755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return skip_call;
101765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
101775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
10178628f0e370a17207a87d2632616fc8ca27e7ac80cChris Forbesstatic void TransitionAttachmentRefLayout(layer_data *dev_data, GLOBAL_CB_NODE *pCB,
10179628f0e370a17207a87d2632616fc8ca27e7ac80cChris Forbes                                          FRAMEBUFFER_NODE *pFramebuffer,
10180628f0e370a17207a87d2632616fc8ca27e7ac80cChris Forbes                                          VkAttachmentReference ref)
10181628f0e370a17207a87d2632616fc8ca27e7ac80cChris Forbes{
10182628f0e370a17207a87d2632616fc8ca27e7ac80cChris Forbes    if (ref.attachment != VK_ATTACHMENT_UNUSED) {
10183628f0e370a17207a87d2632616fc8ca27e7ac80cChris Forbes        auto image_view = pFramebuffer->createInfo.pAttachments[ref.attachment];
10184628f0e370a17207a87d2632616fc8ca27e7ac80cChris Forbes        SetLayout(dev_data, pCB, image_view, ref.layout);
10185628f0e370a17207a87d2632616fc8ca27e7ac80cChris Forbes    }
10186628f0e370a17207a87d2632616fc8ca27e7ac80cChris Forbes}
10187628f0e370a17207a87d2632616fc8ca27e7ac80cChris Forbes
1018827ed8211a6c2cd0947b7929d0d55d0840618855dChris Forbesstatic void TransitionSubpassLayouts(layer_data *dev_data, GLOBAL_CB_NODE *pCB, const VkRenderPassBeginInfo *pRenderPassBegin,
10189e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                                     const int subpass_index) {
1019016387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes    auto renderPass = getRenderPass(dev_data, pRenderPassBegin->renderPass);
1019116387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes    if (!renderPass)
101925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return;
1019316387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes
10194e3ad4b1284408353cc56a04951c1df1f35a636ceChris Forbes    auto framebuffer = getFramebuffer(dev_data, pRenderPassBegin->framebuffer);
10195e3ad4b1284408353cc56a04951c1df1f35a636ceChris Forbes    if (!framebuffer)
101965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return;
10197e3ad4b1284408353cc56a04951c1df1f35a636ceChris Forbes
10198fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes    auto const &subpass = renderPass->createInfo.pSubpasses[subpass_index];
101995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
10200628f0e370a17207a87d2632616fc8ca27e7ac80cChris Forbes        TransitionAttachmentRefLayout(dev_data, pCB, framebuffer, subpass.pInputAttachments[j]);
102015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
102025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
10203628f0e370a17207a87d2632616fc8ca27e7ac80cChris Forbes        TransitionAttachmentRefLayout(dev_data, pCB, framebuffer, subpass.pColorAttachments[j]);
102045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
10205628f0e370a17207a87d2632616fc8ca27e7ac80cChris Forbes    if (subpass.pDepthStencilAttachment) {
10206628f0e370a17207a87d2632616fc8ca27e7ac80cChris Forbes        TransitionAttachmentRefLayout(dev_data, pCB, framebuffer, *subpass.pDepthStencilAttachment);
102075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
102085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
102095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
102108860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool validatePrimaryCommandBuffer(const layer_data *dev_data, const GLOBAL_CB_NODE *pCB, const std::string &cmd_name) {
10211e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool skip_call = false;
102125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) {
102138860b85a52096f9f9b28616bc37feed505497a54Chris Forbes        skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
102145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                             DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", "Cannot execute command %s on a secondary command buffer.",
102155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                             cmd_name.c_str());
102165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
102175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return skip_call;
102185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
102195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
10220f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbesstatic void TransitionFinalSubpassLayouts(layer_data *dev_data, GLOBAL_CB_NODE *pCB, const VkRenderPassBeginInfo *pRenderPassBegin) {
1022116387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes    auto renderPass = getRenderPass(dev_data, pRenderPassBegin->renderPass);
1022216387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes    if (!renderPass)
102235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return;
1022416387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes
10225fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes    const VkRenderPassCreateInfo *pRenderPassInfo = renderPass->createInfo.ptr();
10226e3ad4b1284408353cc56a04951c1df1f35a636ceChris Forbes    auto framebuffer = getFramebuffer(dev_data, pRenderPassBegin->framebuffer);
10227e3ad4b1284408353cc56a04951c1df1f35a636ceChris Forbes    if (!framebuffer)
102285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return;
10229e3ad4b1284408353cc56a04951c1df1f35a636ceChris Forbes
102305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < pRenderPassInfo->attachmentCount; ++i) {
10231628f0e370a17207a87d2632616fc8ca27e7ac80cChris Forbes        auto image_view = framebuffer->createInfo.pAttachments[i];
102325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        SetLayout(dev_data, pCB, image_view, pRenderPassInfo->pAttachments[i].finalLayout);
102335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
102345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
102355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
102368860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool VerifyRenderAreaBounds(const layer_data *dev_data, const VkRenderPassBeginInfo *pRenderPassBegin) {
10237885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine    bool skip_call = false;
102388860b85a52096f9f9b28616bc37feed505497a54Chris Forbes    const safe_VkFramebufferCreateInfo *pFramebufferInfo = &getFramebuffer(dev_data, pRenderPassBegin->framebuffer)->createInfo;
10239885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine    if (pRenderPassBegin->renderArea.offset.x < 0 ||
10240885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine        (pRenderPassBegin->renderArea.offset.x + pRenderPassBegin->renderArea.extent.width) > pFramebufferInfo->width ||
10241885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine        pRenderPassBegin->renderArea.offset.y < 0 ||
10242885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine        (pRenderPassBegin->renderArea.offset.y + pRenderPassBegin->renderArea.extent.height) > pFramebufferInfo->height) {
10243885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine        skip_call |= static_cast<bool>(log_msg(
102448860b85a52096f9f9b28616bc37feed505497a54Chris Forbes            dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
10245885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine            DRAWSTATE_INVALID_RENDER_AREA, "CORE",
10246885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine            "Cannot execute a render pass with renderArea not within the bound of the "
10247885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine            "framebuffer. RenderArea: x %d, y %d, width %d, height %d. Framebuffer: width %d, "
10248885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine            "height %d.",
10249885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine            pRenderPassBegin->renderArea.offset.x, pRenderPassBegin->renderArea.offset.y, pRenderPassBegin->renderArea.extent.width,
10250885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine            pRenderPassBegin->renderArea.extent.height, pFramebufferInfo->width, pFramebufferInfo->height));
10251885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine    }
10252885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine    return skip_call;
10253885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine}
10254885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine
102551a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski// If this is a stencil format, make sure the stencil[Load|Store]Op flag is checked, while if it is a depth/color attachment the
102561a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski// [load|store]Op flag must be checked
102571a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski// TODO: The memory valid flag in DEVICE_MEM_INFO should probably be split to track the validity of stencil memory separately.
102581a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinskitemplate <typename T> static bool FormatSpecificLoadAndStoreOpSettings(VkFormat format, T color_depth_op, T stencil_op, T op) {
10259a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski    if (color_depth_op != op && stencil_op != op) {
10260a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski        return false;
10261a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski    }
102621a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski    bool check_color_depth_load_op = !vk_format_is_stencil_only(format);
102631a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski    bool check_stencil_load_op = vk_format_is_depth_and_stencil(format) || !check_color_depth_load_op;
10264a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski
10265a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski    return (((check_color_depth_load_op == true) && (color_depth_op == op)) ||
10266a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski            ((check_stencil_load_op == true) && (stencil_op == op)));
102671a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski}
102681a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski
1026989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
1027089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin, VkSubpassContents contents) {
1027183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
102725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
10273b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
10274f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis    GLOBAL_CB_NODE *cb_node = getCBNode(dev_data, commandBuffer);
1027516387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes    auto renderPass = pRenderPassBegin ? getRenderPass(dev_data, pRenderPassBegin->renderPass) : nullptr;
10276f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes    auto framebuffer = pRenderPassBegin ? getFramebuffer(dev_data, pRenderPassBegin->framebuffer) : nullptr;
10277f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis    if (cb_node) {
1027816387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes        if (renderPass) {
102796de3c6ffa0819ee37cd5cecee918b062145e2ff1Tobin Ehlis            uint32_t clear_op_size = 0; // Make sure pClearValues is at least as large as last LOAD_OP_CLEAR
10280f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            cb_node->activeFramebuffer = pRenderPassBegin->framebuffer;
102816e17c244b21ce43ac57404a00a0d844039eed363Mark Lobodzinski            for (uint32_t i = 0; i < renderPass->createInfo.attachmentCount; ++i) {
10282f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes                MT_FB_ATTACHMENT_INFO &fb_info = framebuffer->attachments[i];
10283fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes                auto pAttachment = &renderPass->createInfo.pAttachments[i];
10284db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes                if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->loadOp,
10285db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes                                                         pAttachment->stencilLoadOp,
102861a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski                                                         VK_ATTACHMENT_LOAD_OP_CLEAR)) {
1028792bc0680357019834b7529148ab6d73353ce02c7Mark Lobodzinski                    clear_op_size = static_cast<uint32_t>(i) + 1;
1028816387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                    std::function<bool()> function = [=]() {
10289f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis                        SetImageMemoryValid(dev_data, getImageNode(dev_data, fb_info.image), true);
1029016387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                        return false;
1029116387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                    };
10292f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis                    cb_node->validate_functions.push_back(function);
10293db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes                } else if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->loadOp,
10294db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes                                                                pAttachment->stencilLoadOp,
102951a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski                                                                VK_ATTACHMENT_LOAD_OP_DONT_CARE)) {
1029616387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                    std::function<bool()> function = [=]() {
10297f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis                        SetImageMemoryValid(dev_data, getImageNode(dev_data, fb_info.image), false);
1029816387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                        return false;
1029916387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                    };
10300f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis                    cb_node->validate_functions.push_back(function);
10301db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes                } else if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->loadOp,
10302db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes                                                                pAttachment->stencilLoadOp,
103031a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski                                                                VK_ATTACHMENT_LOAD_OP_LOAD)) {
1030416387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                    std::function<bool()> function = [=]() {
10305f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis                        return ValidateImageMemoryIsValid(dev_data, getImageNode(dev_data, fb_info.image),
10306f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis                                                          "vkCmdBeginRenderPass()");
1030716387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                    };
10308f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis                    cb_node->validate_functions.push_back(function);
1030916387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                }
10310db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes                if (renderPass->attachment_first_read[i]) {
1031116387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                    std::function<bool()> function = [=]() {
10312f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis                        return ValidateImageMemoryIsValid(dev_data, getImageNode(dev_data, fb_info.image),
10313f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis                                                          "vkCmdBeginRenderPass()");
1031416387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                    };
10315f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis                    cb_node->validate_functions.push_back(function);
103165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
103175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
103186de3c6ffa0819ee37cd5cecee918b062145e2ff1Tobin Ehlis            if (clear_op_size > pRenderPassBegin->clearValueCount) {
103196de3c6ffa0819ee37cd5cecee918b062145e2ff1Tobin Ehlis                skip_call |=
103206de3c6ffa0819ee37cd5cecee918b062145e2ff1Tobin Ehlis                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
1032177aa75f997ecb8c39c815d79042d1553c08a9b85Tobin Ehlis                            reinterpret_cast<uint64_t &>(renderPass), __LINE__, VALIDATION_ERROR_00442, "DS",
103226de3c6ffa0819ee37cd5cecee918b062145e2ff1Tobin Ehlis                            "In vkCmdBeginRenderPass() the VkRenderPassBeginInfo struct has a clearValueCount of %u but there must "
103236de3c6ffa0819ee37cd5cecee918b062145e2ff1Tobin Ehlis                            "be at least %u "
103246de3c6ffa0819ee37cd5cecee918b062145e2ff1Tobin Ehlis                            "entries in pClearValues array to account for the highest index attachment in renderPass 0x%" PRIx64
103256de3c6ffa0819ee37cd5cecee918b062145e2ff1Tobin Ehlis                            " that uses VK_ATTACHMENT_LOAD_OP_CLEAR is %u. Note that the pClearValues array "
103266de3c6ffa0819ee37cd5cecee918b062145e2ff1Tobin Ehlis                            "is indexed by attachment number so even if some pClearValues entries between 0 and %u correspond to "
1032777aa75f997ecb8c39c815d79042d1553c08a9b85Tobin Ehlis                            "attachments that aren't cleared they will be ignored. %s",
103286de3c6ffa0819ee37cd5cecee918b062145e2ff1Tobin Ehlis                            pRenderPassBegin->clearValueCount, clear_op_size, reinterpret_cast<uint64_t &>(renderPass),
1032977aa75f997ecb8c39c815d79042d1553c08a9b85Tobin Ehlis                            clear_op_size, clear_op_size - 1, validation_error_map[VALIDATION_ERROR_00442]);
103303d71bca42a843966040d6ada9c029e0ec9f35ca6Tobin Ehlis            }
1033183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= VerifyRenderAreaBounds(dev_data, pRenderPassBegin);
10332f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            skip_call |= VerifyFramebufferAndRenderPassLayouts(dev_data, cb_node, pRenderPassBegin);
10333f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            skip_call |= insideRenderPass(dev_data, cb_node, "vkCmdBeginRenderPass");
1033483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= ValidateDependencies(dev_data, framebuffer, renderPass);
10335f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            skip_call |= validatePrimaryCommandBuffer(dev_data, cb_node, "vkCmdBeginRenderPass");
10336f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            skip_call |= addCmd(dev_data, cb_node, CMD_BEGINRENDERPASS, "vkCmdBeginRenderPass()");
10337f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            cb_node->activeRenderPass = renderPass;
103385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // This is a shallow copy as that is all that is needed for now
10339f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            cb_node->activeRenderPassBeginInfo = *pRenderPassBegin;
10340f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            cb_node->activeSubpass = 0;
10341f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            cb_node->activeSubpassContents = contents;
10342f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            cb_node->framebuffers.insert(pRenderPassBegin->framebuffer);
10343883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis            // Connect this framebuffer and its children to this cmdBuffer
10344883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis            AddFramebufferBinding(dev_data, cb_node, framebuffer);
10345ea0f86230ff5c52f805ac831a1ed5a92bd123368Chris Forbes            // transition attachments to the correct layouts for the first subpass
10346f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            TransitionSubpassLayouts(dev_data, cb_node, &cb_node->activeRenderPassBeginInfo, cb_node->activeSubpass);
103475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
1034883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |=
1034983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
1035083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                        DRAWSTATE_INVALID_RENDERPASS, "DS", "You cannot use a NULL RenderPass object in vkCmdBeginRenderPass()");
103515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
103525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
10353b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
1035483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call) {
103554a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdBeginRenderPass(commandBuffer, pRenderPassBegin, contents);
103565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
103575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
103585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1035989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents) {
1036083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
103615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
10362b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
103635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
103645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
1036583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdNextSubpass");
1036683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, pCB, CMD_NEXTSUBPASS, "vkCmdNextSubpass()");
1036783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= outsideRenderPass(dev_data, pCB, "vkCmdNextSubpass");
1036880281691386b37385846f21b38e8c9d4b12cc74eChris Forbes
10369fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes        auto subpassCount = pCB->activeRenderPass->createInfo.subpassCount;
1037080281691386b37385846f21b38e8c9d4b12cc74eChris Forbes        if (pCB->activeSubpass == subpassCount - 1) {
1037180281691386b37385846f21b38e8c9d4b12cc74eChris Forbes            skip_call |=
1037280281691386b37385846f21b38e8c9d4b12cc74eChris Forbes                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1037380281691386b37385846f21b38e8c9d4b12cc74eChris Forbes                        reinterpret_cast<uint64_t>(commandBuffer), __LINE__, DRAWSTATE_INVALID_SUBPASS_INDEX, "DS",
1037480281691386b37385846f21b38e8c9d4b12cc74eChris Forbes                        "vkCmdNextSubpass(): Attempted to advance beyond final subpass");
1037580281691386b37385846f21b38e8c9d4b12cc74eChris Forbes        }
103765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
10377b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
1037896ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes
1037996ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes    if (skip_call)
1038096ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes        return;
1038196ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes
103824a0754042cf090e131e9e769d8a3633c228625beChris Forbes    dev_data->dispatch_table.CmdNextSubpass(commandBuffer, contents);
1038396ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes
1038496ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes    if (pCB) {
1038596ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes      lock.lock();
1038696ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes      pCB->activeSubpass++;
1038796ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes      pCB->activeSubpassContents = contents;
1038896ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes      TransitionSubpassLayouts(dev_data, pCB, &pCB->activeRenderPassBeginInfo, pCB->activeSubpass);
1038996ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes    }
103905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
103915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1039289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdEndRenderPass(VkCommandBuffer commandBuffer) {
1039383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
103945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
10395b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
1039658c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes    auto pCB = getCBNode(dev_data, commandBuffer);
1039758c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes    if (pCB) {
1039858c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes        RENDER_PASS_NODE* pRPNode = pCB->activeRenderPass;
10399e3ad4b1284408353cc56a04951c1df1f35a636ceChris Forbes        auto framebuffer = getFramebuffer(dev_data, pCB->activeFramebuffer);
10400ee691f5c5fa87aac3750454d2bca2cb582e4e817Chris Forbes        if (pRPNode) {
10401fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes            if (pCB->activeSubpass != pRPNode->createInfo.subpassCount - 1) {
1040202a3382f28fc7c6ec6018165be88aa6fc4f05c9eChris Forbes                skip_call |=
1040302a3382f28fc7c6ec6018165be88aa6fc4f05c9eChris Forbes                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1040402a3382f28fc7c6ec6018165be88aa6fc4f05c9eChris Forbes                            reinterpret_cast<uint64_t>(commandBuffer), __LINE__, DRAWSTATE_INVALID_SUBPASS_INDEX, "DS",
1040502a3382f28fc7c6ec6018165be88aa6fc4f05c9eChris Forbes                            "vkCmdEndRenderPass(): Called before reaching final subpass");
1040602a3382f28fc7c6ec6018165be88aa6fc4f05c9eChris Forbes            }
1040702a3382f28fc7c6ec6018165be88aa6fc4f05c9eChris Forbes
10408fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes            for (size_t i = 0; i < pRPNode->createInfo.attachmentCount; ++i) {
10409e3ad4b1284408353cc56a04951c1df1f35a636ceChris Forbes                MT_FB_ATTACHMENT_INFO &fb_info = framebuffer->attachments[i];
10410fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes                auto pAttachment = &pRPNode->createInfo.pAttachments[i];
10411db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes                if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->storeOp,
10412db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes                                                         pAttachment->stencilStoreOp, VK_ATTACHMENT_STORE_OP_STORE)) {
1041358c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes                    std::function<bool()> function = [=]() {
10414f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis                        SetImageMemoryValid(dev_data, getImageNode(dev_data, fb_info.image), true);
1041558c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes                        return false;
1041658c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes                    };
1041758c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes                    pCB->validate_functions.push_back(function);
10418db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes                } else if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->storeOp,
10419db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes                                                                pAttachment->stencilStoreOp,
104201a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski                                                                VK_ATTACHMENT_STORE_OP_DONT_CARE)) {
1042158c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes                    std::function<bool()> function = [=]() {
10422f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis                        SetImageMemoryValid(dev_data, getImageNode(dev_data, fb_info.image), false);
1042358c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes                        return false;
1042458c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes                    };
1042558c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes                    pCB->validate_functions.push_back(function);
104265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
104275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
104285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
1042983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= outsideRenderPass(dev_data, pCB, "vkCmdEndRenderpass");
1043083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdEndRenderPass");
1043183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, pCB, CMD_ENDRENDERPASS, "vkCmdEndRenderPass()");
104320e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes    }
104330e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes    lock.unlock();
104340e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes
104350e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes    if (skip_call)
104360e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes        return;
104370e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes
104384a0754042cf090e131e9e769d8a3633c228625beChris Forbes    dev_data->dispatch_table.CmdEndRenderPass(commandBuffer);
104390e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes
104400e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes    if (pCB) {
104410e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes        lock.lock();
10442f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes        TransitionFinalSubpassLayouts(dev_data, pCB, &pCB->activeRenderPassBeginInfo);
1044358c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes        pCB->activeRenderPass = nullptr;
1044458c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes        pCB->activeSubpass = 0;
1044558c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes        pCB->activeFramebuffer = VK_NULL_HANDLE;
104465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
104475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
104485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
10449a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool logInvalidAttachmentMessage(layer_data *dev_data, VkCommandBuffer secondaryBuffer, uint32_t primaryAttach,
10450a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                        uint32_t secondaryAttach, const char *msg) {
104515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
104525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                   DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS",
10453a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                   "vkCmdExecuteCommands() called w/ invalid Secondary Cmd Buffer 0x%" PRIx64 " which has a render pass "
10454a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                   "that is not compatible with the Primary Cmd Buffer current render pass. "
10455a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                   "Attachment %u is not compatible with %u: %s",
10456a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                   reinterpret_cast<uint64_t &>(secondaryBuffer), primaryAttach, secondaryAttach, msg);
104575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
104585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
10459a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool validateAttachmentCompatibility(layer_data *dev_data, VkCommandBuffer primaryBuffer,
10460a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                            VkRenderPassCreateInfo const *primaryPassCI, uint32_t primaryAttach,
10461a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                            VkCommandBuffer secondaryBuffer, VkRenderPassCreateInfo const *secondaryPassCI,
10462e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                                            uint32_t secondaryAttach, bool is_multi) {
104635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    bool skip_call = false;
10464a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis    if (primaryPassCI->attachmentCount <= primaryAttach) {
104655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        primaryAttach = VK_ATTACHMENT_UNUSED;
104665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
10467a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis    if (secondaryPassCI->attachmentCount <= secondaryAttach) {
104685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        secondaryAttach = VK_ATTACHMENT_UNUSED;
104695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
104705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (primaryAttach == VK_ATTACHMENT_UNUSED && secondaryAttach == VK_ATTACHMENT_UNUSED) {
104715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return skip_call;
104725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
104735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (primaryAttach == VK_ATTACHMENT_UNUSED) {
10474a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis        skip_call |= logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach,
10475a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                                 "The first is unused while the second is not.");
104765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return skip_call;
104775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
104785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (secondaryAttach == VK_ATTACHMENT_UNUSED) {
10479a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis        skip_call |= logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach,
10480a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                                 "The second is unused while the first is not.");
104815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return skip_call;
104825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
10483a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis    if (primaryPassCI->pAttachments[primaryAttach].format != secondaryPassCI->pAttachments[secondaryAttach].format) {
10484a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis        skip_call |=
10485a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis            logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, "They have different formats.");
104865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
10487a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis    if (primaryPassCI->pAttachments[primaryAttach].samples != secondaryPassCI->pAttachments[secondaryAttach].samples) {
10488a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis        skip_call |=
10489a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis            logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, "They have different samples.");
104905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
10491a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis    if (is_multi && primaryPassCI->pAttachments[primaryAttach].flags != secondaryPassCI->pAttachments[secondaryAttach].flags) {
10492a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis        skip_call |=
10493a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis            logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, "They have different flags.");
104945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
104955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return skip_call;
104965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
104975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
10498a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool validateSubpassCompatibility(layer_data *dev_data, VkCommandBuffer primaryBuffer,
10499a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                         VkRenderPassCreateInfo const *primaryPassCI, VkCommandBuffer secondaryBuffer,
10500a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                         VkRenderPassCreateInfo const *secondaryPassCI, const int subpass, bool is_multi) {
105015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    bool skip_call = false;
10502a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis    const VkSubpassDescription &primary_desc = primaryPassCI->pSubpasses[subpass];
10503a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis    const VkSubpassDescription &secondary_desc = secondaryPassCI->pSubpasses[subpass];
105045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t maxInputAttachmentCount = std::max(primary_desc.inputAttachmentCount, secondary_desc.inputAttachmentCount);
105055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < maxInputAttachmentCount; ++i) {
105065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        uint32_t primary_input_attach = VK_ATTACHMENT_UNUSED, secondary_input_attach = VK_ATTACHMENT_UNUSED;
105075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (i < primary_desc.inputAttachmentCount) {
105085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            primary_input_attach = primary_desc.pInputAttachments[i].attachment;
105095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
105105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (i < secondary_desc.inputAttachmentCount) {
105115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            secondary_input_attach = secondary_desc.pInputAttachments[i].attachment;
105125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
10513a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis        skip_call |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_input_attach, secondaryBuffer,
10514a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                                     secondaryPassCI, secondary_input_attach, is_multi);
105155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
105165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t maxColorAttachmentCount = std::max(primary_desc.colorAttachmentCount, secondary_desc.colorAttachmentCount);
105175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < maxColorAttachmentCount; ++i) {
105185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        uint32_t primary_color_attach = VK_ATTACHMENT_UNUSED, secondary_color_attach = VK_ATTACHMENT_UNUSED;
105195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (i < primary_desc.colorAttachmentCount) {
105205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            primary_color_attach = primary_desc.pColorAttachments[i].attachment;
105215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
105225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (i < secondary_desc.colorAttachmentCount) {
105235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            secondary_color_attach = secondary_desc.pColorAttachments[i].attachment;
105245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
10525a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis        skip_call |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_color_attach, secondaryBuffer,
10526a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                                     secondaryPassCI, secondary_color_attach, is_multi);
105275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        uint32_t primary_resolve_attach = VK_ATTACHMENT_UNUSED, secondary_resolve_attach = VK_ATTACHMENT_UNUSED;
105285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (i < primary_desc.colorAttachmentCount && primary_desc.pResolveAttachments) {
105295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            primary_resolve_attach = primary_desc.pResolveAttachments[i].attachment;
105305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
105315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (i < secondary_desc.colorAttachmentCount && secondary_desc.pResolveAttachments) {
105325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            secondary_resolve_attach = secondary_desc.pResolveAttachments[i].attachment;
105335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
10534a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis        skip_call |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_resolve_attach,
10535a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                                     secondaryBuffer, secondaryPassCI, secondary_resolve_attach, is_multi);
105365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
105375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t primary_depthstencil_attach = VK_ATTACHMENT_UNUSED, secondary_depthstencil_attach = VK_ATTACHMENT_UNUSED;
105385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (primary_desc.pDepthStencilAttachment) {
105395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        primary_depthstencil_attach = primary_desc.pDepthStencilAttachment[0].attachment;
105405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
105415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (secondary_desc.pDepthStencilAttachment) {
105425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        secondary_depthstencil_attach = secondary_desc.pDepthStencilAttachment[0].attachment;
105435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
10544a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis    skip_call |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_depthstencil_attach,
10545a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                                 secondaryBuffer, secondaryPassCI, secondary_depthstencil_attach, is_multi);
105465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return skip_call;
105475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
105485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
10549a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis// Verify that given renderPass CreateInfo for primary and secondary command buffers are compatible.
10550a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis//  This function deals directly with the CreateInfo, there are overloaded versions below that can take the renderPass handle and
10551a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis//  will then feed into this function
10552a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool validateRenderPassCompatibility(layer_data *dev_data, VkCommandBuffer primaryBuffer,
10553a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                            VkRenderPassCreateInfo const *primaryPassCI, VkCommandBuffer secondaryBuffer,
10554a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                            VkRenderPassCreateInfo const *secondaryPassCI) {
105555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    bool skip_call = false;
10556a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis
10557a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis    if (primaryPassCI->subpassCount != secondaryPassCI->subpassCount) {
105585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
105595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                             DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS",
10560a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                             "vkCmdExecuteCommands() called w/ invalid secondary Cmd Buffer 0x%" PRIx64
10561a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                             " that has a subpassCount of %u that is incompatible with the primary Cmd Buffer 0x%" PRIx64
10562a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                             " that has a subpassCount of %u.",
10563a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                             reinterpret_cast<uint64_t &>(secondaryBuffer), secondaryPassCI->subpassCount,
10564a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                             reinterpret_cast<uint64_t &>(primaryBuffer), primaryPassCI->subpassCount);
10565a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis    } else {
10566a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis        for (uint32_t i = 0; i < primaryPassCI->subpassCount; ++i) {
10567a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis            skip_call |= validateSubpassCompatibility(dev_data, primaryBuffer, primaryPassCI, secondaryBuffer, secondaryPassCI, i,
10568a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                                      primaryPassCI->subpassCount > 1);
10569a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis        }
105705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
105715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return skip_call;
105725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
105735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
10574e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool validateFramebuffer(layer_data *dev_data, VkCommandBuffer primaryBuffer, const GLOBAL_CB_NODE *pCB,
10575e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                                VkCommandBuffer secondaryBuffer, const GLOBAL_CB_NODE *pSubCB) {
105765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    bool skip_call = false;
105775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (!pSubCB->beginInfo.pInheritanceInfo) {
105785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return skip_call;
105795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
10580c5b97dda856ff837638b3ebb7e231d5507c495a3Chris Forbes    VkFramebuffer primary_fb = pCB->activeFramebuffer;
105815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkFramebuffer secondary_fb = pSubCB->beginInfo.pInheritanceInfo->framebuffer;
105825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (secondary_fb != VK_NULL_HANDLE) {
105835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (primary_fb != secondary_fb) {
105845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
105851af6125615cd6dd9735d32e2ee8684abeff28d41Tobin Ehlis                                 DRAWSTATE_FRAMEBUFFER_INCOMPATIBLE, "DS",
105861af6125615cd6dd9735d32e2ee8684abeff28d41Tobin Ehlis                                 "vkCmdExecuteCommands() called w/ invalid secondary Cmd Buffer 0x%" PRIx64
105871af6125615cd6dd9735d32e2ee8684abeff28d41Tobin Ehlis                                 " which has a framebuffer 0x%" PRIx64
105881af6125615cd6dd9735d32e2ee8684abeff28d41Tobin Ehlis                                 " that is not the same as the primaryCB's current active framebuffer 0x%" PRIx64 ".",
105891af6125615cd6dd9735d32e2ee8684abeff28d41Tobin Ehlis                                 reinterpret_cast<uint64_t &>(secondaryBuffer), reinterpret_cast<uint64_t &>(secondary_fb),
105901af6125615cd6dd9735d32e2ee8684abeff28d41Tobin Ehlis                                 reinterpret_cast<uint64_t &>(primary_fb));
105915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
10592e3ad4b1284408353cc56a04951c1df1f35a636ceChris Forbes        auto fb = getFramebuffer(dev_data, secondary_fb);
10593e3ad4b1284408353cc56a04951c1df1f35a636ceChris Forbes        if (!fb) {
105945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            skip_call |=
105955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
10596414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p "
10597414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                                                          "which has invalid framebuffer 0x%" PRIx64 ".",
105985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        (void *)secondaryBuffer, (uint64_t)(secondary_fb));
105995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            return skip_call;
106005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
10601a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis        auto cb_renderpass = getRenderPass(dev_data, pSubCB->beginInfo.pInheritanceInfo->renderPass);
10602a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis        if (cb_renderpass->renderPass != fb->createInfo.renderPass) {
10603a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis            skip_call |= validateRenderPassCompatibility(dev_data, secondaryBuffer, fb->renderPassCreateInfo.ptr(), secondaryBuffer,
10604fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes                                                         cb_renderpass->createInfo.ptr());
10605a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis        }
106065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
106075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return skip_call;
106085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
106095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
10610e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool validateSecondaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *pCB, GLOBAL_CB_NODE *pSubCB) {
1061183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
106125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_set<int> activeTypes;
106135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (auto queryObject : pCB->activeQueries) {
106145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto queryPoolData = dev_data->queryPoolMap.find(queryObject.pool);
106155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (queryPoolData != dev_data->queryPoolMap.end()) {
106165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (queryPoolData->second.createInfo.queryType == VK_QUERY_TYPE_PIPELINE_STATISTICS &&
106175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                pSubCB->beginInfo.pInheritanceInfo) {
106185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                VkQueryPipelineStatisticFlags cmdBufStatistics = pSubCB->beginInfo.pInheritanceInfo->pipelineStatistics;
106195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if ((cmdBufStatistics & queryPoolData->second.createInfo.pipelineStatistics) != cmdBufStatistics) {
1062083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                    skip_call |= log_msg(
106215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
106225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS",
10623414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p "
10624414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        "which has invalid active query pool 0x%" PRIx64 ". Pipeline statistics is being queried so the command "
106255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        "buffer must have all bits set on the queryPool.",
106265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        reinterpret_cast<void *>(pCB->commandBuffer), reinterpret_cast<const uint64_t &>(queryPoolData->first));
106275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
106285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
106295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            activeTypes.insert(queryPoolData->second.createInfo.queryType);
106305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
106315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
106325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (auto queryObject : pSubCB->startedQueries) {
106335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto queryPoolData = dev_data->queryPoolMap.find(queryObject.pool);
106345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (queryPoolData != dev_data->queryPoolMap.end() && activeTypes.count(queryPoolData->second.createInfo.queryType)) {
1063583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |=
106365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
106375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS",
10638414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p "
10639414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        "which has invalid active query pool 0x%" PRIx64 "of type %d but a query of that type has been started on "
10640414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        "secondary Cmd Buffer 0x%p.",
106415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        reinterpret_cast<void *>(pCB->commandBuffer), reinterpret_cast<const uint64_t &>(queryPoolData->first),
106425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        queryPoolData->second.createInfo.queryType, reinterpret_cast<void *>(pSubCB->commandBuffer));
106435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
106445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
106457bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski
106467bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski    auto primary_pool = getCommandPoolNode(dev_data, pCB->createInfo.commandPool);
106477bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski    auto secondary_pool = getCommandPoolNode(dev_data, pSubCB->createInfo.commandPool);
106487bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski    if (primary_pool && secondary_pool && (primary_pool->queueFamilyIndex != secondary_pool->queueFamilyIndex)) {
106497bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski        skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
106507bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski                             reinterpret_cast<uint64_t>(pSubCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_QUEUE_FAMILY, "DS",
106517bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski                             "vkCmdExecuteCommands(): Primary command buffer 0x%" PRIxLEAST64
106527bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski                             " created in queue family %d has secondary command buffer 0x%" PRIxLEAST64 " created in queue family %d.",
106537bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski                             reinterpret_cast<uint64_t>(pCB->commandBuffer), primary_pool->queueFamilyIndex,
106547bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski                             reinterpret_cast<uint64_t>(pSubCB->commandBuffer), secondary_pool->queueFamilyIndex);
106557bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski    }
106567bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski
1065783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    return skip_call;
106585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
106595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1066089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
1066189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBuffersCount, const VkCommandBuffer *pCommandBuffers) {
1066283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
106635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
10664b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
106655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
106665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
106675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        GLOBAL_CB_NODE *pSubCB = NULL;
106685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t i = 0; i < commandBuffersCount; i++) {
106695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            pSubCB = getCBNode(dev_data, pCommandBuffers[i]);
106705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (!pSubCB) {
1067183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                skip_call |=
106725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
106735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS",
10674414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                            "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p in element %u of pCommandBuffers array.",
106755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            (void *)pCommandBuffers[i], i);
106765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            } else if (VK_COMMAND_BUFFER_LEVEL_PRIMARY == pSubCB->createInfo.level) {
1067783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
1067883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                     __LINE__, DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS",
1067983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                     "vkCmdExecuteCommands() called w/ Primary Cmd Buffer 0x%p in element %u of pCommandBuffers "
1068083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                     "array. All cmd buffers in pCommandBuffers array must be secondary.",
1068183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                                     (void *)pCommandBuffers[i], i);
106825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            } else if (pCB->activeRenderPass) { // Secondary CB w/i RenderPass must have *CONTINUE_BIT set
10683a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                auto secondary_rp_node = getRenderPass(dev_data, pSubCB->beginInfo.pInheritanceInfo->renderPass);
106845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if (!(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) {
1068583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                    skip_call |= log_msg(
106865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
106875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        (uint64_t)pCommandBuffers[i], __LINE__, DRAWSTATE_BEGIN_CB_INVALID_STATE, "DS",
10688414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        "vkCmdExecuteCommands(): Secondary Command Buffer (0x%p) executed within render pass (0x%" PRIxLEAST64
106895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        ") must have had vkBeginCommandBuffer() called w/ VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT set.",
10690ee691f5c5fa87aac3750454d2bca2cb582e4e817Chris Forbes                        (void *)pCommandBuffers[i], (uint64_t)pCB->activeRenderPass->renderPass);
106915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                } else {
106925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    // Make sure render pass is compatible with parent command buffer pass if has continue
10693a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                    if (pCB->activeRenderPass->renderPass != secondary_rp_node->renderPass) {
10694fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes                        skip_call |=
10695fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes                            validateRenderPassCompatibility(dev_data, commandBuffer, pCB->activeRenderPass->createInfo.ptr(),
10696fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes                                                            pCommandBuffers[i], secondary_rp_node->createInfo.ptr());
10697a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                    }
106981af6125615cd6dd9735d32e2ee8684abeff28d41Tobin Ehlis                    //  If framebuffer for secondary CB is not NULL, then it must match active FB from primaryCB
1069983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                    skip_call |= validateFramebuffer(dev_data, commandBuffer, pCB, pCommandBuffers[i], pSubCB);
107005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
107015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                string errorString = "";
107021af6125615cd6dd9735d32e2ee8684abeff28d41Tobin Ehlis                // secondaryCB must have been created w/ RP compatible w/ primaryCB active renderpass
10703a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                if ((pCB->activeRenderPass->renderPass != secondary_rp_node->renderPass) &&
10704fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes                    !verify_renderpass_compatibility(dev_data, pCB->activeRenderPass->createInfo.ptr(),
10705fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes                                                     secondary_rp_node->createInfo.ptr(), errorString)) {
1070683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                    skip_call |= log_msg(
107075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
107085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        (uint64_t)pCommandBuffers[i], __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS",
10709414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        "vkCmdExecuteCommands(): Secondary Command Buffer (0x%p) w/ render pass (0x%" PRIxLEAST64
10710414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        ") is incompatible w/ primary command buffer (0x%p) w/ render pass (0x%" PRIxLEAST64 ") due to: %s",
107115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        (void *)pCommandBuffers[i], (uint64_t)pSubCB->beginInfo.pInheritanceInfo->renderPass, (void *)commandBuffer,
10712ee691f5c5fa87aac3750454d2bca2cb582e4e817Chris Forbes                        (uint64_t)pCB->activeRenderPass->renderPass, errorString.c_str());
107135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
107145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
107155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // TODO(mlentine): Move more logic into this method
1071683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= validateSecondaryCommandBufferState(dev_data, pCB, pSubCB);
1071775b0d6603382dcb3e3de24c11ea6e4aa2ef8b4d2Tobin Ehlis            skip_call |= validateCommandBufferState(dev_data, pSubCB, "vkCmdExecuteCommands()");
107185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // Secondary cmdBuffers are considered pending execution starting w/
107195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // being recorded
107205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (!(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) {
107215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if (dev_data->globalInFlightCmdBuffers.find(pSubCB->commandBuffer) != dev_data->globalInFlightCmdBuffers.end()) {
1072283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                    skip_call |= log_msg(
107235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
107245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        (uint64_t)(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_CB_SIMULTANEOUS_USE, "DS",
10725414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        "Attempt to simultaneously execute CB 0x%" PRIxLEAST64 " w/o VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT "
107265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        "set!",
107275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        (uint64_t)(pCB->commandBuffer));
107285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
107295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if (pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT) {
107305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    // Warn that non-simultaneous secondary cmd buffer renders primary non-simultaneous
1073183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                    skip_call |= log_msg(
107325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
107335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        (uint64_t)(pCommandBuffers[i]), __LINE__, DRAWSTATE_INVALID_CB_SIMULTANEOUS_USE, "DS",
10734414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        "vkCmdExecuteCommands(): Secondary Command Buffer (0x%" PRIxLEAST64
107355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        ") does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set and will cause primary command buffer "
10736414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        "(0x%" PRIxLEAST64 ") to be treated as if it does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT "
1073783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                        "set, even though it does.",
107385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        (uint64_t)(pCommandBuffers[i]), (uint64_t)(pCB->commandBuffer));
107395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    pCB->beginInfo.flags &= ~VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
107405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
107415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
10742f71dd305f197826a61f398bff725267a20ea1d90Chris Forbes            if (!pCB->activeQueries.empty() && !dev_data->enabled_features.inheritedQueries) {
1074383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                skip_call |=
107445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
107455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            reinterpret_cast<uint64_t>(pCommandBuffers[i]), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
107465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            "vkCmdExecuteCommands(): Secondary Command Buffer "
10747414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                            "(0x%" PRIxLEAST64 ") cannot be submitted with a query in "
107485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            "flight and inherited queries not "
107495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            "supported on this device.",
107505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            reinterpret_cast<uint64_t>(pCommandBuffers[i]));
107515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
107525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            pSubCB->primaryCommandBuffer = pCB->commandBuffer;
107535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            pCB->secondaryCommandBuffers.insert(pSubCB->commandBuffer);
107545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            dev_data->globalInFlightCmdBuffers.insert(pSubCB->commandBuffer);
10755d4ee9fdb2def1e9dc70c5627c9103e264471b8ebMichael Lentine            for (auto &function : pSubCB->queryUpdates) {
10756d4ee9fdb2def1e9dc70c5627c9103e264471b8ebMichael Lentine                pCB->queryUpdates.push_back(function);
10757d4ee9fdb2def1e9dc70c5627c9103e264471b8ebMichael Lentine            }
107585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
1075983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdExecuteComands");
1076083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= addCmd(dev_data, pCB, CMD_EXECUTECOMMANDS, "vkCmdExecuteComands()");
107615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
10762b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
1076383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
107644a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdExecuteCommands(commandBuffer, commandBuffersCount, pCommandBuffers);
107655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
107665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
10767b05be7c81dfbaef10cf00e2cc1c3832026fde765Tobin Ehlis// For any image objects that overlap mapped memory, verify that their layouts are PREINIT or GENERAL
10768cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlisstatic bool ValidateMapImageLayouts(VkDevice device, DEVICE_MEM_INFO const *mem_info, VkDeviceSize offset,
10769623548a271287ae55415e45e3c654ee66d4e79ffTobin Ehlis                                    VkDeviceSize end_offset) {
10770e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool skip_call = false;
107715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
10772cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    // Iterate over all bound image ranges and verify that for any that overlap the
10773cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    //  map ranges, the layouts are VK_IMAGE_LAYOUT_PREINITIALIZED or VK_IMAGE_LAYOUT_GENERAL
10774cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    // TODO : This can be optimized if we store ranges based on starting address and early exit when we pass our range
10775cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    for (auto image_handle : mem_info->bound_images) {
10776cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis        auto img_it = mem_info->bound_ranges.find(image_handle);
10777cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis        if (img_it != mem_info->bound_ranges.end()) {
10778623548a271287ae55415e45e3c654ee66d4e79ffTobin Ehlis            if (rangesIntersect(dev_data, &img_it->second, offset, end_offset)) {
10779b05be7c81dfbaef10cf00e2cc1c3832026fde765Tobin Ehlis                std::vector<VkImageLayout> layouts;
10780825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis                if (FindLayouts(dev_data, VkImage(image_handle), layouts)) {
10781b05be7c81dfbaef10cf00e2cc1c3832026fde765Tobin Ehlis                    for (auto layout : layouts) {
10782b05be7c81dfbaef10cf00e2cc1c3832026fde765Tobin Ehlis                        if (layout != VK_IMAGE_LAYOUT_PREINITIALIZED && layout != VK_IMAGE_LAYOUT_GENERAL) {
10783b05be7c81dfbaef10cf00e2cc1c3832026fde765Tobin Ehlis                            skip_call |=
10784b05be7c81dfbaef10cf00e2cc1c3832026fde765Tobin Ehlis                                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
10785b05be7c81dfbaef10cf00e2cc1c3832026fde765Tobin Ehlis                                        __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", "Cannot map an image with layout %s. Only "
10786b05be7c81dfbaef10cf00e2cc1c3832026fde765Tobin Ehlis                                                                                        "GENERAL or PREINITIALIZED are supported.",
10787b05be7c81dfbaef10cf00e2cc1c3832026fde765Tobin Ehlis                                        string_VkImageLayout(layout));
10788b05be7c81dfbaef10cf00e2cc1c3832026fde765Tobin Ehlis                        }
10789b05be7c81dfbaef10cf00e2cc1c3832026fde765Tobin Ehlis                    }
10790b05be7c81dfbaef10cf00e2cc1c3832026fde765Tobin Ehlis                }
10791b05be7c81dfbaef10cf00e2cc1c3832026fde765Tobin Ehlis            }
10792b05be7c81dfbaef10cf00e2cc1c3832026fde765Tobin Ehlis        }
107935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
107945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return skip_call;
107955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
107965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1079789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL
1079889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuMapMemory(VkDevice device, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, VkFlags flags, void **ppData) {
107995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
108005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
10801e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool skip_call = false;
108025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
10803b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
10804cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    DEVICE_MEM_INFO *mem_info = getMemObjInfo(dev_data, mem);
10805cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    if (mem_info) {
10806f541bf53dee6daf82a4c8304354eac599a884d29Tobin Ehlis        // TODO : This could me more fine-grained to track just region that is valid
10807f541bf53dee6daf82a4c8304354eac599a884d29Tobin Ehlis        mem_info->global_valid = true;
10808623548a271287ae55415e45e3c654ee66d4e79ffTobin Ehlis        auto end_offset = (VK_WHOLE_SIZE == size) ? mem_info->alloc_info.allocationSize - 1 : offset + size - 1;
10809623548a271287ae55415e45e3c654ee66d4e79ffTobin Ehlis        skip_call |= ValidateMapImageLayouts(device, mem_info, offset, end_offset);
10810cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis        // TODO : Do we need to create new "bound_range" for the mapped range?
10811623548a271287ae55415e45e3c654ee66d4e79ffTobin Ehlis        SetMemRangesValid(dev_data, mem_info, offset, end_offset);
10812cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis        if ((dev_data->phys_dev_mem_props.memoryTypes[mem_info->alloc_info.memoryTypeIndex].propertyFlags &
10813b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis             VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) {
108145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            skip_call =
108155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
108165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        (uint64_t)mem, __LINE__, MEMTRACK_INVALID_STATE, "MEM",
10817414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        "Mapping Memory without VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT set: mem obj 0x%" PRIxLEAST64, (uint64_t)mem);
108185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
108195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
10820f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis    skip_call |= ValidateMapMemRange(dev_data, mem, offset, size);
10821b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
108225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
10823e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    if (!skip_call) {
108244a0754042cf090e131e9e769d8a3633c228625beChris Forbes        result = dev_data->dispatch_table.MapMemory(device, mem, offset, size, flags, ppData);
108257c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis        if (VK_SUCCESS == result) {
108267c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis            lock.lock();
10827cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis            // TODO : What's the point of this range? See comment on creating new "bound_range" above, which may replace this
108287c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis            storeMemRanges(dev_data, mem, offset, size);
108295f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            initializeAndTrackMemory(dev_data, mem, offset, size, ppData);
108307c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis            lock.unlock();
108317c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis        }
108325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
108335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
108345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
108355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1083689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL UnmapMemory(VkDevice device, VkDeviceMemory mem) {
108378860b85a52096f9f9b28616bc37feed505497a54Chris Forbes    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1083883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
108395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
10840b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
108418860b85a52096f9f9b28616bc37feed505497a54Chris Forbes    skip_call |= deleteMemRanges(dev_data, mem);
10842b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
1084383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call) {
108444a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.UnmapMemory(device, mem);
108455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
108465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
108475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
108488860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool validateMemoryIsMapped(layer_data *dev_data, const char *funcName, uint32_t memRangeCount,
10849e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                                   const VkMappedMemoryRange *pMemRanges) {
1085083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
108515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < memRangeCount; ++i) {
108528860b85a52096f9f9b28616bc37feed505497a54Chris Forbes        auto mem_info = getMemObjInfo(dev_data, pMemRanges[i].memory);
1085357fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis        if (mem_info) {
10854de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis            if (mem_info->mem_range.offset > pMemRanges[i].offset) {
1085583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                skip_call |=
108568860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
1085757fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis                            (uint64_t)pMemRanges[i].memory, __LINE__, MEMTRACK_INVALID_MAP, "MEM",
1085857fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis                            "%s: Flush/Invalidate offset (" PRINTF_SIZE_T_SPECIFIER ") is less than Memory Object's offset "
1085957fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis                            "(" PRINTF_SIZE_T_SPECIFIER ").",
10860de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis                            funcName, static_cast<size_t>(pMemRanges[i].offset), static_cast<size_t>(mem_info->mem_range.offset));
108615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
108624b70ef75f98d2a6196132d8c48d43d1d5e04992eMark Mueller
108638860b85a52096f9f9b28616bc37feed505497a54Chris Forbes            const uint64_t dev_dataTerminus = (mem_info->mem_range.size == VK_WHOLE_SIZE)
108648860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                                                  ? mem_info->alloc_info.allocationSize
108658860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                                                  : (mem_info->mem_range.offset + mem_info->mem_range.size);
108668860b85a52096f9f9b28616bc37feed505497a54Chris Forbes            if (pMemRanges[i].size != VK_WHOLE_SIZE && (dev_dataTerminus < (pMemRanges[i].offset + pMemRanges[i].size))) {
108678860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
108688860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                                     VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)pMemRanges[i].memory, __LINE__,
108698860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                                     MEMTRACK_INVALID_MAP, "MEM", "%s: Flush/Invalidate upper-bound (" PRINTF_SIZE_T_SPECIFIER
108708860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                                                                  ") exceeds the Memory Object's upper-bound "
108718860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                                                                  "(" PRINTF_SIZE_T_SPECIFIER ").",
108728860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                                     funcName, static_cast<size_t>(pMemRanges[i].offset + pMemRanges[i].size),
108738860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                                     static_cast<size_t>(dev_dataTerminus));
108745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
108755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
108765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
1087783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    return skip_call;
108785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
108795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
108808860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool ValidateAndCopyNoncoherentMemoryToDriver(layer_data *dev_data, uint32_t memRangeCount,
10881e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                                                     const VkMappedMemoryRange *pMemRanges) {
1088283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
108835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < memRangeCount; ++i) {
108848860b85a52096f9f9b28616bc37feed505497a54Chris Forbes        auto mem_info = getMemObjInfo(dev_data, pMemRanges[i].memory);
1088557fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis        if (mem_info) {
108865f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            if (mem_info->shadow_copy) {
108875f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                VkDeviceSize size = (mem_info->mem_range.size != VK_WHOLE_SIZE)
108885f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                                        ? mem_info->mem_range.size
10889d8a53ade6b5501256798a8b4ec0bc14f72adc1faTobin Ehlis                                        : (mem_info->alloc_info.allocationSize - mem_info->mem_range.offset);
108905f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                char *data = static_cast<char *>(mem_info->shadow_copy);
108915f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                for (uint64_t j = 0; j < mem_info->shadow_pad_size; ++j) {
108925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    if (data[j] != NoncoherentMemoryFillValue) {
1089383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                        skip_call |= log_msg(
108948860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                            dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
1089583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            (uint64_t)pMemRanges[i].memory, __LINE__, MEMTRACK_INVALID_MAP, "MEM",
108965f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                            "Memory underflow was detected on mem obj 0x%" PRIxLEAST64, (uint64_t)pMemRanges[i].memory);
108975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
108985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
108995f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                for (uint64_t j = (size + mem_info->shadow_pad_size); j < (2 * mem_info->shadow_pad_size + size); ++j) {
109005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    if (data[j] != NoncoherentMemoryFillValue) {
1090183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                        skip_call |= log_msg(
109028860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                            dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
1090383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            (uint64_t)pMemRanges[i].memory, __LINE__, MEMTRACK_INVALID_MAP, "MEM",
1090483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                            "Memory overflow was detected on mem obj 0x%" PRIxLEAST64, (uint64_t)pMemRanges[i].memory);
109055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
109065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
109075f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                memcpy(mem_info->p_driver_data, static_cast<void *>(data + mem_info->shadow_pad_size), (size_t)(size));
109085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
109095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
109105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
1091183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    return skip_call;
109125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
109135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
109148860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic void CopyNoncoherentMemoryFromDriver(layer_data *dev_data, uint32_t memory_range_count,
109155f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                                            const VkMappedMemoryRange *mem_ranges) {
109169e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski    for (uint32_t i = 0; i < memory_range_count; ++i) {
109178860b85a52096f9f9b28616bc37feed505497a54Chris Forbes        auto mem_info = getMemObjInfo(dev_data, mem_ranges[i].memory);
109185f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski        if (mem_info && mem_info->shadow_copy) {
109195f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            VkDeviceSize size = (mem_info->mem_range.size != VK_WHOLE_SIZE)
109205f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                                    ? mem_info->mem_range.size
109215f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                                    : (mem_info->alloc_info.allocationSize - mem_ranges[i].offset);
109225f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            char *data = static_cast<char *>(mem_info->shadow_copy);
109235f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            memcpy(data + mem_info->shadow_pad_size, mem_info->p_driver_data, (size_t)(size));
109249e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski        }
109259e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski    }
109269e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski}
109279e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski
1092889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVkResult VKAPI_CALL
1092989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuFlushMappedMemoryRanges(VkDevice device, uint32_t memRangeCount, const VkMappedMemoryRange *pMemRanges) {
109305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
1093183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
109328860b85a52096f9f9b28616bc37feed505497a54Chris Forbes    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
109335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
10934b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
109358860b85a52096f9f9b28616bc37feed505497a54Chris Forbes    skip_call |= ValidateAndCopyNoncoherentMemoryToDriver(dev_data, memRangeCount, pMemRanges);
109368860b85a52096f9f9b28616bc37feed505497a54Chris Forbes    skip_call |= validateMemoryIsMapped(dev_data, "vkFlushMappedMemoryRanges", memRangeCount, pMemRanges);
10937b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
1093883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call) {
109394a0754042cf090e131e9e769d8a3633c228625beChris Forbes        result = dev_data->dispatch_table.FlushMappedMemoryRanges(device, memRangeCount, pMemRanges);
109405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
109415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
109425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
109435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1094489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVkResult VKAPI_CALL
1094589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuInvalidateMappedMemoryRanges(VkDevice device, uint32_t memRangeCount, const VkMappedMemoryRange *pMemRanges) {
109465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
1094783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
109488860b85a52096f9f9b28616bc37feed505497a54Chris Forbes    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
109495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
10950b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
109518860b85a52096f9f9b28616bc37feed505497a54Chris Forbes    skip_call |= validateMemoryIsMapped(dev_data, "vkInvalidateMappedMemoryRanges", memRangeCount, pMemRanges);
10952b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
1095383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call) {
109544a0754042cf090e131e9e769d8a3633c228625beChris Forbes        result = dev_data->dispatch_table.InvalidateMappedMemoryRanges(device, memRangeCount, pMemRanges);
109559e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski        // Update our shadow copy with modified driver data
109568860b85a52096f9f9b28616bc37feed505497a54Chris Forbes        CopyNoncoherentMemoryFromDriver(dev_data, memRangeCount, pMemRanges);
109575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
109585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
109595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
109605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1096189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL BindImageMemory(VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memoryOffset) {
109625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
109635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
1096483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
10965b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
109666d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis    auto image_node = getImageNode(dev_data, image);
109676d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis    if (image_node) {
1096894c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis        // Track objects tied to memory
1096947aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski        uint64_t image_handle = reinterpret_cast<uint64_t &>(image);
10970888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis        skip_call = SetMemBinding(dev_data, mem, image_handle, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, "vkBindImageMemory");
109715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        VkMemoryRequirements memRequirements;
10972b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
109734a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.GetImageMemoryRequirements(device, image, &memRequirements);
10974b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.lock();
1097547aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski
1097647aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski        // Track and validate bound memory range information
1097757fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis        auto mem_info = getMemObjInfo(dev_data, mem);
1097857fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis        if (mem_info) {
109799f12a235bb9c014878a98ce385b68587add2538aTobin Ehlis            skip_call |= InsertImageMemoryRange(dev_data, image, mem_info, memoryOffset, memRequirements,
10980825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis                                                image_node->createInfo.tiling == VK_IMAGE_TILING_LINEAR);
1098183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis            skip_call |= ValidateMemoryTypes(dev_data, mem_info, memRequirements.memoryTypeBits, "vkBindImageMemory");
1098247aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski        }
1098347aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski
109840a1ce3dfd81c9f4efbe46f5ba5ddaea70bc4aa61Chris Forbes        print_mem_list(dev_data);
10985b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
1098683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        if (!skip_call) {
109874a0754042cf090e131e9e769d8a3633c228625beChris Forbes            result = dev_data->dispatch_table.BindImageMemory(device, image, mem, memoryOffset);
10988b9e992386a44404152747d66817a733aa127e281Jeremy Hayes            lock.lock();
109896d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            image_node->mem = mem;
109906d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            image_node->memOffset = memoryOffset;
109916d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            image_node->memSize = memRequirements.size;
10992b9e992386a44404152747d66817a733aa127e281Jeremy Hayes            lock.unlock();
1099394c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis        }
1099494c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis    } else {
1099594c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis        log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
1099694c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis                reinterpret_cast<const uint64_t &>(image), __LINE__, MEMTRACK_INVALID_OBJECT, "MT",
10997414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                "vkBindImageMemory: Cannot find invalid image 0x%" PRIx64 ", has it already been deleted?",
1099894c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis                reinterpret_cast<const uint64_t &>(image));
109995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
110005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
110015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
110025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1100389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL SetEvent(VkDevice device, VkEvent event) {
110043ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis    bool skip_call = false;
110053ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
110065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
11007b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
110089556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis    auto event_node = getEventNode(dev_data, event);
110099556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis    if (event_node) {
110109556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis        event_node->needsSignaled = false;
110119556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis        event_node->stageMask = VK_PIPELINE_STAGE_HOST_BIT;
110129556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis        if (event_node->write_in_use) {
110133ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT,
110143ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis                                 reinterpret_cast<const uint64_t &>(event), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS",
11015414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                 "Cannot call vkSetEvent() on event 0x%" PRIxLEAST64 " that is already in use by a command buffer.",
110163ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis                                 reinterpret_cast<const uint64_t &>(event));
110173ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis        }
110183ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis    }
11019b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
110206fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis    // Host setting event is visible to all queues immediately so update stageMask for any queue that's seen this event
110216fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis    // TODO : For correctness this needs separate fix to verify that app doesn't make incorrect assumptions about the
110226fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis    // ordering of this command in relation to vkCmd[Set|Reset]Events (see GH297)
110236fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis    for (auto queue_data : dev_data->queueMap) {
110246fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis        auto event_entry = queue_data.second.eventToStageMap.find(event);
110256fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis        if (event_entry != queue_data.second.eventToStageMap.end()) {
110266fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis            event_entry->second |= VK_PIPELINE_STAGE_HOST_BIT;
110276fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis        }
110286fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis    }
110293ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis    if (!skip_call)
110304a0754042cf090e131e9e769d8a3633c228625beChris Forbes        result = dev_data->dispatch_table.SetEvent(device, event);
110315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
110325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
110335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
110345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin EhlisVKAPI_ATTR VkResult VKAPI_CALL
1103589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuQueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo *pBindInfo, VkFence fence) {
110365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
110375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
11038e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool skip_call = false;
11039b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
11040651d92815dfff917308137bb67aacccc4f60df86Chris Forbes    auto pFence = getFenceNode(dev_data, fence);
11041651d92815dfff917308137bb67aacccc4f60df86Chris Forbes    auto pQueue = getQueueNode(dev_data, queue);
11042651d92815dfff917308137bb67aacccc4f60df86Chris Forbes
110434b38d3aa8b6be6a7f5bebb472ab439da0562824fTobin Ehlis    // First verify that fence is not in use
11044651d92815dfff917308137bb67aacccc4f60df86Chris Forbes    skip_call |= ValidateFenceForSubmit(dev_data, pFence);
11045651d92815dfff917308137bb67aacccc4f60df86Chris Forbes
110469867daedbf52debc77d6568162ee21e071699b80Chris Forbes    if (pFence) {
110479867daedbf52debc77d6568162ee21e071699b80Chris Forbes        SubmitFence(pQueue, pFence, bindInfoCount);
110484b38d3aa8b6be6a7f5bebb472ab439da0562824fTobin Ehlis    }
11049651d92815dfff917308137bb67aacccc4f60df86Chris Forbes
110501344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis    for (uint32_t bindIdx = 0; bindIdx < bindInfoCount; ++bindIdx) {
110511344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis        const VkBindSparseInfo &bindInfo = pBindInfo[bindIdx];
110525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Track objects tied to memory
110531344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis        for (uint32_t j = 0; j < bindInfo.bufferBindCount; j++) {
110541344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis            for (uint32_t k = 0; k < bindInfo.pBufferBinds[j].bindCount; k++) {
110551344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                if (set_sparse_mem_binding(dev_data, bindInfo.pBufferBinds[j].pBinds[k].memory,
110561344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                                           (uint64_t)bindInfo.pBufferBinds[j].buffer, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT,
110575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                           "vkQueueBindSparse"))
11058e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                    skip_call = true;
110595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
110605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
110611344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis        for (uint32_t j = 0; j < bindInfo.imageOpaqueBindCount; j++) {
110621344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis            for (uint32_t k = 0; k < bindInfo.pImageOpaqueBinds[j].bindCount; k++) {
110631344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                if (set_sparse_mem_binding(dev_data, bindInfo.pImageOpaqueBinds[j].pBinds[k].memory,
110641344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                                           (uint64_t)bindInfo.pImageOpaqueBinds[j].image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
110655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                           "vkQueueBindSparse"))
11066e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                    skip_call = true;
110675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
110685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
110691344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis        for (uint32_t j = 0; j < bindInfo.imageBindCount; j++) {
110701344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis            for (uint32_t k = 0; k < bindInfo.pImageBinds[j].bindCount; k++) {
110711344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                if (set_sparse_mem_binding(dev_data, bindInfo.pImageBinds[j].pBinds[k].memory,
110721344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                                           (uint64_t)bindInfo.pImageBinds[j].image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
110735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                           "vkQueueBindSparse"))
11074e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                    skip_call = true;
110755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
110765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
110779867daedbf52debc77d6568162ee21e071699b80Chris Forbes
110789867daedbf52debc77d6568162ee21e071699b80Chris Forbes        std::vector<SEMAPHORE_WAIT> semaphore_waits;
110799867daedbf52debc77d6568162ee21e071699b80Chris Forbes        std::vector<VkSemaphore> semaphore_signals;
110801344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis        for (uint32_t i = 0; i < bindInfo.waitSemaphoreCount; ++i) {
1108101a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes            VkSemaphore semaphore = bindInfo.pWaitSemaphores[i];
1108201a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes            auto pSemaphore = getSemaphoreNode(dev_data, semaphore);
1108301a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes            if (pSemaphore) {
1108401a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes                if (pSemaphore->signaled) {
110859867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    if (pSemaphore->signaler.first != VK_NULL_HANDLE) {
110869867daedbf52debc77d6568162ee21e071699b80Chris Forbes                        semaphore_waits.push_back({semaphore, pSemaphore->signaler.first, pSemaphore->signaler.second});
110879867daedbf52debc77d6568162ee21e071699b80Chris Forbes                        pSemaphore->in_use.fetch_add(1);
110889867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    }
110899867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    pSemaphore->signaler.first = VK_NULL_HANDLE;
1109001a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes                    pSemaphore->signaled = false;
110911344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                } else {
110921344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                    skip_call |=
110935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT,
110941344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                                reinterpret_cast<const uint64_t &>(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS",
11095414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                "vkQueueBindSparse: Queue 0x%" PRIx64 " is waiting on semaphore 0x%" PRIx64
110961344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                                " that has no way to be signaled.",
110971344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                                reinterpret_cast<const uint64_t &>(queue), reinterpret_cast<const uint64_t &>(semaphore));
110985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
110995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
111005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
111011344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis        for (uint32_t i = 0; i < bindInfo.signalSemaphoreCount; ++i) {
1110201a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes            VkSemaphore semaphore = bindInfo.pSignalSemaphores[i];
1110301a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes            auto pSemaphore = getSemaphoreNode(dev_data, semaphore);
1110401a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes            if (pSemaphore) {
1110501a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes                if (pSemaphore->signaled) {
111065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    skip_call =
111075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT,
111081344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                                reinterpret_cast<const uint64_t &>(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS",
11109414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                                "vkQueueBindSparse: Queue 0x%" PRIx64 " is signaling semaphore 0x%" PRIx64
111101344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                                ", but that semaphore is already signaled.",
111111344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                                reinterpret_cast<const uint64_t &>(queue), reinterpret_cast<const uint64_t &>(semaphore));
111125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
111139867daedbf52debc77d6568162ee21e071699b80Chris Forbes                else {
111149867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    pSemaphore->signaler.first = queue;
111159867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    pSemaphore->signaler.second = pQueue->seq + pQueue->submissions.size() + 1;
111169867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    pSemaphore->signaled = true;
111179867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    pSemaphore->in_use.fetch_add(1);
111189867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    semaphore_signals.push_back(semaphore);
111199867daedbf52debc77d6568162ee21e071699b80Chris Forbes                }
111205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
111215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
111229867daedbf52debc77d6568162ee21e071699b80Chris Forbes
111239867daedbf52debc77d6568162ee21e071699b80Chris Forbes        pQueue->submissions.emplace_back(std::vector<VkCommandBuffer>(),
111249867daedbf52debc77d6568162ee21e071699b80Chris Forbes                                         semaphore_waits,
111259867daedbf52debc77d6568162ee21e071699b80Chris Forbes                                         semaphore_signals,
111269867daedbf52debc77d6568162ee21e071699b80Chris Forbes                                         bindIdx == bindInfoCount - 1 ? fence : VK_NULL_HANDLE);
111275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
111289867daedbf52debc77d6568162ee21e071699b80Chris Forbes
111299867daedbf52debc77d6568162ee21e071699b80Chris Forbes    if (pFence && !bindInfoCount) {
111309867daedbf52debc77d6568162ee21e071699b80Chris Forbes        // No work to do, just dropping a fence in the queue by itself.
111319867daedbf52debc77d6568162ee21e071699b80Chris Forbes        pQueue->submissions.emplace_back(std::vector<VkCommandBuffer>(),
111329867daedbf52debc77d6568162ee21e071699b80Chris Forbes                                         std::vector<SEMAPHORE_WAIT>(),
111339867daedbf52debc77d6568162ee21e071699b80Chris Forbes                                         std::vector<VkSemaphore>(),
111349867daedbf52debc77d6568162ee21e071699b80Chris Forbes                                         fence);
111359867daedbf52debc77d6568162ee21e071699b80Chris Forbes    }
111369867daedbf52debc77d6568162ee21e071699b80Chris Forbes
111370a1ce3dfd81c9f4efbe46f5ba5ddaea70bc4aa61Chris Forbes    print_mem_list(dev_data);
11138b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
111395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
11140e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    if (!skip_call)
111414a0754042cf090e131e9e769d8a3633c228625beChris Forbes        return dev_data->dispatch_table.QueueBindSparse(queue, bindInfoCount, pBindInfo, fence);
111425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
111435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
111445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
111455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1114689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo *pCreateInfo,
1114789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                               const VkAllocationCallbacks *pAllocator, VkSemaphore *pSemaphore) {
111485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
111494a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateSemaphore(device, pCreateInfo, pAllocator, pSemaphore);
111505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (result == VK_SUCCESS) {
11151b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        std::lock_guard<std::mutex> lock(global_lock);
111525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        SEMAPHORE_NODE* sNode = &dev_data->semaphoreMap[*pSemaphore];
111539867daedbf52debc77d6568162ee21e071699b80Chris Forbes        sNode->signaler.first = VK_NULL_HANDLE;
111549867daedbf52debc77d6568162ee21e071699b80Chris Forbes        sNode->signaler.second = 0;
111551344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis        sNode->signaled = false;
111565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
111575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
111585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
111595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
111605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin EhlisVKAPI_ATTR VkResult VKAPI_CALL
1116189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCreateEvent(VkDevice device, const VkEventCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkEvent *pEvent) {
111625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
111634a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateEvent(device, pCreateInfo, pAllocator, pEvent);
111645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (result == VK_SUCCESS) {
11165b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        std::lock_guard<std::mutex> lock(global_lock);
111665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        dev_data->eventMap[*pEvent].needsSignaled = false;
11167293ecfc5e69ed3978a8c04518166d828294870a4Tony Barbour        dev_data->eventMap[*pEvent].write_in_use = 0;
111685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        dev_data->eventMap[*pEvent].stageMask = VkPipelineStageFlags(0);
111695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
111705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
111715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
111725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
11173d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbesstatic bool PreCallValidateCreateSwapchainKHR(layer_data *dev_data, VkSwapchainCreateInfoKHR const *pCreateInfo,
11174d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes                                              SURFACE_STATE *surface_state, SWAPCHAIN_NODE *old_swapchain_state) {
11175d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes    auto most_recent_swapchain = surface_state->swapchain ? surface_state->swapchain : surface_state->old_swapchain;
11176d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes
11177d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes    if (most_recent_swapchain != old_swapchain_state || (surface_state->old_swapchain && surface_state->swapchain)) {
11178d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes        if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
11179d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes                    reinterpret_cast<uint64_t>(dev_data->device), __LINE__, DRAWSTATE_SWAPCHAIN_ALREADY_EXISTS, "DS",
11180d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes                    "vkCreateSwapchainKHR(): surface has an existing swapchain other than oldSwapchain"))
11181d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes            return true;
11182d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes    }
11183d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes    if (old_swapchain_state && old_swapchain_state->createInfo.surface != pCreateInfo->surface) {
11184d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes        if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
11185d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes                    reinterpret_cast<uint64_t const &>(pCreateInfo->oldSwapchain), __LINE__, DRAWSTATE_SWAPCHAIN_WRONG_SURFACE,
11186d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes                    "DS", "vkCreateSwapchainKHR(): pCreateInfo->oldSwapchain's surface is not pCreateInfo->surface"))
11187d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes            return true;
11188d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes    }
11189d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes
11190d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes    return false;
11191d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes}
11192d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes
1119389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
1119489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                  const VkAllocationCallbacks *pAllocator,
1119589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                  VkSwapchainKHR *pSwapchain) {
111965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
11197ddc5201048319558ce66701163a4546ee957af19Chris Forbes    auto surface_state = getSurfaceState(dev_data->instance_data, pCreateInfo->surface);
11198ddc5201048319558ce66701163a4546ee957af19Chris Forbes    auto old_swapchain_state = getSwapchainNode(dev_data, pCreateInfo->oldSwapchain);
11199ddc5201048319558ce66701163a4546ee957af19Chris Forbes
11200d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes    if (PreCallValidateCreateSwapchainKHR(dev_data, pCreateInfo, surface_state, old_swapchain_state))
11201d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes        return VK_ERROR_VALIDATION_FAILED_EXT;
11202d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes
112034a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
112045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
112055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
11206b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        std::lock_guard<std::mutex> lock(global_lock);
11207ddc5201048319558ce66701163a4546ee957af19Chris Forbes        auto swapchain_state = unique_ptr<SWAPCHAIN_NODE>(new SWAPCHAIN_NODE(pCreateInfo, *pSwapchain));
11208ddc5201048319558ce66701163a4546ee957af19Chris Forbes        surface_state->swapchain = swapchain_state.get();
11209ddc5201048319558ce66701163a4546ee957af19Chris Forbes        dev_data->device_extensions.swapchainMap[*pSwapchain] = std::move(swapchain_state);
11210ddc5201048319558ce66701163a4546ee957af19Chris Forbes    } else {
11211ddc5201048319558ce66701163a4546ee957af19Chris Forbes        surface_state->swapchain = nullptr;
112125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
112135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
11214ddc5201048319558ce66701163a4546ee957af19Chris Forbes    // Spec requires that even if CreateSwapchainKHR fails, oldSwapchain behaves as replaced.
11215ddc5201048319558ce66701163a4546ee957af19Chris Forbes    surface_state->old_swapchain = old_swapchain_state;
11216ddc5201048319558ce66701163a4546ee957af19Chris Forbes
112175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
112185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
112195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1122089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
1122189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *pAllocator) {
112225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1122383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
112245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
11225b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
11226b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis    auto swapchain_data = getSwapchainNode(dev_data, swapchain);
11227b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis    if (swapchain_data) {
11228b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis        if (swapchain_data->images.size() > 0) {
11229b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis            for (auto swapchain_image : swapchain_data->images) {
112305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                auto image_sub = dev_data->imageSubresourceMap.find(swapchain_image);
112315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if (image_sub != dev_data->imageSubresourceMap.end()) {
112325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    for (auto imgsubpair : image_sub->second) {
112335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        auto image_item = dev_data->imageLayoutMap.find(imgsubpair);
112345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        if (image_item != dev_data->imageLayoutMap.end()) {
112355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            dev_data->imageLayoutMap.erase(image_item);
112365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        }
112375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
112385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    dev_data->imageSubresourceMap.erase(image_sub);
112395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
1124083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                skip_call =
1124183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                    clear_object_binding(dev_data, (uint64_t)swapchain_image, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT);
1124294c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis                dev_data->imageMap.erase(swapchain_image);
112435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
112445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
11245ddc5201048319558ce66701163a4546ee957af19Chris Forbes
11246ddc5201048319558ce66701163a4546ee957af19Chris Forbes        auto surface_state = getSurfaceState(dev_data->instance_data, swapchain_data->createInfo.surface);
11247ddc5201048319558ce66701163a4546ee957af19Chris Forbes        if (surface_state) {
11248ddc5201048319558ce66701163a4546ee957af19Chris Forbes            if (surface_state->swapchain == swapchain_data)
11249ddc5201048319558ce66701163a4546ee957af19Chris Forbes                surface_state->swapchain = nullptr;
11250ddc5201048319558ce66701163a4546ee957af19Chris Forbes            if (surface_state->old_swapchain == swapchain_data)
11251ddc5201048319558ce66701163a4546ee957af19Chris Forbes                surface_state->old_swapchain = nullptr;
11252ddc5201048319558ce66701163a4546ee957af19Chris Forbes        }
11253ddc5201048319558ce66701163a4546ee957af19Chris Forbes
112545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        dev_data->device_extensions.swapchainMap.erase(swapchain);
112555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
11256b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
1125783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (!skip_call)
112584a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroySwapchainKHR(device, swapchain, pAllocator);
112595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
112605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1126189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL
1126289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pCount, VkImage *pSwapchainImages) {
112635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
112644a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.GetSwapchainImagesKHR(device, swapchain, pCount, pSwapchainImages);
112655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
112665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (result == VK_SUCCESS && pSwapchainImages != NULL) {
112675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // This should never happen and is checked by param checker.
112685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (!pCount)
112695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            return result;
11270b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        std::lock_guard<std::mutex> lock(global_lock);
112715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        const size_t count = *pCount;
11272b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis        auto swapchain_node = getSwapchainNode(dev_data, swapchain);
11273b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis        if (swapchain_node && !swapchain_node->images.empty()) {
112740801763633180d277d26a90343464bd11646056fTobin Ehlis            // TODO : Not sure I like the memcmp here, but it works
112750801763633180d277d26a90343464bd11646056fTobin Ehlis            const bool mismatch = (swapchain_node->images.size() != count ||
112760801763633180d277d26a90343464bd11646056fTobin Ehlis                                   memcmp(&swapchain_node->images[0], pSwapchainImages, sizeof(swapchain_node->images[0]) * count));
112775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (mismatch) {
112785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                // TODO: Verify against Valid Usage section of extension
112795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
112805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        (uint64_t)swapchain, __LINE__, MEMTRACK_NONE, "SWAP_CHAIN",
11281414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        "vkGetSwapchainInfoKHR(0x%" PRIx64
112825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        ", VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_KHR) returned mismatching data",
112835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        (uint64_t)(swapchain));
112845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
112855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
112865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t i = 0; i < *pCount; ++i) {
112875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            IMAGE_LAYOUT_NODE image_layout_node;
112885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            image_layout_node.layout = VK_IMAGE_LAYOUT_UNDEFINED;
112895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            image_layout_node.format = swapchain_node->createInfo.imageFormat;
112906d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            // Add imageMap entries for each swapchain image
112916d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            VkImageCreateInfo image_ci = {};
112926d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            image_ci.mipLevels = 1;
112936d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            image_ci.arrayLayers = swapchain_node->createInfo.imageArrayLayers;
112946d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            image_ci.usage = swapchain_node->createInfo.imageUsage;
112956d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            image_ci.format = swapchain_node->createInfo.imageFormat;
1129641ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis            image_ci.samples = VK_SAMPLE_COUNT_1_BIT;
112976d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            image_ci.extent.width = swapchain_node->createInfo.imageExtent.width;
112986d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            image_ci.extent.height = swapchain_node->createInfo.imageExtent.height;
112996d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            image_ci.sharingMode = swapchain_node->createInfo.imageSharingMode;
1130029e9a148072b1015633a102470f0cf706a9e2e55Tobin Ehlis            dev_data->imageMap[pSwapchainImages[i]] = unique_ptr<IMAGE_NODE>(new IMAGE_NODE(pSwapchainImages[i], &image_ci));
1130194c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis            auto &image_node = dev_data->imageMap[pSwapchainImages[i]];
113026d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            image_node->valid = false;
113036d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            image_node->mem = MEMTRACKER_SWAP_CHAIN_IMAGE_KEY;
113045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            swapchain_node->images.push_back(pSwapchainImages[i]);
113055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            ImageSubresourcePair subpair = {pSwapchainImages[i], false, VkImageSubresource()};
113065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            dev_data->imageSubresourceMap[pSwapchainImages[i]].push_back(subpair);
113075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            dev_data->imageLayoutMap[subpair] = image_layout_node;
113085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            dev_data->device_extensions.imageToSwapchainMap[pSwapchainImages[i]] = swapchain;
113095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
113105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
113115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
113125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
113135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1131489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) {
113155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
113165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    bool skip_call = false;
113175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
113186c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes    std::lock_guard<std::mutex> lock(global_lock);
113196c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes    for (uint32_t i = 0; i < pPresentInfo->waitSemaphoreCount; ++i) {
113206c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes        auto pSemaphore = getSemaphoreNode(dev_data, pPresentInfo->pWaitSemaphores[i]);
113216c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes        if (pSemaphore && !pSemaphore->signaled) {
113226c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes            skip_call |=
113236c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
113246c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes                            VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS",
113256c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes                            "Queue 0x%" PRIx64 " is waiting on semaphore 0x%" PRIx64 " that has no way to be signaled.",
113266c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes                            reinterpret_cast<uint64_t &>(queue), reinterpret_cast<const uint64_t &>(pPresentInfo->pWaitSemaphores[i]));
113275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
113286c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes    }
11329249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis
113306c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes    for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) {
113316c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes        auto swapchain_data = getSwapchainNode(dev_data, pPresentInfo->pSwapchains[i]);
11332a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes        if (swapchain_data) {
11333a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes            if (pPresentInfo->pImageIndices[i] >= swapchain_data->images.size()) {
11334a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
11335d17d86d15a733f1ec988956721ea4b7cdfb6771bChris Forbes                                     reinterpret_cast<uint64_t const &>(pPresentInfo->pSwapchains[i]), __LINE__, DRAWSTATE_SWAPCHAIN_INVALID_IMAGE,
11336a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                                     "DS", "vkQueuePresentKHR: Swapchain image index too large (%u). There are only %u images in this swapchain.",
11337a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                                     pPresentInfo->pImageIndices[i], (uint32_t)swapchain_data->images.size());
11338a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes            }
11339a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes            else {
11340a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                auto image = swapchain_data->images[pPresentInfo->pImageIndices[i]];
11341a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                auto image_node = getImageNode(dev_data, image);
11342a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                skip_call |= ValidateImageMemoryIsValid(dev_data, image_node, "vkQueuePresentKHR()");
11343a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes
11344a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                if (!image_node->acquired) {
11345a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                    skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
11346a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                                         reinterpret_cast<uint64_t const &>(pPresentInfo->pSwapchains[i]), __LINE__, DRAWSTATE_SWAPCHAIN_IMAGE_NOT_ACQUIRED,
11347a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                                         "DS", "vkQueuePresentKHR: Swapchain image index %u has not been acquired.",
11348a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                                         pPresentInfo->pImageIndices[i]);
11349a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                }
11350a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes
11351a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                vector<VkImageLayout> layouts;
11352a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                if (FindLayouts(dev_data, image, layouts)) {
11353a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                    for (auto layout : layouts) {
11354a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                        if (layout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) {
11355a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                            skip_call |=
11356a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT,
11357a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                                            reinterpret_cast<uint64_t &>(queue), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
11358a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                                            "Images passed to present must be in layout "
11359a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                                            "VK_IMAGE_LAYOUT_PRESENT_SRC_KHR but is in %s",
11360a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                                            string_VkImageLayout(layout));
11361a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                        }
113625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
113635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
113645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
113655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
113665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
113675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
113686c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes    if (skip_call) {
113696c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes        return VK_ERROR_VALIDATION_FAILED_EXT;
113706c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes    }
113716c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes
113724a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.QueuePresentKHR(queue, pPresentInfo);
113736c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes
113746c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes    if (result != VK_ERROR_VALIDATION_FAILED_EXT) {
113756c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes        // Semaphore waits occur before error generation, if the call reached
113766c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes        // the ICD. (Confirm?)
113776c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes        for (uint32_t i = 0; i < pPresentInfo->waitSemaphoreCount; ++i) {
113786c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes            auto pSemaphore = getSemaphoreNode(dev_data, pPresentInfo->pWaitSemaphores[i]);
113799867daedbf52debc77d6568162ee21e071699b80Chris Forbes            if (pSemaphore) {
113809867daedbf52debc77d6568162ee21e071699b80Chris Forbes                pSemaphore->signaler.first = VK_NULL_HANDLE;
113816c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes                pSemaphore->signaled = false;
113826c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes            }
113836c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes        }
113849867daedbf52debc77d6568162ee21e071699b80Chris Forbes
11385220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes        for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) {
11386220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes            // Note: this is imperfect, in that we can get confused about what
11387220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes            // did or didn't succeed-- but if the app does that, it's confused
11388220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes            // itself just as much.
11389220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes            auto local_result = pPresentInfo->pResults ? pPresentInfo->pResults[i] : result;
11390220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes
11391220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes            if (local_result != VK_SUCCESS && local_result != VK_SUBOPTIMAL_KHR)
11392220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes                continue; // this present didn't actually happen.
11393220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes
11394220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes            // Mark the image as having been released to the WSI
11395220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes            auto swapchain_data = getSwapchainNode(dev_data, pPresentInfo->pSwapchains[i]);
11396220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes            auto image = swapchain_data->images[pPresentInfo->pImageIndices[i]];
11397220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes            auto image_node = getImageNode(dev_data, image);
11398220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes            image_node->acquired = false;
11399220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes        }
11400220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes
114019867daedbf52debc77d6568162ee21e071699b80Chris Forbes        // Note: even though presentation is directed to a queue, there is no
114029867daedbf52debc77d6568162ee21e071699b80Chris Forbes        // direct ordering between QP and subsequent work, so QP (and its
114039867daedbf52debc77d6568162ee21e071699b80Chris Forbes        // semaphore waits) /never/ participate in any completion proof.
114046c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes    }
114051344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis
114065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
114075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
114085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
11409c827a5880dc3fabfc7d1a58bb62798649cab1181Mark YoungVKAPI_ATTR VkResult VKAPI_CALL CreateSharedSwapchainsKHR(VkDevice device, uint32_t swapchainCount,
11410c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young                                                         const VkSwapchainCreateInfoKHR *pCreateInfos,
11411c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young                                                         const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchains) {
11412c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
11413c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young    std::unique_lock<std::mutex> lock(global_lock);
11414c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young    VkResult result =
114154a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CreateSharedSwapchainsKHR(device, swapchainCount, pCreateInfos, pAllocator, pSwapchains);
11416c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young    return result;
11417c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young}
11418c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young
1141989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout,
1142089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                   VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) {
114215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1142283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
114231344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis
11424b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::unique_lock<std::mutex> lock(global_lock);
11425449670637ef4214b33018f497cf10daeff9dc85bChris Forbes
11426449670637ef4214b33018f497cf10daeff9dc85bChris Forbes    if (fence == VK_NULL_HANDLE && semaphore == VK_NULL_HANDLE) {
11427449670637ef4214b33018f497cf10daeff9dc85bChris Forbes        skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
11428d17d86d15a733f1ec988956721ea4b7cdfb6771bChris Forbes                             reinterpret_cast<uint64_t &>(device), __LINE__, DRAWSTATE_SWAPCHAIN_NO_SYNC_FOR_ACQUIRE, "DS",
11429449670637ef4214b33018f497cf10daeff9dc85bChris Forbes                             "vkAcquireNextImageKHR: Semaphore and fence cannot both be VK_NULL_HANDLE. There would be no way "
11430449670637ef4214b33018f497cf10daeff9dc85bChris Forbes                             "to determine the completion of this operation.");
11431449670637ef4214b33018f497cf10daeff9dc85bChris Forbes    }
11432449670637ef4214b33018f497cf10daeff9dc85bChris Forbes
11433f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes    auto pSemaphore = getSemaphoreNode(dev_data, semaphore);
11434f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes    if (pSemaphore && pSemaphore->signaled) {
1143583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT,
1143683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                             reinterpret_cast<const uint64_t &>(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS",
1143783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                             "vkAcquireNextImageKHR: Semaphore must not be currently signaled or in a wait state");
114385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
11439f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes
11440f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes    auto pFence = getFenceNode(dev_data, fence);
11441f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes    if (pFence) {
1144283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        skip_call |= ValidateFenceForSubmit(dev_data, pFence);
114435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
11444b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
114451344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis
1144683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    if (skip_call)
11447f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes        return VK_ERROR_VALIDATION_FAILED_EXT;
11448f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes
114494a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex);
11450f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes
11451f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes    lock.lock();
11452f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes    if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) {
11453f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes        if (pFence) {
11454f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes            pFence->state = FENCE_INFLIGHT;
114559867daedbf52debc77d6568162ee21e071699b80Chris Forbes            pFence->signaler.first = VK_NULL_HANDLE;   // ANI isn't on a queue, so this can't participate in a completion proof.
11456f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes        }
11457f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes
11458f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes        // A successful call to AcquireNextImageKHR counts as a signal operation on semaphore
11459f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes        if (pSemaphore) {
11460f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes            pSemaphore->signaled = true;
114619867daedbf52debc77d6568162ee21e071699b80Chris Forbes            pSemaphore->signaler.first = VK_NULL_HANDLE;
11462f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes        }
11463220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes
11464220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes        // Mark the image as acquired.
11465220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes        auto swapchain_data = getSwapchainNode(dev_data, swapchain);
11466220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes        auto image = swapchain_data->images[*pImageIndex];
11467220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes        auto image_node = getImageNode(dev_data, image);
11468220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes        image_node->acquired = true;
114695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
11470f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes    lock.unlock();
114711344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis
114725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
114735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
114745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
11475f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount,
11476f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski                                                        VkPhysicalDevice *pPhysicalDevices) {
1147783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis    bool skip_call = false;
11478f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes    instance_layer_data *instance_data = get_my_data_ptr(get_dispatch_key(instance), instance_layer_data_map);
11479b1f16c99e817d67a9f6c87d92e312478de4721d7Chris Forbes    if (instance_data->instance_state) {
11480f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski        // For this instance, flag when vkEnumeratePhysicalDevices goes to QUERY_COUNT and then QUERY_DETAILS
11481f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski        if (NULL == pPhysicalDevices) {
11482b1f16c99e817d67a9f6c87d92e312478de4721d7Chris Forbes            instance_data->instance_state->vkEnumeratePhysicalDevicesState = QUERY_COUNT;
11483f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski        } else {
11484b1f16c99e817d67a9f6c87d92e312478de4721d7Chris Forbes            if (UNCALLED == instance_data->instance_state->vkEnumeratePhysicalDevicesState) {
11485f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski                // Flag warning here. You can call this without having queried the count, but it may not be
11486f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski                // robust on platforms with multiple physical devices.
11487b1f16c99e817d67a9f6c87d92e312478de4721d7Chris Forbes                skip_call |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
11488f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski                                    0, __LINE__, DEVLIMITS_MISSING_QUERY_COUNT, "DL",
11489f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski                                    "Call sequence has vkEnumeratePhysicalDevices() w/ non-NULL pPhysicalDevices. You should first "
11490f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski                                    "call vkEnumeratePhysicalDevices() w/ NULL pPhysicalDevices to query pPhysicalDeviceCount.");
11491f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski            } // TODO : Could also flag a warning if re-calling this function in QUERY_DETAILS state
11492b1f16c99e817d67a9f6c87d92e312478de4721d7Chris Forbes            else if (instance_data->instance_state->physical_devices_count != *pPhysicalDeviceCount) {
11493f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski                // Having actual count match count from app is not a requirement, so this can be a warning
11494b1f16c99e817d67a9f6c87d92e312478de4721d7Chris Forbes                skip_call |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
11495f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski                                    VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL",
11496f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski                                    "Call to vkEnumeratePhysicalDevices() w/ pPhysicalDeviceCount value %u, but actual count "
11497f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski                                    "supported by this instance is %u.",
11498b1f16c99e817d67a9f6c87d92e312478de4721d7Chris Forbes                                    *pPhysicalDeviceCount, instance_data->instance_state->physical_devices_count);
11499f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski            }
11500b1f16c99e817d67a9f6c87d92e312478de4721d7Chris Forbes            instance_data->instance_state->vkEnumeratePhysicalDevicesState = QUERY_DETAILS;
11501f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski        }
1150283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis        if (skip_call) {
11503f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski            return VK_ERROR_VALIDATION_FAILED_EXT;
11504f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski        }
115059172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes        VkResult result = instance_data->dispatch_table.EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
11506f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski        if (NULL == pPhysicalDevices) {
11507b1f16c99e817d67a9f6c87d92e312478de4721d7Chris Forbes            instance_data->instance_state->physical_devices_count = *pPhysicalDeviceCount;
115085f270eedee8426a5b556a8a9432dd836d83f7b51Tony Barbour        } else if (result == VK_SUCCESS){ // Save physical devices
11509f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski            for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) {
115103bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes                auto & phys_device_state = instance_data->physical_device_map[pPhysicalDevices[i]];
115113bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes                phys_device_state.phys_device = pPhysicalDevices[i];
11512f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski                // Init actual features for each physical device
115139172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes                instance_data->dispatch_table.GetPhysicalDeviceFeatures(pPhysicalDevices[i], &phys_device_state.features);
11514f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski            }
11515f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski        }
11516f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski        return result;
11517f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    } else {
11518b1f16c99e817d67a9f6c87d92e312478de4721d7Chris Forbes        log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 0, __LINE__,
11519f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski                DEVLIMITS_INVALID_INSTANCE, "DL", "Invalid instance (0x%" PRIxLEAST64 ") passed into vkEnumeratePhysicalDevices().",
11520f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski                (uint64_t)instance);
11521f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    }
11522f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    return VK_ERROR_VALIDATION_FAILED_EXT;
11523f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski}
11524f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski
11525cd569b3559a7f8dca06012165480a4e6d7e6c492Mark LobodzinskiVKAPI_ATTR void VKAPI_CALL
11526cd569b3559a7f8dca06012165480a4e6d7e6c492Mark LobodzinskiGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
11527cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski    VkQueueFamilyProperties *pQueueFamilyProperties) {
11528cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski    bool skip_call = false;
11529f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes    instance_layer_data *instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), instance_layer_data_map);
115301f8e18308ae29b5220ce300f0d4dc964bc0941d6Chris Forbes    auto physical_device_state = getPhysicalDeviceState(instance_data, physicalDevice);
115314b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes    if (physical_device_state) {
115324b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes        if (!pQueueFamilyProperties) {
115334b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes            physical_device_state->vkGetPhysicalDeviceQueueFamilyPropertiesState = QUERY_COUNT;
11534cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski        }
11535cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski        else {
11536cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski            // Verify that for each physical device, this function is called first with NULL pQueueFamilyProperties ptr in order to
11537cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski            // get count
115384b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes            if (UNCALLED == physical_device_state->vkGetPhysicalDeviceQueueFamilyPropertiesState) {
115391f8e18308ae29b5220ce300f0d4dc964bc0941d6Chris Forbes                skip_call |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
11540cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski                    VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_MISSING_QUERY_COUNT, "DL",
11541cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski                    "Call sequence has vkGetPhysicalDeviceQueueFamilyProperties() w/ non-NULL "
11542cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski                    "pQueueFamilyProperties. You should first call vkGetPhysicalDeviceQueueFamilyProperties() w/ "
11543cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski                    "NULL pQueueFamilyProperties to query pCount.");
11544cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski            }
11545cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski            // Then verify that pCount that is passed in on second call matches what was returned
115464b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes            if (physical_device_state->queueFamilyPropertiesCount != *pCount) {
11547cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski
11548cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski                // TODO: this is not a requirement of the Valid Usage section for vkGetPhysicalDeviceQueueFamilyProperties, so
11549cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski                // provide as warning
115501f8e18308ae29b5220ce300f0d4dc964bc0941d6Chris Forbes                skip_call |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
11551cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski                    VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL",
11552cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski                    "Call to vkGetPhysicalDeviceQueueFamilyProperties() w/ pCount value %u, but actual count "
11553cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski                    "supported by this physicalDevice is %u.",
115544b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes                    *pCount, physical_device_state->queueFamilyPropertiesCount);
11555cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski            }
115564b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes            physical_device_state->vkGetPhysicalDeviceQueueFamilyPropertiesState = QUERY_DETAILS;
11557cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski        }
11558cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski        if (skip_call) {
11559cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski            return;
11560cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski        }
115619172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes        instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pCount, pQueueFamilyProperties);
115624b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes        if (!pQueueFamilyProperties) {
115634b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes            physical_device_state->queueFamilyPropertiesCount = *pCount;
11564cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski        }
11565cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski        else { // Save queue family properties
115667d8b6ab1b68c397da50bad43deb1fba389ebace7Chris Forbes            if (physical_device_state->queue_family_properties.size() < *pCount)
115677d8b6ab1b68c397da50bad43deb1fba389ebace7Chris Forbes                physical_device_state->queue_family_properties.resize(*pCount);
11568cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski            for (uint32_t i = 0; i < *pCount; i++) {
115697d8b6ab1b68c397da50bad43deb1fba389ebace7Chris Forbes                physical_device_state->queue_family_properties[i] = pQueueFamilyProperties[i];
11570cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski            }
11571cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski        }
11572cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski    }
11573cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski    else {
115741f8e18308ae29b5220ce300f0d4dc964bc0941d6Chris Forbes        log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0,
11575cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski            __LINE__, DEVLIMITS_INVALID_PHYSICAL_DEVICE, "DL",
11576cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski            "Invalid physicalDevice (0x%" PRIxLEAST64 ") passed into vkGetPhysicalDeviceQueueFamilyProperties().",
11577cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski            (uint64_t)physicalDevice);
11578cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski    }
11579cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski}
11580cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski
11581747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbestemplate<typename TCreateInfo, typename FPtr>
11582747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbesstatic VkResult CreateSurface(VkInstance instance, TCreateInfo const *pCreateInfo,
11583747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes                              VkAllocationCallbacks const *pAllocator, VkSurfaceKHR *pSurface,
11584747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes                              FPtr fptr)
11585747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes{
11586747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    instance_layer_data *instance_data = get_my_data_ptr(get_dispatch_key(instance), instance_layer_data_map);
11587747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
11588747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    // Call down the call chain:
11589747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    VkResult result = (instance_data->dispatch_table.*fptr)(instance, pCreateInfo, pAllocator, pSurface);
11590747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
11591747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    if (result == VK_SUCCESS) {
11592747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        std::unique_lock<std::mutex> lock(global_lock);
11593747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        instance_data->surface_map[*pSurface] = SURFACE_STATE(*pSurface);
11594747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        lock.unlock();
11595747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    }
11596747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
11597747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    return result;
11598747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
11599747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
11600747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR void VKAPI_CALL DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks *pAllocator) {
11601747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    bool skip_call = false;
11602747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    instance_layer_data *instance_data = get_my_data_ptr(get_dispatch_key(instance), instance_layer_data_map);
11603747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    std::unique_lock<std::mutex> lock(global_lock);
11604747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    auto surface_state = getSurfaceState(instance_data, surface);
11605747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
11606747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    if (surface_state) {
11607747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        // TODO: track swapchains created from this surface.
11608747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        instance_data->surface_map.erase(surface);
11609747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    }
11610747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    lock.unlock();
11611747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
11612747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    if (!skip_call) {
11613747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        // Call down the call chain:
11614747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        instance_data->dispatch_table.DestroySurfaceKHR(instance, surface, pAllocator);
11615747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    }
11616747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
11617747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
11618747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_ANDROID_KHR
11619747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR *pCreateInfo,
11620747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes                                                       const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
11621747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateAndroidSurfaceKHR);
11622747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
11623747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif // VK_USE_PLATFORM_ANDROID_KHR
11624747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
11625747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_MIR_KHR
11626747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateMirSurfaceKHR(VkInstance instance, const VkMirSurfaceCreateInfoKHR *pCreateInfo,
11627747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes                                                   const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
11628747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateMirSurfaceKHR);
11629747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
11630747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif // VK_USE_PLATFORM_MIR_KHR
11631747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
11632747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WAYLAND_KHR
11633747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateWaylandSurfaceKHR(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
11634747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes                                                       const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
11635a9c6cc532ce0ef61d48d1419a96aae51b0e4c64aTobin Ehlis    return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateWaylandSurfaceKHR);
11636747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
11637747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif // VK_USE_PLATFORM_WAYLAND_KHR
11638747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
11639747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WIN32_KHR
11640747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
11641747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes                                                     const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
11642747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateWin32SurfaceKHR);
11643747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
11644747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif // VK_USE_PLATFORM_WIN32_KHR
11645747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
11646747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XCB_KHR
11647747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateXcbSurfaceKHR(VkInstance instance, const VkXcbSurfaceCreateInfoKHR *pCreateInfo,
11648747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes                                                   const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
11649747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateXcbSurfaceKHR);
11650747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
11651747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif // VK_USE_PLATFORM_XCB_KHR
11652747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
11653747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XLIB_KHR
11654747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateXlibSurfaceKHR(VkInstance instance, const VkXlibSurfaceCreateInfoKHR *pCreateInfo,
11655747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes                                                   const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
11656747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateXlibSurfaceKHR);
11657747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
11658747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif // VK_USE_PLATFORM_XLIB_KHR
11659747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
11660747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
1166189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL
1166289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
1166389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                             const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
116648860b85a52096f9f9b28616bc37feed505497a54Chris Forbes    instance_layer_data *instance_data = get_my_data_ptr(get_dispatch_key(instance), instance_layer_data_map);
116659172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    VkResult res = instance_data->dispatch_table.CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
116665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == res) {
11667b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        std::lock_guard<std::mutex> lock(global_lock);
116688860b85a52096f9f9b28616bc37feed505497a54Chris Forbes        res = layer_create_msg_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback);
116695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
116705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return res;
116715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
116725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1167389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance,
1167489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                         VkDebugReportCallbackEXT msgCallback,
1167589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                         const VkAllocationCallbacks *pAllocator) {
116768860b85a52096f9f9b28616bc37feed505497a54Chris Forbes    instance_layer_data *instance_data = get_my_data_ptr(get_dispatch_key(instance), instance_layer_data_map);
116779172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    instance_data->dispatch_table.DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
11678b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    std::lock_guard<std::mutex> lock(global_lock);
116798860b85a52096f9f9b28616bc37feed505497a54Chris Forbes    layer_destroy_msg_callback(instance_data->report_data, msgCallback, pAllocator);
116805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
116815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1168289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL
1168389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
1168489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                      size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
116858860b85a52096f9f9b28616bc37feed505497a54Chris Forbes    instance_layer_data *instance_data = get_my_data_ptr(get_dispatch_key(instance), instance_layer_data_map);
116869172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    instance_data->dispatch_table.DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
116875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
116885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
11689a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL
11690a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I WuEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
11691a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
11692a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu}
11693a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu
11694a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL
11695a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I WuEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
11696a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
11697a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu}
11698a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu
11699a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL
11700a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I WuEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
11701a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
11702a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu        return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
11703a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu
11704a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    return VK_ERROR_LAYER_NOT_PRESENT;
11705a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu}
11706a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu
1170789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1170889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                                  const char *pLayerName, uint32_t *pCount,
1170989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                                  VkExtensionProperties *pProperties) {
11710a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu    if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
1171108939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu        return util_GetExtensionProperties(0, NULL, pCount, pProperties);
11712a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu
11713a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu    assert(physicalDevice);
11714a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu
117159172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    instance_layer_data *instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), instance_layer_data_map);
117169172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    return instance_data->dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
1171708939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu}
1171808939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu
1171980be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wustatic PFN_vkVoidFunction
117207ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wuintercept_core_instance_command(const char *name);
117217ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu
117227ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wustatic PFN_vkVoidFunction
1172380be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wuintercept_core_device_command(const char *name);
1172480be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu
1172509a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wustatic PFN_vkVoidFunction
1172609a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wuintercept_khr_swapchain_command(const char *name, VkDevice dev);
1172709a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu
11728747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbesstatic PFN_vkVoidFunction
11729747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbesintercept_khr_surface_command(const char *name, VkInstance instance);
11730747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
1173189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice dev, const char *funcName) {
1173280be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu    PFN_vkVoidFunction proc = intercept_core_device_command(funcName);
1173380be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu    if (proc)
1173480be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu        return proc;
1173580be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu
1173680be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu    assert(dev);
117375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1173809a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu    proc = intercept_khr_swapchain_command(funcName, dev);
1173909a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu    if (proc)
1174009a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu        return proc;
1174109a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu
11742f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(dev), layer_data_map);
117435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
117444a0754042cf090e131e9e769d8a3633c228625beChris Forbes    auto &table = dev_data->dispatch_table;
117454a0754042cf090e131e9e769d8a3633c228625beChris Forbes    if (!table.GetDeviceProcAddr)
117464a0754042cf090e131e9e769d8a3633c228625beChris Forbes        return nullptr;
117474a0754042cf090e131e9e769d8a3633c228625beChris Forbes    return table.GetDeviceProcAddr(dev, funcName);
117485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
117495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1175089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
117517ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu    PFN_vkVoidFunction proc = intercept_core_instance_command(funcName);
117523f6f8132355ebdae2736b31fc20de2ac60a70310Chia-I Wu    if (!proc)
117533f6f8132355ebdae2736b31fc20de2ac60a70310Chia-I Wu        proc = intercept_core_device_command(funcName);
117543f6f8132355ebdae2736b31fc20de2ac60a70310Chia-I Wu    if (!proc)
117553f6f8132355ebdae2736b31fc20de2ac60a70310Chia-I Wu        proc = intercept_khr_swapchain_command(funcName, VK_NULL_HANDLE);
11756747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    if (!proc)
11757747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        proc = intercept_khr_surface_command(funcName, instance);
117587ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu    if (proc)
117597ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu        return proc;
117605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
117617ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu    assert(instance);
117625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
117638860b85a52096f9f9b28616bc37feed505497a54Chris Forbes    instance_layer_data *instance_data = get_my_data_ptr(get_dispatch_key(instance), instance_layer_data_map);
117648860b85a52096f9f9b28616bc37feed505497a54Chris Forbes    proc = debug_report_get_instance_proc_addr(instance_data->report_data, funcName);
117657ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu    if (proc)
117667ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu        return proc;
117675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
117684a0754042cf090e131e9e769d8a3633c228625beChris Forbes    auto &table = instance_data->dispatch_table;
117694a0754042cf090e131e9e769d8a3633c228625beChris Forbes    if (!table.GetInstanceProcAddr)
117704a0754042cf090e131e9e769d8a3633c228625beChris Forbes        return nullptr;
117714a0754042cf090e131e9e769d8a3633c228625beChris Forbes    return table.GetInstanceProcAddr(instance, funcName);
117725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
1177308939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu
1177480be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wustatic PFN_vkVoidFunction
117757ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wuintercept_core_instance_command(const char *name) {
117767ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu    static const struct {
117777ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu        const char *name;
117787ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu        PFN_vkVoidFunction proc;
117797ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu    } core_instance_commands[] = {
117807ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu        { "vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr) },
117817ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu        { "vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr) },
117827ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu        { "vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance) },
117837ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu        { "vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(CreateDevice) },
11784f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski        { "vkEnumeratePhysicalDevices", reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices) },
11785cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski        { "vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceQueueFamilyProperties) },
117867ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu        { "vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance) },
11787a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu        { "vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceLayerProperties) },
11788a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu        { "vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceLayerProperties) },
11789a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu        { "vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties) },
117907ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu        { "vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties) },
117917ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu    };
117927ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu
117937ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu    for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) {
117947ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu        if (!strcmp(core_instance_commands[i].name, name))
117957ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu            return core_instance_commands[i].proc;
117967ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu    }
117977ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu
117987ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu    return nullptr;
117997ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu}
118007ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu
118017ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wustatic PFN_vkVoidFunction
1180280be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wuintercept_core_device_command(const char *name) {
1180380be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu    static const struct {
1180480be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu        const char *name;
1180580be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu        PFN_vkVoidFunction proc;
1180680be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu    } core_device_commands[] = {
11807593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr)},
11808593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkQueueSubmit", reinterpret_cast<PFN_vkVoidFunction>(QueueSubmit)},
11809593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkWaitForFences", reinterpret_cast<PFN_vkVoidFunction>(WaitForFences)},
11810593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkGetFenceStatus", reinterpret_cast<PFN_vkVoidFunction>(GetFenceStatus)},
11811593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkQueueWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(QueueWaitIdle)},
11812593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkDeviceWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(DeviceWaitIdle)},
11813593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue)},
11814593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance)},
11815593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice)},
11816593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkDestroyFence", reinterpret_cast<PFN_vkVoidFunction>(DestroyFence)},
11817593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkResetFences", reinterpret_cast<PFN_vkVoidFunction>(ResetFences)},
11818593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkDestroySemaphore", reinterpret_cast<PFN_vkVoidFunction>(DestroySemaphore)},
11819593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkDestroyEvent", reinterpret_cast<PFN_vkVoidFunction>(DestroyEvent)},
11820593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkDestroyQueryPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyQueryPool)},
11821593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkDestroyBuffer", reinterpret_cast<PFN_vkVoidFunction>(DestroyBuffer)},
11822593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkDestroyBufferView", reinterpret_cast<PFN_vkVoidFunction>(DestroyBufferView)},
11823593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkDestroyImage", reinterpret_cast<PFN_vkVoidFunction>(DestroyImage)},
11824593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkDestroyImageView", reinterpret_cast<PFN_vkVoidFunction>(DestroyImageView)},
11825593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkDestroyShaderModule", reinterpret_cast<PFN_vkVoidFunction>(DestroyShaderModule)},
11826593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkDestroyPipeline", reinterpret_cast<PFN_vkVoidFunction>(DestroyPipeline)},
11827593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkDestroyPipelineLayout", reinterpret_cast<PFN_vkVoidFunction>(DestroyPipelineLayout)},
11828593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkDestroySampler", reinterpret_cast<PFN_vkVoidFunction>(DestroySampler)},
11829593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkDestroyDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(DestroyDescriptorSetLayout)},
11830593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkDestroyDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyDescriptorPool)},
11831593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkDestroyFramebuffer", reinterpret_cast<PFN_vkVoidFunction>(DestroyFramebuffer)},
11832593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkDestroyRenderPass", reinterpret_cast<PFN_vkVoidFunction>(DestroyRenderPass)},
11833593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCreateBuffer", reinterpret_cast<PFN_vkVoidFunction>(CreateBuffer)},
11834593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCreateBufferView", reinterpret_cast<PFN_vkVoidFunction>(CreateBufferView)},
11835593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCreateImage", reinterpret_cast<PFN_vkVoidFunction>(CreateImage)},
11836593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCreateImageView", reinterpret_cast<PFN_vkVoidFunction>(CreateImageView)},
11837593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCreateFence", reinterpret_cast<PFN_vkVoidFunction>(CreateFence)},
11838593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCreatePipelineCache", reinterpret_cast<PFN_vkVoidFunction>(CreatePipelineCache)},
11839593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkDestroyPipelineCache", reinterpret_cast<PFN_vkVoidFunction>(DestroyPipelineCache)},
11840593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkGetPipelineCacheData", reinterpret_cast<PFN_vkVoidFunction>(GetPipelineCacheData)},
11841593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkMergePipelineCaches", reinterpret_cast<PFN_vkVoidFunction>(MergePipelineCaches)},
11842593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCreateGraphicsPipelines", reinterpret_cast<PFN_vkVoidFunction>(CreateGraphicsPipelines)},
11843593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCreateComputePipelines", reinterpret_cast<PFN_vkVoidFunction>(CreateComputePipelines)},
11844593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCreateSampler", reinterpret_cast<PFN_vkVoidFunction>(CreateSampler)},
11845593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCreateDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(CreateDescriptorSetLayout)},
11846593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCreatePipelineLayout", reinterpret_cast<PFN_vkVoidFunction>(CreatePipelineLayout)},
11847593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCreateDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(CreateDescriptorPool)},
11848593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkResetDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(ResetDescriptorPool)},
11849593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkAllocateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(AllocateDescriptorSets)},
11850593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkFreeDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(FreeDescriptorSets)},
11851593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkUpdateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(UpdateDescriptorSets)},
11852593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCreateCommandPool", reinterpret_cast<PFN_vkVoidFunction>(CreateCommandPool)},
11853593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkDestroyCommandPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyCommandPool)},
11854593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkResetCommandPool", reinterpret_cast<PFN_vkVoidFunction>(ResetCommandPool)},
11855593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCreateQueryPool", reinterpret_cast<PFN_vkVoidFunction>(CreateQueryPool)},
11856593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkAllocateCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(AllocateCommandBuffers)},
11857593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkFreeCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(FreeCommandBuffers)},
11858593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkBeginCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(BeginCommandBuffer)},
11859593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkEndCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(EndCommandBuffer)},
11860593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkResetCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(ResetCommandBuffer)},
11861593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdBindPipeline", reinterpret_cast<PFN_vkVoidFunction>(CmdBindPipeline)},
11862593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdSetViewport", reinterpret_cast<PFN_vkVoidFunction>(CmdSetViewport)},
11863593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdSetScissor", reinterpret_cast<PFN_vkVoidFunction>(CmdSetScissor)},
11864593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdSetLineWidth", reinterpret_cast<PFN_vkVoidFunction>(CmdSetLineWidth)},
11865593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdSetDepthBias", reinterpret_cast<PFN_vkVoidFunction>(CmdSetDepthBias)},
11866593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdSetBlendConstants", reinterpret_cast<PFN_vkVoidFunction>(CmdSetBlendConstants)},
11867593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdSetDepthBounds", reinterpret_cast<PFN_vkVoidFunction>(CmdSetDepthBounds)},
11868593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdSetStencilCompareMask", reinterpret_cast<PFN_vkVoidFunction>(CmdSetStencilCompareMask)},
11869593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdSetStencilWriteMask", reinterpret_cast<PFN_vkVoidFunction>(CmdSetStencilWriteMask)},
11870593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdSetStencilReference", reinterpret_cast<PFN_vkVoidFunction>(CmdSetStencilReference)},
11871593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdBindDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(CmdBindDescriptorSets)},
11872593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdBindVertexBuffers", reinterpret_cast<PFN_vkVoidFunction>(CmdBindVertexBuffers)},
11873593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdBindIndexBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdBindIndexBuffer)},
11874593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdDraw", reinterpret_cast<PFN_vkVoidFunction>(CmdDraw)},
11875593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdDrawIndexed", reinterpret_cast<PFN_vkVoidFunction>(CmdDrawIndexed)},
11876593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdDrawIndirect", reinterpret_cast<PFN_vkVoidFunction>(CmdDrawIndirect)},
11877593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdDrawIndexedIndirect", reinterpret_cast<PFN_vkVoidFunction>(CmdDrawIndexedIndirect)},
11878593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdDispatch", reinterpret_cast<PFN_vkVoidFunction>(CmdDispatch)},
11879593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdDispatchIndirect", reinterpret_cast<PFN_vkVoidFunction>(CmdDispatchIndirect)},
11880593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdCopyBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyBuffer)},
11881593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdCopyImage", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyImage)},
11882593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdBlitImage", reinterpret_cast<PFN_vkVoidFunction>(CmdBlitImage)},
11883593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdCopyBufferToImage", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyBufferToImage)},
11884593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdCopyImageToBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyImageToBuffer)},
11885593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdUpdateBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdUpdateBuffer)},
11886593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdFillBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdFillBuffer)},
11887593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdClearColorImage", reinterpret_cast<PFN_vkVoidFunction>(CmdClearColorImage)},
11888593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdClearDepthStencilImage", reinterpret_cast<PFN_vkVoidFunction>(CmdClearDepthStencilImage)},
11889593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdClearAttachments", reinterpret_cast<PFN_vkVoidFunction>(CmdClearAttachments)},
11890593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdResolveImage", reinterpret_cast<PFN_vkVoidFunction>(CmdResolveImage)},
11891593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdSetEvent", reinterpret_cast<PFN_vkVoidFunction>(CmdSetEvent)},
11892593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdResetEvent", reinterpret_cast<PFN_vkVoidFunction>(CmdResetEvent)},
11893593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdWaitEvents", reinterpret_cast<PFN_vkVoidFunction>(CmdWaitEvents)},
11894593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdPipelineBarrier", reinterpret_cast<PFN_vkVoidFunction>(CmdPipelineBarrier)},
11895593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdBeginQuery", reinterpret_cast<PFN_vkVoidFunction>(CmdBeginQuery)},
11896593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdEndQuery", reinterpret_cast<PFN_vkVoidFunction>(CmdEndQuery)},
11897593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdResetQueryPool", reinterpret_cast<PFN_vkVoidFunction>(CmdResetQueryPool)},
11898593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdCopyQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyQueryPoolResults)},
11899593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdPushConstants", reinterpret_cast<PFN_vkVoidFunction>(CmdPushConstants)},
11900593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdWriteTimestamp", reinterpret_cast<PFN_vkVoidFunction>(CmdWriteTimestamp)},
11901593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCreateFramebuffer", reinterpret_cast<PFN_vkVoidFunction>(CreateFramebuffer)},
11902593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCreateShaderModule", reinterpret_cast<PFN_vkVoidFunction>(CreateShaderModule)},
11903593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCreateRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CreateRenderPass)},
11904593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdBeginRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CmdBeginRenderPass)},
11905593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdNextSubpass", reinterpret_cast<PFN_vkVoidFunction>(CmdNextSubpass)},
11906593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdEndRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CmdEndRenderPass)},
11907593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCmdExecuteCommands", reinterpret_cast<PFN_vkVoidFunction>(CmdExecuteCommands)},
11908593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkSetEvent", reinterpret_cast<PFN_vkVoidFunction>(SetEvent)},
11909593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkMapMemory", reinterpret_cast<PFN_vkVoidFunction>(MapMemory)},
11910593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkUnmapMemory", reinterpret_cast<PFN_vkVoidFunction>(UnmapMemory)},
11911593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkFlushMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(FlushMappedMemoryRanges)},
11912593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkInvalidateMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(InvalidateMappedMemoryRanges)},
11913593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkAllocateMemory", reinterpret_cast<PFN_vkVoidFunction>(AllocateMemory)},
11914593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkFreeMemory", reinterpret_cast<PFN_vkVoidFunction>(FreeMemory)},
11915593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkBindBufferMemory", reinterpret_cast<PFN_vkVoidFunction>(BindBufferMemory)},
11916593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkGetBufferMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(GetBufferMemoryRequirements)},
11917593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkGetImageMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(GetImageMemoryRequirements)},
11918593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkGetQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(GetQueryPoolResults)},
11919593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkBindImageMemory", reinterpret_cast<PFN_vkVoidFunction>(BindImageMemory)},
11920593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkQueueBindSparse", reinterpret_cast<PFN_vkVoidFunction>(QueueBindSparse)},
11921593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCreateSemaphore", reinterpret_cast<PFN_vkVoidFunction>(CreateSemaphore)},
11922593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis        {"vkCreateEvent", reinterpret_cast<PFN_vkVoidFunction>(CreateEvent)},
1192380be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu    };
1192480be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu
1192580be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu    for (size_t i = 0; i < ARRAY_SIZE(core_device_commands); i++) {
1192680be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu        if (!strcmp(core_device_commands[i].name, name))
1192780be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu            return core_device_commands[i].proc;
1192880be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu    }
1192980be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu
1193080be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu    return nullptr;
1193180be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu}
1193280be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu
1193309a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wustatic PFN_vkVoidFunction
1193409a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wuintercept_khr_swapchain_command(const char *name, VkDevice dev) {
1193509a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu    static const struct {
1193609a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu        const char *name;
1193709a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu        PFN_vkVoidFunction proc;
1193809a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu    } khr_swapchain_commands[] = {
1193909a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu        { "vkCreateSwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateSwapchainKHR) },
1194009a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu        { "vkDestroySwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySwapchainKHR) },
1194109a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu        { "vkGetSwapchainImagesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetSwapchainImagesKHR) },
1194209a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu        { "vkAcquireNextImageKHR", reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImageKHR) },
1194309a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu        { "vkQueuePresentKHR", reinterpret_cast<PFN_vkVoidFunction>(QueuePresentKHR) },
1194409a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu    };
11945c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young    layer_data *dev_data = nullptr;
1194609a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu
119473f6f8132355ebdae2736b31fc20de2ac60a70310Chia-I Wu    if (dev) {
11948c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young        dev_data = get_my_data_ptr(get_dispatch_key(dev), layer_data_map);
119493f6f8132355ebdae2736b31fc20de2ac60a70310Chia-I Wu        if (!dev_data->device_extensions.wsi_enabled)
119503f6f8132355ebdae2736b31fc20de2ac60a70310Chia-I Wu            return nullptr;
119513f6f8132355ebdae2736b31fc20de2ac60a70310Chia-I Wu    }
1195209a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu
1195309a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu    for (size_t i = 0; i < ARRAY_SIZE(khr_swapchain_commands); i++) {
1195409a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu        if (!strcmp(khr_swapchain_commands[i].name, name))
1195509a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu            return khr_swapchain_commands[i].proc;
1195609a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu    }
1195709a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu
11958c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young    if (dev_data) {
11959c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young        if (!dev_data->device_extensions.wsi_display_swapchain_enabled)
11960c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young            return nullptr;
11961c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young    }
11962c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young
11963c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young    if (!strcmp("vkCreateSharedSwapchainsKHR", name))
11964c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young        return reinterpret_cast<PFN_vkVoidFunction>(CreateSharedSwapchainsKHR);
11965c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young
1196609a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu    return nullptr;
11967747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
11968747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
11969747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbesstatic PFN_vkVoidFunction
11970747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbesintercept_khr_surface_command(const char *name, VkInstance instance) {
11971747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    static const struct {
11972747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        const char *name;
11973747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        PFN_vkVoidFunction proc;
11974747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        bool instance_layer_data::*enable;
11975747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    } khr_surface_commands[] = {
11976747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_ANDROID_KHR
11977747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        {"vkCreateAndroidSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateAndroidSurfaceKHR),
11978747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes            &instance_layer_data::androidSurfaceExtensionEnabled},
11979747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif // VK_USE_PLATFORM_ANDROID_KHR
11980747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_MIR_KHR
11981747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        {"vkCreateMirSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateMirSurfaceKHR),
11982747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes            &instance_layer_data::mirSurfaceExtensionEnabled},
11983747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif // VK_USE_PLATFORM_MIR_KHR
11984747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WAYLAND_KHR
11985747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        {"vkCreateWaylandSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWaylandSurfaceKHR),
11986747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes            &instance_layer_data::waylandSurfaceExtensionEnabled},
11987747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif // VK_USE_PLATFORM_WAYLAND_KHR
11988747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WIN32_KHR
11989747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        {"vkCreateWin32SurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWin32SurfaceKHR),
11990747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes            &instance_layer_data::win32SurfaceExtensionEnabled},
11991747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif // VK_USE_PLATFORM_WIN32_KHR
11992747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XCB_KHR
11993747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        {"vkCreateXcbSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXcbSurfaceKHR),
11994747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes            &instance_layer_data::xcbSurfaceExtensionEnabled},
11995747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif // VK_USE_PLATFORM_XCB_KHR
11996747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XLIB_KHR
11997747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        {"vkCreateXlibSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXlibSurfaceKHR),
11998747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes            &instance_layer_data::xlibSurfaceExtensionEnabled},
11999747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif // VK_USE_PLATFORM_XLIB_KHR
12000747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        {"vkDestroySurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySurfaceKHR),
12001747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes            &instance_layer_data::surfaceExtensionEnabled},
12002747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    };
12003747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
12004747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    instance_layer_data *instance_data = nullptr;
12005747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    if (instance) {
12006747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        instance_data = get_my_data_ptr(get_dispatch_key(instance), instance_layer_data_map);
12007747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    }
12008747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
12009747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    for (size_t i = 0; i < ARRAY_SIZE(khr_surface_commands); i++) {
12010747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        if (!strcmp(khr_surface_commands[i].name, name)) {
12011747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes            if (instance_data && !(instance_data->*(khr_surface_commands[i].enable)))
12012747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes                return nullptr;
12013747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes            return khr_surface_commands[i].proc;
12014747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        }
12015747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    }
12016747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
12017747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    return nullptr;
1201809a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu}
1201909a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu
12020d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} // namespace core_validation
12021d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu
12022d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu// vk_layer_logging.h expects these to be defined
12023d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu
12024d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuVKAPI_ATTR VkResult VKAPI_CALL
12025d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuvkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
12026d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu                               const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
1202789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu    return core_validation::CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
12028d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu}
12029d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu
12030d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuVKAPI_ATTR void VKAPI_CALL
12031d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuvkDestroyDebugReportCallbackEXT(VkInstance instance,
12032d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu                                VkDebugReportCallbackEXT msgCallback,
12033d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu                                const VkAllocationCallbacks *pAllocator) {
1203489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu    core_validation::DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
12035d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu}
12036d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu
12037d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuVKAPI_ATTR void VKAPI_CALL
12038d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuvkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
12039d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu                        size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
1204089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu    core_validation::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
12041d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu}
12042d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu
12043a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu// loader-layer interface v0, just wrappers since there is only a layer
12044d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu
1204508939232d080c94fc7b4c5ad348644928beb1519Chia-I WuVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1204608939232d080c94fc7b4c5ad348644928beb1519Chia-I WuvkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
12047a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    return core_validation::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
1204808939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu}
1204908939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu
1205008939232d080c94fc7b4c5ad348644928beb1519Chia-I WuVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1205108939232d080c94fc7b4c5ad348644928beb1519Chia-I WuvkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
12052a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    return core_validation::EnumerateInstanceLayerProperties(pCount, pProperties);
1205308939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu}
1205408939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu
1205508939232d080c94fc7b4c5ad348644928beb1519Chia-I WuVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1205608939232d080c94fc7b4c5ad348644928beb1519Chia-I WuvkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
12057a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    // the layer command handles VK_NULL_HANDLE just fine internally
12058a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    assert(physicalDevice == VK_NULL_HANDLE);
12059a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    return core_validation::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
12060d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu}
12061d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu
12062d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
12063d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu                                                                                    const char *pLayerName, uint32_t *pCount,
12064d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu                                                                                    VkExtensionProperties *pProperties) {
12065a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    // the layer command handles VK_NULL_HANDLE just fine internally
12066a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    assert(physicalDevice == VK_NULL_HANDLE);
12067a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu    return core_validation::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
12068d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu}
12069d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu
12070d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
1207189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu    return core_validation::GetDeviceProcAddr(dev, funcName);
12072d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu}
12073d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu
12074d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
1207589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu    return core_validation::GetInstanceProcAddr(instance, funcName);
1207608939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu}
12077